描述这个问题的最好方法是签出JSFiddle。当你试图移动鼠标或做任何事情时,动画将非常不稳定。我已经把它缩小到与class This . requestanimationframe (This .animation)有关,这一开始不起作用,但是在stackoverflow上看了之后,我发现了一个修复说this.animate = this.animate.bind(this);
,这使它工作,但非常慢!我怎样才能使这个更快,同时保留类?
JSFiddle:
https://jsfiddle.net/gentleman_goat66/o5wn3bpf/100/
下面是我的代码: HTML
<script type="importmap">
{
"imports":
{
"three": "https://unpkg.com/three@0.151.3/build/three.module.js",
"OrbitControls": "https://unpkg.com/three@0.151.3/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<div id="container">
</div>
JS
import * as THREE from 'three';
import { OrbitControls } from 'OrbitControls';
class Heatmap {
constructor(){
console.log("Heatmap - constructor()");
//ThreeJS Variables
this.camera = null;
this.scene = null;
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.orbital_controls = null;
this.ambientLight = null;
this.heatmap = new THREE.Object3D(); //This will hold all the meshes that make up the heatmap
this.animate = this.animate.bind(this);
//Animation Related Variables
this.clock = new THREE.Clock();
this.delta = 0;
this.fps = 60; //60 fps
this.interval = 1;
this.seconds = 2; //seconds for animation
this.timeSoFar = 0;
this.targetTime = 3;
//Setup
this.scene = new THREE.Scene();
this.setUpCamera();
this.setUpRenderer();
this.setUpLighting();
this.setUpOrbitalControls();
//Add optional GridHelper for Debug
this.scene.add(new THREE.GridHelper());
//TODO: Create the heatmap here
this.createDataRectangle();
//Add the finished heatmap to the scene
this.scene.add(this.heatmap);
this.render();
this.animate();
}
setUpRenderer(){
console.log("Heatmap - setUpRenderer()");
let width = $('#container').width();
let height = $('#container').height();
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(width,height);
this.renderer.setClearColor(0x404040);
$("#container").html(this.renderer.domElement);
window.addEventListener("resize", event => {
this.camera.aspect = innerWidth / innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(innerWidth, innerHeight);
});
}
setUpCamera(){
console.log("Heatmap - setUpCamera()");
this.camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 100);
this.camera.position.z = 4;
}
setUpLighting(){
console.log("Heatmap - setUpLighting()");
this.ambientLight = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(this.ambientLight);
}
setUpOrbitalControls(){
console.log("Heatmap - setUpOrbitalControls()");
this.orbital_controls = new OrbitControls( this.camera, this.renderer.domElement );
this.orbital_controls.target.set(0, 0, 0);
this.orbital_controls.enableDamping = true;
this.orbital_controls.dampingFactor = 0.025;
this.orbital_controls.maxPolarAngle = Math.PI/2.0;
this.orbital_controls.minDistance = 2.0;
this.orbital_controls.maxDistance = 80.0;
this.orbital_controls.update();
this.orbital_controls.addEventListener( 'change', function(){
if (this.target.y < 0){
this.target.y = 0;
/* camera.position.y = -1; */
} else if (this.target.y > 1){
this.target.y = 1;
/* camera.position.y = 1; */
}
});
}
createDataRectangle(){ //TODO: Make this create at a position specified
console.log("Heatmap - createDataRectangle()");
const geometry = new THREE.BufferGeometry();
const vertices = [
-2, 0, 1,//0, floor, bottom left
-1, 0, 1,//1, floor, bottom right
-1, 0, -1,//2, floor, top right
-2, 0, -1,//3 floor, top left
-2, 0, 1,//4 roof, bottom left
-1, 0, 1,//5 roof, bottom right
-1, 0, -1,//6 roof, top right
-2, 0, -1//7 roof, top left
];
const indices = [
0, 1, 2,//floor, first triangle
2, 3, 0,//floor, second triangle
4, 5, 6,//roof, first triangle
6, 7, 4,//roof, second triangle
3, 0, 4,//west wall, first triangle
3, 4, 7,//west wall, second triangle
0, 1, 5,//south wall, first triangle
0, 5, 4,//south wall, first triangle
1, 2, 6,//east wall, first triangle
1, 6, 5,//east wall, second triangle
2, 3, 7,//north wall, first triangle
2, 7, 6,//north wall, second triangle
];
const colors = [
2,0,0, // bottom left
0,2,0, // bottom right
0,2,0, // top right
2,0,0, // top left
2,0,0, // bottom left
0,2,0, // bottom right
0,2,0, // top right
2,0,0 // top left
];
geometry.setIndex(indices);
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.computeVertexNormals();
const material = new THREE.MeshStandardMaterial({side:THREE.FrontSide,vertexColors:true,color: 0xFFFFFF });
const sample_rectangle = new THREE.Mesh(geometry, material);
this.heatmap.add(sample_rectangle);
}
animate(){
requestAnimationFrame( this.animate);
this.orbital_controls.update();//Required for Damping on OrbitControls
this.delta += this.clock.getDelta();
if (this.delta > this.interval) {
//this.timeSoFar = this.timeSoFar + (1 * morphDirection);
this.render();
this.delta = this.delta % this.interval;
}
}
render(){
this.renderer.render(this.scene, this.camera);
}
}
$(document).ready(function(){
console.log("DOM ready!");
new Heatmap();
});
CSS
body,html{
margin: 0;
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
background-color: black;
margin: 0;
}
我不知道你在期待什么
this.delta += this.clock.getDelta();
if (this.delta > this.interval) {
部分就可以了。但这是你的问题,这里的this.interval = 1
意味着if
块中的部分每秒只执行一次。
也许你想限制一些帧,在这种情况下你应该有this.interval = 1 / this.fps;
但我看不出一个好的理由这样做,因为限制固定FPS很难得到正确的(你必须选择一个多个主动监控本地的刷新率,<子>和可变利率监测…子>)
所以最好的可能是完全摆脱这种检查和运行监控和浏览器一样快愿意走。
body,html{
margin: 0;
width: 100%;
height: 100%;
}
#container {
width: 100%;
height: 100%;
background-color: black;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="importmap">
{
"imports":
{
"three": "https://unpkg.com/three@0.151.3/build/three.module.js",
"OrbitControls": "https://unpkg.com/three@0.151.3/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<div id="container">
</div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'OrbitControls';
class Heatmap {
constructor(){
console.log("Heatmap - constructor()");
//ThreeJS Variables
this.camera = null;
this.scene = null;
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.orbital_controls = null;
this.ambientLight = null;
this.heatmap = new THREE.Object3D(); //This will hold all the meshes that make up the heatmap
this.animate = this.animate.bind(this);
this.seconds = 2; //seconds for animation
this.timeSoFar = 0;
this.targetTime = 3;
//Setup
this.scene = new THREE.Scene();
this.setUpCamera();
this.setUpRenderer();
this.setUpLighting();
this.setUpOrbitalControls();
//Add optional GridHelper for Debug
this.scene.add(new THREE.GridHelper());
//TODO: Create the heatmap here
this.createDataRectangle();
//Add the finished heatmap to the scene
this.scene.add(this.heatmap);
this.render();
this.animate();
}
setUpRenderer(){
console.log("Heatmap - setUpRenderer()");
let width = $('#container').width();
let height = $('#container').height();
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize(width,height);
this.renderer.setClearColor(0x404040);
$("#container").html(this.renderer.domElement);
window.addEventListener("resize", event => {
this.camera.aspect = innerWidth / innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize(innerWidth, innerHeight);
});
}
setUpCamera(){
console.log("Heatmap - setUpCamera()");
this.camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 100);
this.camera.position.z = 4;
}
setUpLighting(){
console.log("Heatmap - setUpLighting()");
this.ambientLight = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(this.ambientLight);
}
setUpOrbitalControls(){
console.log("Heatmap - setUpOrbitalControls()");
this.orbital_controls = new OrbitControls( this.camera, this.renderer.domElement );
this.orbital_controls.target.set(0, 0, 0);
this.orbital_controls.enableDamping = true;
this.orbital_controls.dampingFactor = 0.025;
this.orbital_controls.maxPolarAngle = Math.PI/2.0;
this.orbital_controls.minDistance = 2.0;
this.orbital_controls.maxDistance = 80.0;
this.orbital_controls.update();
this.orbital_controls.addEventListener( 'change', function(){
if (this.target.y < 0){
this.target.y = 0;
/* camera.position.y = -1; */
} else if (this.target.y > 1){
this.target.y = 1;
/* camera.position.y = 1; */
}
});
}
createDataRectangle(){ //TODO: Make this create at a position specified
console.log("Heatmap - createDataRectangle()");
const geometry = new THREE.BufferGeometry();
const vertices = [
-2, 0, 1,//0, floor, bottom left
-1, 0, 1,//1, floor, bottom right
-1, 0, -1,//2, floor, top right
-2, 0, -1,//3 floor, top left
-2, 0, 1,//4 roof, bottom left
-1, 0, 1,//5 roof, bottom right
-1, 0, -1,//6 roof, top right
-2, 0, -1//7 roof, top left
];
const indices = [
0, 1, 2,//floor, first triangle
2, 3, 0,//floor, second triangle
4, 5, 6,//roof, first triangle
6, 7, 4,//roof, second triangle
3, 0, 4,//west wall, first triangle
3, 4, 7,//west wall, second triangle
0, 1, 5,//south wall, first triangle
0, 5, 4,//south wall, first triangle
1, 2, 6,//east wall, first triangle
1, 6, 5,//east wall, second triangle
2, 3, 7,//north wall, first triangle
2, 7, 6,//north wall, second triangle
];
const colors = [
2,0,0, // bottom left
0,2,0, // bottom right
0,2,0, // top right
2,0,0, // top left
2,0,0, // bottom left
0,2,0, // bottom right
0,2,0, // top right
2,0,0 // top left
];
geometry.setIndex(indices);
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.computeVertexNormals();
const material = new THREE.MeshStandardMaterial({side:THREE.FrontSide,vertexColors:true,color: 0xFFFFFF });
const sample_rectangle = new THREE.Mesh(geometry, material);
this.heatmap.add(sample_rectangle);
}
animate(){
requestAnimationFrame(this.animate);
this.orbital_controls.update();//Required for Damping on OrbitControls
this.render();
}
render(){
this.renderer.render(this.scene, this.camera);
}
}
$(document).ready(function(){
console.log("DOM ready!");
new Heatmap();
});
</script>