为什么立方体并不总是用three.js制作动画 [英] Why cubes do not always animate with three.js

查看:36
本文介绍了为什么立方体并不总是用three.js制作动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,立方体有时随着动画移动,有时没有.我该如何解决?

另外,我应该如何设置旋转速度?

new Vue({el: '#app',数据 () {返回 {相机:空,场景:空,渲染器:空,立方体:空,角度:空}},方法: {初始化:函数(){this.camera = new THREE.PerspectiveCamera(1, 1);this.camera.position.z = 200;//有意义this.scene = new THREE.Scene();this.clock = new THREE.Clock();//this.renderer = new THREE.WebGLRenderer({抗锯齿:真实,阿尔法:真实});let container = document.getElementById('container')this.renderer.setSize(container.offsetWidth, container.offsetHeight);container.appendChild(this.renderer.domElement);让cube2 = this.createCube()cube2.name = "cube2"//cube2.position = new THREE.Vector3(1, 0)this.scene.add(cube2);},createCube: 函数 () {//几何学//1. 从空几何开始让几何 = new THREE.Geometry();//2. 给几何体添加顶点geometry.vertices.push(//顶点 [0-3] 在 +z 中新三.Vector3(-1, 1, 1),新三.Vector3(-1, -1, 1),新三.Vector3(1, -1, 1),新三.Vector3(1, 1, 1),//在 -z 中翻转 [4-7]新三.Vector3(-1, 1, -1),new THREE.Vector3(-1, -1, -1),new THREE.Vector3(1, -1, -1),新三.Vector3(1, 1, -1),);//3. 按所需顺序连接顶点以制作面让 b = 0x1db0ec让 y = 0xffef3a让 r = 0xea353d让 w = 0xffffff//设置半面geometry.faces.push(new THREE.Face3(0, 1, 2));//蓝色geometry.faces.push(new THREE.Face3(0, 2, 3));//黄色geometry.faces.push(new THREE.Face3(5, 4, 6));//白色的geometry.faces.push(new THREE.Face3(6, 4, 7));//红色的//设置全脸geometry.faces.push(new THREE.Face3(1, 0, 5));//蓝色geometry.faces.push(new THREE.Face3(5, 0, 4));geometry.faces.push(new THREE.Face3(1, 5, 2));//白色的geometry.faces.push(new THREE.Face3(5, 6, 2));geometry.faces.push(new THREE.Face3(2, 6, 3));//红色的geometry.faces.push(new THREE.Face3(3, 6, 7));geometry.faces.push(new THREE.Face3(0, 3, 4));//黄色geometry.faces.push(new THREE.Face3(3, 7, 4));//设置人脸颜色geometry.faces[0].color.setHex(b);//半脸geometry.faces[1].color.setHex(y);geometry.faces[2].color.setHex(w);geometry.faces[3].color.setHex(r);geometry.faces[4].color.setHex(b);//整张脸geometry.faces[5].color.setHex(b);geometry.faces[6].color.setHex(w);geometry.faces[7].color.setHex(w);geometry.faces[8].color.setHex(r);geometry.faces[9].color.setHex(r);geometry.faces[10].color.setHex(y);geometry.faces[11].color.setHex(y);//材料//制作材质让材料 = 新的 THREE.MeshBasicMaterial({//颜色:0x00FF00,顶点颜色:THREE.FaceColors,线框:假,});//网let cube = new THREE.Mesh(geometry, material);返回立方体},旋转到:功能(面){如果(脸=='黄色')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI/2, Math.PI/2));否则如果(脸=='红色')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI/2, 0, Math.PI/2));否则如果(脸=='蓝色')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI/2, 0, - Math.PI/2));否则如果(脸=='白')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(- Math.PI/2, Math.PI/2, 0));否则如果(脸=='yb')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));否则如果(脸=='rw')this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI, 0, 0));this.animate()},动画:函数(){让 id = requestAnimationFrame(this.animate);让 delta = this.clock.getDelta();this.scene.children[0].quaternion.rotateTowards(this.angle, Math.PI * delta);this.renderer.render(this.scene, this.camera);如果 (this.scene.children[0].quaternion.equals(this.angle)) {取消动画帧(id)}}},挂载(){this.init();this.renderer.render(this.scene, this.camera);}})

#container {背景色:#aaa;宽度:20em;高度:20em;}

<script src="https://unpkg.com/vue"></script><script src="https://threejs.org/build/three.min.js"></script><div id="应用程序"><div><button v-on:click="rotateTo('yellow')">黄色</button><button v-on:click="rotateTo('red')">red</button><button v-on:click="rotateTo('blue')">blue</button><button v-on:click="rotateTo('white')">white</button><button v-on:click="rotateTo('yb')">黄色/蓝色</button><button v-on:click="rotateTo('rw')">红/白</button>

<div id="容器"></div>

更新

代码仅隔离到 Threejs 部分.

var camera = null;var 场景 = null;var 渲染器 = null;var 立方体 = 空;var 角度 = 空;在里面();renderer.render(场景,相机);函数初始化(){相机=新三.透视相机(1,1);相机.位置.z = 200;//有意义场景 = 新的 THREE.Scene();时钟 = 新的 THREE.Clock();//渲染器 = 新的 THREE.WebGLRenderer({抗锯齿:真实,阿尔法:真实});let container = document.getElementById('container');renderer.setSize(container.offsetWidth, container.offsetHeight);container.appendChild(renderer.domElement);让cube2 = createCube();cube2.name = "cube2";//cube2.position = new THREE.Vector3(1, 0)场景.添加(立方体2);}函数 createCube() {//几何学//1. 从空几何开始让几何 = new THREE.Geometry();//2. 给几何体添加顶点geometry.vertices.push(//顶点 [0-3] 在 +z 中新三.Vector3(-1, 1, 1),新三.Vector3(-1, -1, 1),新三.Vector3(1, -1, 1),新三.Vector3(1, 1, 1),//在 -z 中翻转 [4-7]新三.Vector3(-1, 1, -1),new THREE.Vector3(-1, -1, -1),new THREE.Vector3(1, -1, -1),新三.Vector3(1, 1, -1),);//3. 按所需顺序连接顶点以制作面让 b = 0x1db0ec;让 y = 0xffef3a;让 r = 0xea353d;让 w = 0xffffff;//设置半面geometry.faces.push(new THREE.Face3(0, 1, 2));//蓝色geometry.faces.push(new THREE.Face3(0, 2, 3));//黄色geometry.faces.push(new THREE.Face3(5, 4, 6));//白色的geometry.faces.push(new THREE.Face3(6, 4, 7));//红色的//设置全脸geometry.faces.push(new THREE.Face3(1, 0, 5));//蓝色geometry.faces.push(new THREE.Face3(5, 0, 4));geometry.faces.push(new THREE.Face3(1, 5, 2));//白色的geometry.faces.push(new THREE.Face3(5, 6, 2));geometry.faces.push(new THREE.Face3(2, 6, 3));//红色的geometry.faces.push(new THREE.Face3(3, 6, 7));geometry.faces.push(new THREE.Face3(0, 3, 4));//黄色geometry.faces.push(new THREE.Face3(3, 7, 4));//设置人脸颜色geometry.faces[0].color.setHex(b);//半脸geometry.faces[1].color.setHex(y);geometry.faces[2].color.setHex(w);geometry.faces[3].color.setHex(r);geometry.faces[4].color.setHex(b);//整张脸geometry.faces[5].color.setHex(b);geometry.faces[6].color.setHex(w);geometry.faces[7].color.setHex(w);geometry.faces[8].color.setHex(r);geometry.faces[9].color.setHex(r);geometry.faces[10].color.setHex(y);geometry.faces[11].color.setHex(y);//材料//制作材质让材料 = 新的 THREE.MeshBasicMaterial({//颜色:0x00FF00,顶点颜色:THREE.FaceColors,线框:假,});//网let cube = new THREE.Mesh(geometry, material);返回立方体;}函数旋转到(脸){如果(脸=='黄色')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI/2, Math.PI/2));否则如果(脸=='红色')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI/2, 0, Math.PI/2));否则如果(脸=='蓝色')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI/2, 0, -Math.PI/2));否则如果(脸=='白')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(-Math.PI/2, Math.PI/2, 0));否则如果(脸=='yb')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));否则如果(脸=='rw')角度 = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI, 0, 0));动画();}函数动画(){让 id = requestAnimationFrame(animate);让 delta = clock.getDelta();scene.children[0].quaternion.rotateTowards(angle, Math.PI * delta);renderer.render(场景,相机);如果 (scene.children[0].quaternion.equals(angle)) {取消动画帧(id);}}

#container {背景色:#aaa;宽度:20em;高度:20em;}

<script src="https://threejs.org/build/three.min.js"></script><div><button onclick="rotateTo('yellow')">黄色</button><button onclick="rotateTo('red')">red</button><button onclick="rotateTo('blue')">blue</button><button onclick="rotateTo('white')">white</button><button onclick="rotateTo('yb')">黄色/蓝色</button><button onclick="rotateTo('rw')">红/白</button>

<div id="container"></div>

解决方案

动画不播放的原因是因为当你cancelAnimationFrame时时钟还在运行,所以下次你调用rotateTo delta 太高以至于动画立即结束.

您可以通过使用 cancelAnimationFrame 停止时钟来避免这种情况,并在调用 rotateTo 时重新启动它,如下所示:

function rotateTo(face) {时钟.开始()...}

function animate() {...如果 (scene.children[0].quaternion.equals(angle)) {取消动画帧(id);时钟停止()}}

至于旋转速度,rotateTowards 的第二个参数是 step,它决定了它到达那里的速度.所以如果你给它添加一个修饰符var,你就可以控制速度.

let rotSpeedMotifier = 0.2//越高越快scene.children[0].quaternion.rotateTowards(angle, Math.PI * delta * rotSpeedMotifier);

In the code below, cubes sometimes move with animation and sometimes without. How can I fix it ?

Also, how should I set rotation speed ?

new Vue({
  el: '#app',
  data () {
    return {
      camera: null,
      scene: null,
      renderer: null,
      cube: null,
      angle: null
    }
  },
  methods: {
    init: function () {

      this.camera = new THREE.PerspectiveCamera(1, 1);
      this.camera.position.z = 200;

      // Make a scene
      this.scene = new THREE.Scene();

      this.clock = new THREE.Clock();

      //
      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      let container = document.getElementById('container')
      this.renderer.setSize(container.offsetWidth, container.offsetHeight);
      container.appendChild(this.renderer.domElement);

      let cube2 = this.createCube()
      cube2.name = "cube2"
      //       cube2.position = new THREE.Vector3(1, 0)
      this.scene.add(cube2);

    },
    createCube: function () {

      // GEOMETRY

      // 1. Start with empty geometry
      let geometry = new THREE.Geometry();

      // 2. Add vertices to geometry
      geometry.vertices.push(
        // verts [0-3] are in in +z
        new THREE.Vector3(-1, 1, 1),
        new THREE.Vector3(-1, -1, 1),
        new THREE.Vector3(1, -1, 1),
        new THREE.Vector3(1, 1, 1),
        // verts [4-7] in -z
        new THREE.Vector3(-1, 1, -1),
        new THREE.Vector3(-1, -1, -1),
        new THREE.Vector3(1, -1, -1),
        new THREE.Vector3(1, 1, -1),
      );

      // 3. Connect vertices in desired order to make faces
      let b = 0x1db0ec
      let y = 0xffef3a
      let r = 0xea353d
      let w = 0xffffff

      // Set half faces
      geometry.faces.push(new THREE.Face3(0, 1, 2)); // blue
      geometry.faces.push(new THREE.Face3(0, 2, 3)); // yellow
      geometry.faces.push(new THREE.Face3(5, 4, 6)); // white
      geometry.faces.push(new THREE.Face3(6, 4, 7)); // red

      // Set whole faces
      geometry.faces.push(new THREE.Face3(1, 0, 5)); // blue
      geometry.faces.push(new THREE.Face3(5, 0, 4));
      geometry.faces.push(new THREE.Face3(1, 5, 2)); // white
      geometry.faces.push(new THREE.Face3(5, 6, 2));
      geometry.faces.push(new THREE.Face3(2, 6, 3)); // red
      geometry.faces.push(new THREE.Face3(3, 6, 7));
      geometry.faces.push(new THREE.Face3(0, 3, 4)); // yellow
      geometry.faces.push(new THREE.Face3(3, 7, 4));

      // Set faces colors
      geometry.faces[0].color.setHex(b); // Half face
      geometry.faces[1].color.setHex(y);
      geometry.faces[2].color.setHex(w);
      geometry.faces[3].color.setHex(r);
      geometry.faces[4].color.setHex(b); // Whole face
      geometry.faces[5].color.setHex(b);
      geometry.faces[6].color.setHex(w);
      geometry.faces[7].color.setHex(w);
      geometry.faces[8].color.setHex(r);
      geometry.faces[9].color.setHex(r);
      geometry.faces[10].color.setHex(y);
      geometry.faces[11].color.setHex(y);

      // MATERIAL

      // Make a material
      let material = new THREE.MeshBasicMaterial({
        // color: 0x00FF00,
        vertexColors: THREE.FaceColors,
        wireframe: false,
      });

      // MESH

      let cube = new THREE.Mesh(geometry, material);
      return cube
    },
    rotateTo: function (face) {

      if (face == 'yellow')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI / 2, Math.PI / 2));
      else if (face == 'red')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, Math.PI / 2));
      else if (face == 'blue')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, - Math.PI / 2));
      else if (face == 'white')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(- Math.PI / 2, Math.PI / 2, 0));
      else if (face == 'yb')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));
      else if (face == 'rw')
        this.angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI, 0, 0));

      this.animate()

    },
    animate: function () {

      let id = requestAnimationFrame(this.animate);

      let delta = this.clock.getDelta();
      this.scene.children[0].quaternion.rotateTowards(this.angle, Math.PI * delta);

      this.renderer.render(this.scene, this.camera);

      if (this.scene.children[0].quaternion.equals(this.angle)) {
        cancelAnimationFrame(id)
      }

    }
  },
  mounted () {
    this.init();
    this.renderer.render(this.scene, this.camera);
  }
})

#container {
  background-color: #aaa;
  width: 20em;
  height: 20em;
}

<script src="https://unpkg.com/vue"></script>
<script src="https://threejs.org/build/three.min.js"></script>

<div id="app">
    <div>
      <button v-on:click="rotateTo('yellow')">yellow</button>
      <button v-on:click="rotateTo('red')">red</button>
      <button v-on:click="rotateTo('blue')">blue</button>
      <button v-on:click="rotateTo('white')">white</button>
      <button v-on:click="rotateTo('yb')">yellow/blue</button>
      <button v-on:click="rotateTo('rw')">red/white</button>
    </div>

    <div id="container"></div>
</div>

UPDATE

Code isolated to only the threejs portion.

var camera = null;
var scene = null;
var renderer = null;
var cube = null;
var angle = null;

init();
renderer.render(scene, camera);

function init() {

	camera = new THREE.PerspectiveCamera(1, 1);
	camera.position.z = 200;

	// Make a scene
	scene = new THREE.Scene();

	clock = new THREE.Clock();

	//
	renderer = new THREE.WebGLRenderer({
		antialias: true,
		alpha: true
	});
	let container = document.getElementById('container');
	renderer.setSize(container.offsetWidth, container.offsetHeight);
	container.appendChild(renderer.domElement);

	let cube2 = createCube();
	cube2.name = "cube2";
	//       cube2.position = new THREE.Vector3(1, 0)
	scene.add(cube2);

}

function createCube() {

	// GEOMETRY

	// 1. Start with empty geometry
	let geometry = new THREE.Geometry();

	// 2. Add vertices to geometry
	geometry.vertices.push(
		// verts [0-3] are in in +z
		new THREE.Vector3(-1, 1, 1),
		new THREE.Vector3(-1, -1, 1),
		new THREE.Vector3(1, -1, 1),
		new THREE.Vector3(1, 1, 1),
		// verts [4-7] in -z
		new THREE.Vector3(-1, 1, -1),
		new THREE.Vector3(-1, -1, -1),
		new THREE.Vector3(1, -1, -1),
		new THREE.Vector3(1, 1, -1),
	);

	// 3. Connect vertices in desired order to make faces
	let b = 0x1db0ec;
	let y = 0xffef3a;
	let r = 0xea353d;
	let w = 0xffffff;

	// Set half faces
	geometry.faces.push(new THREE.Face3(0, 1, 2)); // blue
	geometry.faces.push(new THREE.Face3(0, 2, 3)); // yellow
	geometry.faces.push(new THREE.Face3(5, 4, 6)); // white
	geometry.faces.push(new THREE.Face3(6, 4, 7)); // red

	// Set whole faces
	geometry.faces.push(new THREE.Face3(1, 0, 5)); // blue
	geometry.faces.push(new THREE.Face3(5, 0, 4));
	geometry.faces.push(new THREE.Face3(1, 5, 2)); // white
	geometry.faces.push(new THREE.Face3(5, 6, 2));
	geometry.faces.push(new THREE.Face3(2, 6, 3)); // red
	geometry.faces.push(new THREE.Face3(3, 6, 7));
	geometry.faces.push(new THREE.Face3(0, 3, 4)); // yellow
	geometry.faces.push(new THREE.Face3(3, 7, 4));

	// Set faces colors
	geometry.faces[0].color.setHex(b); // Half face
	geometry.faces[1].color.setHex(y);
	geometry.faces[2].color.setHex(w);
	geometry.faces[3].color.setHex(r);
	geometry.faces[4].color.setHex(b); // Whole face
	geometry.faces[5].color.setHex(b);
	geometry.faces[6].color.setHex(w);
	geometry.faces[7].color.setHex(w);
	geometry.faces[8].color.setHex(r);
	geometry.faces[9].color.setHex(r);
	geometry.faces[10].color.setHex(y);
	geometry.faces[11].color.setHex(y);

	// MATERIAL

	// Make a material
	let material = new THREE.MeshBasicMaterial({
		// color: 0x00FF00,
		vertexColors: THREE.FaceColors,
		wireframe: false,
	});

	// MESH

	let cube = new THREE.Mesh(geometry, material);
	return cube;
}

function rotateTo(face) {

	if (face == 'yellow')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI / 2, Math.PI / 2));
	else if (face == 'red')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, Math.PI / 2));
	else if (face == 'blue')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, -Math.PI / 2));
	else if (face == 'white')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(-Math.PI / 2, Math.PI / 2, 0));
	else if (face == 'yb')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0));
	else if (face == 'rw')
		angle = new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI, 0, 0));

	animate();

}

function animate() {

	let id = requestAnimationFrame(animate);

	let delta = clock.getDelta();
	scene.children[0].quaternion.rotateTowards(angle, Math.PI * delta);

	renderer.render(scene, camera);

	if (scene.children[0].quaternion.equals(angle)) {
		cancelAnimationFrame(id);
	}

}

#container {
      background-color: #aaa;
      width: 20em;
      height: 20em;
    }

<script src="https://threejs.org/build/three.min.js"></script>

        <div>
          <button onclick="rotateTo('yellow')">yellow</button>
          <button onclick="rotateTo('red')">red</button>
          <button onclick="rotateTo('blue')">blue</button>
          <button onclick="rotateTo('white')">white</button>
          <button onclick="rotateTo('yb')">yellow/blue</button>
          <button onclick="rotateTo('rw')">red/white</button>
        </div>

        <div id="container"></div>

解决方案

The reason for the animation not playing is because when you cancelAnimationFrame the clock is still running, so the next time you call rotateTo the delta is so high that the animation ends immediately.

you can avoid this by stopping the clock with cancelAnimationFrame, and start it again when calling rotateTo as follows:

function rotateTo(face) {
  clock.start()
  ...
}

function animate() {
    ...
    if (scene.children[0].quaternion.equals(angle)) {
        cancelAnimationFrame(id);
        clock.stop()
    }
}

as for rotation speed, the 2nd arg of rotateTowards is step, which determines how fast will it get there. So if you add a modifier var to it, you can control the speed.

let rotSpeedMotifier = 0.2 // the higher the faster
scene.children[0].quaternion.rotateTowards(angle, Math.PI * delta * rotSpeedMotifier );

这篇关于为什么立方体并不总是用three.js制作动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆