function* sleep(milliseconds) {yield milliseconds};
function runSleepyTask(task) {
(function wakeup() {
var result = task.next();
if (!result.done) setTimeout(wakeup, result.value);
})()
}
pen3D =setup3D();
var taskObject = new drawTree(pen3D.center, 5);
runSleepyTask(taskObject);
function* drawTree(root3D, size) {
if (size < 2) runSleepyTask(new growLeaf(root3D))
else {
pen3D.drawTrunk(root3D, size);
for (var p of [1, 3, 5]) {
var part3D = new pen3D.Thing;
root3D.add(part3D);
part3D.move(size).turn(p).tilt(1-p/20);
yield* sleep(50);
yield* drawTree(part3D, (0.7+p/40)*size);
}
}
}
function* growLeaf(stem3D) {
var leaf3D = pen3D.drawLeaf(stem3D);
for (var s=0;s++<15;) {yield* sleep(100); leaf3D.scale.multiplyScalar(1.1)}
yield* sleep( 1000 + 9000*Math.random() );
for (var c=0;c++<30;) {yield* sleep(200); leaf3D.skin.color.setRGB(c/30, 1-c/40, 0)}
for (var m=0;m++<90;) {yield* sleep( 50); leaf3D.turn(0.4).tilt(0.3).move(2)}
leaf3D.visible = false;
}
///////////////////////////////////////////////////////////////////////
function setup3D() {
var scene, camera, renderer, diretionalLight, pen3D;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75,
window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 15, 20);
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
directionalLight = new THREE.DirectionalLight(0xffffaa, 0.7);
directionalLight.position.set(-1, 2, 1);
scene.add(directionalLight);
scene.add(new THREE.AmbientLight(0x9999ff));
(function render() {
requestAnimationFrame(render);
// renderer.setSize( window.innerWidth, window.innerHeight );
scene.rotateY(10/60/60);
renderer.render(scene, camera);
})();
window.addEventListener(
'resize',
function(){
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
},
false
);
pen3D = {
drawTrunk: function(root, size) {
// root.skin = skin(0.5, 0.3, 0.2);
root.add(new THREE.Mesh(new THREE.CylinderGeometry(size/12, size/10, size, 16),
root.skin).translateY(size/2));
root.add(new THREE.Mesh(new THREE.SphereGeometry(size/12, 16),
root.skin).translateY(size));
return root;
},
drawLeaf: function(stem) {
stem.skin.color.setRGB(0, 1, 0);
stem.add(new THREE.Mesh(new THREE.CylinderGeometry(0, 0.02, 0.6),
stem.skin) .rotateX(0.3).translateY(0.3));
stem.add(new THREE.Mesh(new THREE.CircleGeometry(0.2),
stem.skin) .rotateX(0.3).translateY(0.4));
return stem;
},
Thing: function() {
THREE.Object3D.call(this);
this.skin = new THREE.MeshLambertMaterial({
color: new THREE.Color(0.5, 0.3, 0.2),
vertexColors: THREE.FaceColors,
side: THREE.DoubleSide
})
}
};
pen3D.Thing.prototype = Object.create(THREE.Object3D.prototype);
pen3D.Thing.prototype.tilt = pen3D.Thing.prototype.rotateX;
pen3D.Thing.prototype.turn = pen3D.Thing.prototype.rotateY;
pen3D.Thing.prototype.move = pen3D.Thing.prototype.translateY;
pen3D.center = new pen3D.Thing;
scene.add(pen3D.center);
return pen3D;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r71/three.min.js"></script>
sleep()
来计时动画。(我知道有更好的方法...)提问者提供的代码在 Chrome 中对我无效,因为浏览器不会在脚本中进行修改后立即更新 DOM,而是等待代码执行完成后再进行任何 DOM 更新,因此脚本会等待所有延迟的总和,然后一次性应用所有 DOM 更新。 - Ari Fordsham