【问题标题】:Why is my Three.js animation slower in Vue.js?为什么我的 Three.js 动画在 Vue.js 中变慢了?
【发布时间】:2019-10-25 13:09:02
【问题描述】:

我正在尝试在 Vue.js 中重新创建这个很棒的波浪模拟:https://codepen.io/cheekymonkey/pen/vMvYNV。但是,当我在 Vue.js 中重新创建动画时,动画真的很慢

我已经尝试制作与 Vue.js 方法相同的所有函数,并将变量包含在组件的数据属性中。

<template>
    <div id="container" style="width:100%; height:100vh;"></div>
</template>

<script>
import * as Three from 'three'
import SimplexNoise from'simplex-noise'

export default {
  name: 'ThreeTest',
  data() {
    return {
      camera: Three.PerspectiveCamera,
      scene: Three.Scene,
      renderer: Three.WebGLRenderer,
      mesh: Three.Mesh,
      noise: SimplexNoise,
      geometry: null,
      factor: 0
    }
  },
  methods: {
    init: function() {
      this.createScene();
      this.createCamera();
      this.createShape();
      this.addSpotlight('#fdffab');
      this.addAmbientLight();
      this.animate();
      window.addEventListener('resize', this.onResize())

    },
    onResize: function() {
      let container = document.getElementById('container');
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.camera.aspect = container.clientWidth / container.clientHeight;
      this.camera.updateProjectionMatrix();
    },
    createScene: function() {
      this.scene = new Three.Scene();
      this.renderer = new Three.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      let container = document.getElementById('container');
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearColor(new Three.Color('#fff'));
      //this.render.shadowMap.type = Three.PCFSoftShadowMap;
      this.noise = new SimplexNoise()
      container.appendChild(this.renderer.domElement);
    },
    createCamera: function() {
      this.camera = new Three.PerspectiveCamera(20, container.clientWidth/container.clientHeight, 1, 1000);
      this.camera.position.set(0, 0, 20);
    },
    createShape: function() {
      const seg = 100
      this.geometry = new Three.PlaneGeometry(5, 8, seg, seg)
      const material = new Three.MeshPhysicalMaterial({
        color: '#da0463',
        metalness: 0.6,
        emissive: '#000',
        side: Three.DoubleSide,
        wireframe: true
      })
      this.mesh = new Three.Mesh(this.geometry, material)
      this.mesh.receiveShadow = true
      this.mesh.castShadow = true
      this.mesh.position.set(0, 0, 0)
      this.mesh.rotation.x = -Math.PI / 3
      this.mesh.rotation.z = -Math.PI / 4
      this.scene.add(this.mesh)
    },
    addSpotlight: function(color) {
      const light = new Three.SpotLight(color, 2, 1000)
      light.position.set(0, 0, 30)
      this.scene.add(light)
    },
    addAmbientLight: function() {
      const light = new Three.AmbientLight('#fff', 0.5)
      this.scene.add(light)
    },
    addjustVertices: function() {
      for (let i = 0; i < this.geometry.vertices.length; i++) {
        const vertex = this.geometry.vertices[i]
        const x = vertex.x / 4
        const y = vertex.y / 6
        vertex.z = this.noise.noise2D(x, y + this.factor)
      }
      this.factor += 0.007
      this.geometry.verticesNeedUpdate = true
      this.geometry.computeVertexNormals()
    },
    animate: function() {
        requestAnimationFrame(this.animate);
        this.addjustVertices();
        this.camera.updateProjectionMatrix();
        this.renderer.render(this.scene, this.camera);
    }
  },
  mounted() {
      this.init();
  }
}
</script>

它可以工作,就像它应该在波浪动画中一样,但它要慢得多。不确定这是由于 Vue.js 还是我是如何设置的。非常感谢任何建议!

【问题讨论】:

  • 当您将它们并排运行时,您能清楚地注意到差异吗?另外,你看到 Vue 开发模式和构建模式的区别了吗?
  • @ThomasvanBroekhoven 我正在经历这种事情,但仅限于开发模式。您是否遇到过这种情况并且已经有了解决方案?

标签: javascript vue.js vuejs2 three.js


【解决方案1】:

之所以发生这种情况,是因为 Vue 在后台使每个附加到实例的组件都具有反应性。 Reactivity in Depth。打开开发工具并查看你的内存占用,当我在我的机器上运行你的 sn-p 时,它大约是 300mb,而 codepen 示例大约是 20mb。

当您console.log(this.scene) 时,您看到的是允许 Vue 跟踪对象的 getter/setter。

下面的 sn -p 将三个.js 对象从 Vue 数据对象中拉出来,并将它们附加到一个 vue-static 对象上。此插件允许您将某些变量设置为非反应性。

<template>
    <div id="container" style="width:100%; height:100vh;"></div>
</template>

<script>
import * as Three from 'three'
import SimplexNoise from'simplex-noise'

export default {
  name: 'ThreeTest',
  static(){
    return {
      scene: new Three.Scene(),
      camera: null,
      renderer: Three.WebGLRenderer,
      mesh: new Three.Mesh,
      noise: SimplexNoise,
      factor:0
    }
  },
  mounted() {
    this.init();
  },
  methods: {
    init: function() {
      this.createScene();
      this.createCamera();
      this.createShape();
      this.addSpotlight('#fdffab');
      this.addAmbientLight();
      this.animate();
      window.addEventListener('resize', this.onResize())
    },
    onResize: function() {
      let container = document.getElementById('container');
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.camera.aspect = container.clientWidth / container.clientHeight;
      this.camera.updateProjectionMatrix();
    },
    createScene: function() {

      console.log("TCL: this.$options.bigHairyHorseNuts ",this.bigHairyHorseNuts)

      this.renderer = new Three.WebGLRenderer({
        antialias: true,
        alpha: true
      });
      let container = document.getElementById('container');
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearColor(new Three.Color('#fff'));
      //this.render.shadowMap.type = Three.PCFSoftShadowMap;
      this.noise = new SimplexNoise()
      container.appendChild(this.renderer.domElement);
    },
    createCamera: function() {
      this.camera = new Three.PerspectiveCamera(20, container.clientWidth/container.clientHeight, 1, 1000);
      this.camera.position.set(0, 0, 20);
    },
    createShape: function() {
      const seg = 100
      this.geometry = new Three.PlaneGeometry(5, 8, seg, seg)
      const material = new Three.MeshPhysicalMaterial({
        color: '#da0463',
        metalness: 0.6,
        emissive: '#000',
        side: Three.DoubleSide,
        wireframe: true
      })
      this.mesh = new Three.Mesh(this.geometry, material)
      this.mesh.receiveShadow = true
      this.mesh.castShadow = true
      this.mesh.position.set(0, 0, 0)
      this.mesh.rotation.x = -Math.PI / 3
      this.mesh.rotation.z = -Math.PI / 4
      this.scene.add(this.mesh)
    },
    addSpotlight: function(color) {
      const light = new Three.SpotLight(color, 2, 1000)
      light.position.set(0, 0, 30)
      this.scene.add(light)
    },
    addAmbientLight: function() {
      const light = new Three.AmbientLight('#fff', 0.5)
      this.scene.add(light)
    },
    addjustVertices: function() {
      for (let i = 0; i < this.geometry.vertices.length; i++) {
        const vertex = this.geometry.vertices[i]
        const x = vertex.x / 4
        const y = vertex.y / 6
        vertex.z = this.noise.noise2D(x, y + this.factor)
      }
      this.factor += 0.007
      this.geometry.verticesNeedUpdate = true
      this.geometry.computeVertexNormals()
    },
    animate: function() {
        requestAnimationFrame(this.animate);
        this.addjustVertices();
        this.camera.updateProjectionMatrix();
        this.renderer.render(this.scene, this.camera);
    }
  }
}
</script>

【讨论】:

  • 或者只是在挂载的生命周期中移动 this.scene = new Three.Scene()
  • 如果您将this.scene 移动到挂载状态,它不会执行,因为 Vue 实例使该对象反应性地膨胀文件大小。考虑到基本情况@wobsoriano,您能否提供一个实现 60fps 的解决方案示例?
  • 呐,如果你认为你是对的,那我就不用提供解决方案了。对我来说额外的知识:)
猜你喜欢
  • 2013-07-24
  • 1970-01-01
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 2012-05-24
  • 1970-01-01
相关资源
最近更新 更多