我想在进入和离开全屏时调整画布大小。我正在使用 Three.js 及其
THREE.WebGLRenderer
。
使用下面的代码我可以做到这一点,但它设置了窗口的尺寸“一次迭代” - 这意味着当我进入全屏时,它设置较小的高度(但底部部分),然后我离开全屏,它会在垂直方向上过度拉伸尺寸。
代码:
var width = window.innerWidth,
height = window.innerHeight;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
function toggleFullscreen(){
var docElm = document.documentElement;
if(!document.fullscreen){
if (docElm.requestFullscreen) {
docElm.requestFullscreen();
}
else if (docElm.mozRequestFullScreen) {
docElm.mozRequestFullScreen();
}
else if (docElm.webkitRequestFullScreen) {
docElm.webkitRequestFullScreen();
}
else if (docElm.msRequestFullscreen) {
docElm.msRequestFullscreen();
}
document.fullscreen = true;
}
else{
if (document.exitFullscreen) {
document.exitFullscreen();
}
else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
}
else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
}
else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
document.fullscreen = false;
}
renderer.setSize(window.innerWidth, window.innerHeight);
}
...
<body>
<div onclick="toggleFullscreen()" id="button">Fullscreen</button>
</body>
setSize()
函数中的toggleFullscreen()
函数在进入或离开全屏之前被调用。这意味着渲染器的大小是由先前的窗口大小设置的。
通过
requestFullscreen
或exitFullscreen
进入或离开全屏会触发onresize
事件,所以在setSize()
事件处理函数中编写onresize
函数。
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
}
好吧,到目前为止我能想到的最糟糕也是唯一的解决方案是添加这个添加回调函数的结尾
window.setTimeout(function(){
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}, 500);
请告诉我情况有多糟糕并给出另一个解决方案:)
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
var canvas = renderer.domElement;
canvas.addEventListener('click', function(){
canvas.requestFullscreen = canvas.requestFullscreen ||
canvas.mozRequestFullScreen ||
canvas.webkitRequestFullscreen ||
canvas.msRequestFullscreen;
canvas.requestFullscreen();
});
document.body.appendChild( canvas );
window.addEventListener('resize', function(event){
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth , window.innerHeight );
});
如果您遵循最佳实践全屏正常工作,则无需更改您的 Three.js 代码。
这是一个遵循最佳实践的工作示例(单击任意位置即可全屏)。另外,这里还有 更多示例都使用相同的代码 表明,当您遵循最佳实践时,无需为所有不同的用例更改任何代码
在这种情况下,最佳实践意味着使用 CSS 并拥抱浏览器而不是对抗它。这意味着设置您的 CSS,以便您的画布(和其他元素)可以拉伸、缩放或移动到您想要的任何位置。然后查找浏览器执行的操作并设置画布的后备存储以匹配。
当你让 CSS 做它应该做的事情时,这里的调整大小代码就可以工作。
// Resize by clientWidth and clientHeight
var resize = function() {
var width = canvas.clientWidth;
var height = canvas.clientHeight;
if (canvas.width != width ||
canvas.height != height ) {
// You have to pass false here otherwise three.js does
// arguably the wrong thing and fights the CSS.
renderer.setSize( canvas.clientWidth, canvas.clientHeight, false );
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
};
现在将画布 CSS 设置为 100% 大小
canvas {
width: 100%;
height: 100%;
display: block; /* remove's the extra space that causes a scrollbar */
}
如果您的画布位于容器内(例如另一个 div),请将其也设置为 100% 大小,并将
body,html
设置为 100% 大小
html, body {
height: 100%;
margin: 0;
}
如果要渲染每一帧,只需在渲染循环结束时调用它即可。
var render = function() {
resize();
...
renderer.render( scene, camera );
requestAnimationFrame( render, canvas );
};
render();
如果您没有渲染每一帧,则在渲染时调用调整大小,并在屏幕调整大小时或通过 ResizeObserver 调用渲染。