JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://unpkg.com/[email protected]/build/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>

CSS

body {
  overflow: hidden;
  margin: 0;
}

JavaScript

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 3, 5).setLength(4);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0xffffff);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));

scene.add(new THREE.GridHelper(4, 4));

var geom = new THREE.SphereGeometry(1, 8, 4);

// spikes morphTargets
var spikes = geom.vertices.map(v => {
  return v.clone()
});
spikes[0].y = 2;
spikes[25].y = -2;
spikes[9].x = -2;
spikes[11].z = 2;
spikes[13].x = 2;
spikes[15].z = -2;

geom.morphTargets.push({
  name: "spikes",
  vertices: spikes
});

// heart morphTargets

var heart = geom.vertices.map(v => {
  let tv = v.clone();
  let absX = Math.abs(tv.x * 0.75);
  // reference for the formula of heart: https://www.youtube.com/watch?v=aNR4n0i2ZlM
  tv.y += absX * (Math.sqrt((20 - absX) / 15));
  tv.z *= 0.5;
  tv.x *= 1.2;
  return tv;
});

geom.morphTargets.push({
  name: "heart",
  vertices: heart
});


var mesh = new THREE.Mesh(geom, new THREE.MeshLambertMaterial({
  color: "aqua",
  wireframe: false,
  morphTargets: true,
  transparent: true
}));
scene.add(mesh);

// tweenings

function createTween(influence, start, end, delay, colorStart, colorEnd) {
	let c = colorStart.clone();
  return new TWEEN.Tween({
    val: start,
    r: colorStart.r,
    g: colorStart.g,
    b: colorStart.b
  }).to({
    val: end,
    r: colorEnd.r,
    g: colorEnd.g,
    b: colorEnd.b
  }, 1000).delay(delay).onUpdate(function(value) {
    mesh.morphTargetInfluences[influence] = value.val;
    mesh.rotation.y = value.val * Math.PI * 2;
    mesh.material.color.setRGB(value.r, value.g, value.b);
 ...