【问题标题】:Three.js call function every second not frame三.js每秒调用函数不帧
【发布时间】:2019-04-28 02:37:48
【问题描述】:

我有一个向量数组。我想像这样使用这些数组向量移动对象:

animate() {

this.lorryBounds.forEach(vector => {
  this.sceneManager.boxes[0].position.set(vector)
})

this.renderer.render(this.scene, this.camera)
this.frameId = window.requestAnimationFrame(this.animate)

}

但我每秒钟都在努力做到这一点,而不是帧。我阅读了很多问题并没有找到解决方案。我已经尝试过 THREE.Clock() 和 deltaTime()。有一种方法 requestAnimationFrame,但我不明白如何在 React.js 中使用它。我的文件是:

    import React, { Component } from 'react'
import * as THREE from 'three'
import {SceneManager} from '../Three/SceneManager'
import Box from '../Models/Box'

class Scene extends Component {
  constructor(props) {
    super(props)

    this.start = this.start.bind(this)
    this.animate = this.animate.bind(this)
    this.Update = this.Update.bind(this)

  }

  componentDidMount() {

    const sceneManager = new SceneManager();
          sceneManager.setupLorry();
          sceneManager.calculateLorryBounds()

    const lorry = sceneManager.lorry
    const lorryBounds = sceneManager.lorryBounds


    const width = this.mount.clientWidth;
    const height = this.mount.clientHeight;

    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 1000);
          camera.position.z = 20;

    const renderer = new THREE.WebGLRenderer({ antialias: true });
          renderer.setClearColor('#ffffff');
          renderer.setSize(width, height);

    //instantiate boxes
    var boxes = []
    boxes.push(new Box(1,1,1))
    boxes.push(new Box(1,2,1))
    boxes.push(new Box(2,1,1))

    sceneManager.createBoxesFromParams(boxes)
    sceneManager.boxes.forEach(element => {
      scene.add(element)
    })

    //sceneManager.boxes[0].position.set(5,-2,2)
    //console.log(sceneManager.boxes[0].position)


    scene.add(lorry);
    //get bounds
    lorry.geometry.computeBoundingBox()

    console.log(lorry.geometry.boundingBox.max)
    console.log("min bounding box : " )

    lorryBounds.forEach( vector => {
      setTimeout(() => {
        console.log(sceneManager.boxes[0].position.set(vector))
      }, 2000);

    })
    //const geometry = new THREE.BoxGeometry(10, 2, 2)
    //const geometry2 = new THREE.BoxGeometry(5, 1, 1)
    //var mat = new THREE.LineBasicMaterial( { color: 0xff2fff, linewidth: 2 } );
    //var material = new THREE.MeshBasicMaterial({color: '#FF2222'})
    //var cube = new THREE.Mesh(geometry2, material);
    //const edges = new THREE.EdgesGeometry(geometry)
    //var wireframe3 = new THREE.LineSegments( edges, mat );
    //var pivotPoint = new THREE.Object3D();



    //scene.add(wireframe3)


    //cube.add(pivotPoint);
    //scene.add(cube);



    this.scene = scene
    this.camera = camera
    this.renderer = renderer
    this.sceneManager = sceneManager
    this.lorryBounds = lorryBounds
    this.clock = new THREE.Clock();
    this.time = 0;
    this.delta = 0;
    this.speed = 1000; // units a second - 2 seconds
    this.last = 0

    this.mount.appendChild(this.renderer.domElement)
    this.start()
  }

  componentWillUnmount() {
    cancelAnimationFrame(this.frameId)
    this.mount.removeChild(this.renderer.domElement)
  }

  start() {
    if (!this.frameId) {
      this.frameId = requestAnimationFrame(this.animate)
    }
  }

  animate() {

    this.lorryBounds.forEach(vector => {
      this.sceneManager.boxes[0].position.set(vector)
    })

    this.renderer.render(this.scene, this.camera)
    this.frameId = window.requestAnimationFrame(this.animate)

  }

  render() {
    return (
      <div
        style={{ width: '100%', height: '800px' }}
        ref={(mount) => { this.mount = mount }}
      />
    )
  }
}

export default Scene

【问题讨论】:

    标签: reactjs animation three.js frame


    【解决方案1】:

    您可以使用一些throttle 函数每秒只执行一次函数,而您的帧速率要高得多。 (https://www.npmjs.com/package/throttle-debounce)

    var setBoxPosition = throttle(1000, function () {
        this.lorryBounds.forEach(vector => {
            this.sceneManager.boxes[0].position.set(vector)
        });
    });
    
    function animate() {
    
        setBoxPosition();
    
        this.renderer.render(this.scene, this.camera)
        this.frameId = window.requestAnimationFrame(this.animate)
    }
    

    或者你可以使用window.setInterval方法:https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

    更新

    如果您想每秒应用一个向量迭代向量数组,您可以执行以下操作:

    var currentIndex = 0;
    var intervalID;
    
    function setBoxPosition() {
    
      this.sceneManager.boxes[0].position.set( this.lorryBounds[currentIndex] );
    
      if (currentIndex < this.lorryBounds.length - 1) {
        currentIndex++;
      }
      else {
        clearInterval(intervalID);
      }
    }
    
    function start() {
      if (!this.frameId) {
        this.frameId = requestAnimationFrame(this.animate)
      }
    
      intervalID = setInterval(setBoxPosition, 1000);
    }
    
    function animate() {
      this.renderer.render(this.scene, this.camera)
      this.frameId = window.requestAnimationFrame(this.animate)
    }
    

    【讨论】:

    • 您好,我使用了 setInterval,但它不起作用。它会在每个时间间隔触发所有迭代。
    • 那么,您想为boxes[0] 每秒设置一个向量吗?我不确定,因为我只是从你用油门包裹的代码中复制了一小段代码。
    • 是的,我花了 6 个小时试图做到这一点……太复杂了
    • 好吧,animate() 函数中根本没有调用油门
    • 我用setInterval 更新了我的答案。也许这就是您希望它工作的方式。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2023-03-26
    • 2019-08-29
    • 2011-11-06
    • 2018-01-26
    • 2011-03-09
    • 2014-12-24
    相关资源
    最近更新 更多