为什么多维数据集不总是与Three.js关联

时间:2019-12-30 03:50:03

标签: three.js

在下面的代码中,多维数据集有时随动画一起移动,有时不随动画一起移动。我该如何解决?

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

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>

更新

仅隔离到threejs部分的代码。

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>

1 个答案:

答案 0 :(得分:2)

动画不播放的原因是,当您cancelAnimationFrame时钟仍在运行时,因此下次调用rotateTo时,增量如此之高,动画立即结束。

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

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

关于转速,rotateTowards的第二个arg是step,它确定到达那里的速度。因此,如果向其添加修饰符var,则可以控制速度。

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