我正在考虑将three.js用于my 3D model visualization Sphinx extension。该扩展程序使您可以轻松地可视化文档中的交互式3D对象,但是currently uses an oudated and unmaintained library for that。
three.js库包含大量示例。其中,有一个引起了我的注意:WebGL multiple elements text示例。
这是一个很好的例子,因为它满足了我对Sphinx扩展的需求:
现在,它只有一个警告:CPU / GPU消耗。即使您既不滚动也不与3D可视化交互时,CPU / GPU似乎也很忙。
起初,我认为可能是由于每个场景中的动画所致。我不需要为扩展程序添加动画,而只需要交互,因此我决定删除它们并仅在场景用户交互上强制重新渲染:
diff --git a/examples/webgl_multiple_elements_text.html b/examples/webgl_multiple_elements_text.html
index 289e4935a..e9fe7e087 100644
--- a/examples/webgl_multiple_elements_text.html
+++ b/examples/webgl_multiple_elements_text.html
@@ -196,6 +196,7 @@
scene.userData.camera = camera;
var controls = new THREE.OrbitControls( camera, views[ n ] );
+ controls.addEventListener( 'change', render );
scene.userData.controls = controls;
scenes.push( scene );
@@ -223,7 +224,6 @@
function animate() {
render();
- requestAnimationFrame( animate );
}
有了一个非常简单的更改:
但是,现在存在一个问题:如果尝试向下滚动页面,场景将不会随着文本滚动。
我该如何解决?
注意事项:
答案 0 :(得分:1)
添加队列以在scroll
事件中调用渲染
window.addEventListerner('scroll', queueRenderIfNotQueued);
let renderQueued = false;
function render() {
renderQueued = false;
...
}
function queueRenderIfNotQueued() {
if (!renderQueued) {
renderQueued = true;
requestAnimationFrame(render);
}
}
您可能还希望以调整大小进行渲染
window.addEventListerner('resize', queueRenderIfNotQueued);
的想法修改而成的示例
'use strict';
/* global THREE */
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({
canvas: canvas,
alpha: true
});
const sceneElements = [];
function addScene(elem, fn) {
sceneElements.push({
elem,
fn
});
}
function makeScene(elem) {
const scene = new THREE.Scene();
const fov = 45;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 5;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 1, 2);
camera.lookAt(0, 0, 0);
const controls = new THREE.OrbitControls(camera, elem);
controls.enableZoom = false;
controls.enablePan = false;
{
const color = 0xFFFFFF;
const intensity = 1;
const light = new THREE.DirectionalLight(color, intensity);
light.position.set(-1, 2, 4);
scene.add(light);
}
const geometry = new THREE.BoxBufferGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial({color:'red'});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function render(rect) {
camera.aspect = rect.width / rect.height;
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}
function renderWithBounds() {
const rect = elem.getBoundingClientRect();
const {
left,
right,
top,
bottom,
width,
height
} = rect;
renderer.setViewport(left, top, width, height);
renderer.setScissor(left, top, width, height);
render(rect);
}
controls.addEventListener('change', renderWithBounds);
addScene(elem, render);
}
[...document.querySelectorAll('.diagram')].forEach(makeScene);
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
const clearColor = new THREE.Color('#000');
let renderQueued = false;
function render() {
renderQueued = false;
resizeRendererToDisplaySize(renderer);
renderer.setScissorTest(false);
renderer.setClearColor(clearColor, 0);
renderer.clear(true, true);
renderer.setScissorTest(true);
const transform = `translateY(${window.scrollY}px)`;
renderer.domElement.style.transform = transform;
for (const {
elem,
fn
} of sceneElements) {
// get the viewport relative position opf this element
const rect = elem.getBoundingClientRect();
const {
left,
right,
top,
bottom,
width,
height
} = rect;
const isOffscreen =
bottom < 0 ||
top > renderer.domElement.clientHeight ||
right < 0 ||
left > renderer.domElement.clientWidth;
if (!isOffscreen) {
renderer.setViewport(left, top, width, height);
renderer.setScissor(left, top, width, height);
fn(rect);
}
}
}
function queueRenderIfNotQueued() {
if (!renderQueued) {
renderQueued = true;
requestAnimationFrame(render);
}
}
queueRenderIfNotQueued();
window.addEventListener('scroll', queueRenderIfNotQueued);
window.addEventListener('resize', queueRenderIfNotQueued);
}
main();
#c {
position: absolute;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
display: block;
z-index: -1;
}
.diagram {
display: inline-block;
width: 5em;
height: 3em;
}
.left {
float: left;
margin-right: .25em;
}
.right {
float: right;
margin-left: .25em;
}
p {
margin: 1em auto;
max-width: 500px;
font-size: xx-large;
}
<canvas id="c"></canvas>
<p>
<span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<span class="diagram left"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<p>
<span class="diagram right"></span>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus mi turpis, pellentesque sed aliquam vel, tincidunt eget massa. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</p>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r98/js/controls/OrbitControls.js"></script>