Three.js全屏问题

29

我已经阅读了Three.js的API,并在StackOverflow上阅读了相关问题,我使用firebug和chrome的调试器进行了代码调试,我删除了所有我能够删除的内容,但是仍然遇到了这个有点烦人的全屏错误,其中渲染器视口比我的屏幕更大,因此会出现滚动条。 这是一个可见的错误,不影响渲染或其他操作,我只是想控制视口的大小,以便它匹配可用的屏幕空间而不会出现滚动条。

我在Windows 7上使用Google Chrome 18,刚开始使用Three.js API,但过去曾使用过诸如OpenGL之类的图形API,因此对其并不陌生。

当我尝试运行这个代码(这是在github主页面上显示的默认示例)时:

var camera, scene, renderer,
geometry, material, mesh;

init();
animate();

function init() {

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.z = 1000;
    scene.add( camera );

    geometry = new THREE.CubeGeometry( 200, 200, 200 );
    material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.CanvasRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );

    document.body.appendChild( renderer.domElement );

}

function animate() {

    // note: three.js includes requestAnimationFrame shim
    requestAnimationFrame( animate );
    render();

}

function render() {

    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.02;

    renderer.render( scene, camera );

}
它可以正常渲染,我能够看到红色线框盒子旋转,但我发现渲染器视口太大了,比我的屏幕尺寸还要大,这导致出现滚动条。代码使用window.innerWidthwindow.innerHeight设置宽高比和渲染器的宽度/高度,但似乎在某处多出了20至30个像素,并将它们添加到页面的底部和右侧?
我尝试调整body元素的CSS以删除边距和填充,对于创建的canvas元素也是如此,但仍然无效。我将屏幕大小回显到页面,并使用JavaScript alert()函数检查窗口的宽度和高度,然后观察它们在运行时操作期间传递给Three.js API,但错误仍然存在:canvas渲染对象正在调整大小,略大于屏幕尺寸。我解决问题的最接近方法是执行类似以下内容的操作:
var val = 7;
//Trims the window size by val
function get_width(){return window.innerWidth - val;}
function get_height(){return window.innerHeight - val;}

//... Code omitted for brevity

camera = new THREE.PerspectiveCamera( 75, get_width() / get_height(), 1, 10000 );

//... Code omitted for brevity 

render.setSize(get_width(), get_height());

它可以将渲染器大小限制在窗口范围内,但只能到某个程度。如果我将val降低到小于7,例如6或更低,则渲染器大小会弹出并再次比屏幕大20像素(约),导致滚动条出现?

有什么想法或建议吗?

5个回答

66

只需在CSS中将canvas元素设置为display: block;

<canvas>元素根据Mozilla开发者网络的官方说法是块级元素,介于内联元素和块级元素之间。他们写道:

浏览器通常在元素前后显示一个换行符。

但元素的呈现可能因浏览器而异,因此最好在CSS中显式设置display: inline;display: block;以确保获得正确的行为。

因此,只需在CSS文件中将其显示值设置为块即可解决问题。

canvas {
    display: block; /* fix necessary to remove space at bottom of canvas */
}

4
这应该是被接受的答案——隐藏溢出只是掩盖问题,但这个方法解决了它。非常感谢! - ultrafez
1
我同意ultrafez的观点。而且,即使滚动条被隐藏,通过鼠标在窗口上进行点击拖动,内容仍然可以滚动!... - Charles HETIER
2
由于我仍然在这个问题上收到回复,四年后我已经接受了ultrafez的建议以及社区对该答案的赞同。感谢@Wilt提供更新的答案! - hypervisor666

2

I. 视口尺寸的准确性

建议使用 Tyson Matanich 的 viewportSize.js,因为 'window.innerWidth' 和 'window.innerHeight' 不总是准确的。

下载链接: https://github.com/tysonmatanich/viewportSize

示例链接: http://tysonmatanich.github.com/viewportSize/

以下是作者的详细说明:

"大多数人依赖于 window.innerWidth、document.documentElement.clientWidth 或 $(window).width(),但它们并不总是准确地报告 CSS 媒体查询中使用的视口宽度。例如,WebKit 浏览器在滚动条可见时会更改其 CSS 视口的大小,而大多数其他浏览器则不会。由于 window.innerWidth 不受滚动条状态的影响,因此它不适合在 Chrome 或 Safari 中使用。此外,Internet Explorer 6、7 和 8 不支持 window.innerWidth。另一方面,document.documentElement.clientWidth 根据滚动条状态而改变,因此不适用于 Internet Explorer、Firefox 或 Opera。"

示例:

var viewportWidth  = viewportSize.getWidth(),
    viewportHeight = viewportSize.getHeight(),
    viewportAspect = viewportWidth / viewportHeight;

camera = new THREE.PerspectiveCamera( 75, viewportAspect, 1, 10000 );

II. 难以捉摸的元素

要注意任何通过“createElement”程序创建的元素。它们很容易被忽略。

使用Chrome的检查器或Firebug来查看是否有任何其他可能被忽略的元素。通常我会在上周的代码深处发现完全忘记的东西,然后想知道自己之前怎么会错过它。

III. 硬重置

最后,为了彻底,您可以尝试硬重置。Eric Meyer的经典重置通常被认为是最彻底的(http://meyerweb.com/eric/tools/css/reset/index.html),但我个人更喜欢“Condensed Meyer Reset”(作者未知,去年某个时候出现在网上):

body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, 
pre, form, fieldset, input, textarea, p, blockquote, th, td { 
    padding: 0;
    margin: 0;
    }
fieldset, img { 
    border: 0;
    }
table {
    border-collapse: collapse;
    border-spacing: 0;
    }
ol, ul {
    list-style: none;
    }
address, caption, cite, code, dfn, em, strong, th, var {
    font-weight: normal;
    font-style: normal;
    }
caption, th {
    text-align: left;
    }
h1, h2, h3, h4, h5, h6 {
    font-weight: normal;
    font-size: 100%;
    }
q:before, q:after {
    content: '';
    }
abbr, acronym { 
    border: 0;
    }

1
这对我有所帮助。它会一直保持画布全屏状态。
canvas {
    width: 100vw;
    height: 100vh;
    display: block;
  }

之前的答案都不适用于我,但这个可以。非常感谢。 - jnsnsml

1

我的做法和@paraplu类似,但我在我的样式中只是添加了!important。因为THREE.js添加了内联样式。

canvas {
   display: block;
   width: 100vw !important;
   height: 100vh !important;
}

我正在使用:

renderer.setSize(window.innerWidth, window.innerHeight);

另外,我已经找到了一种没有CSS的解决方法

renderer.setSize(window.innerWidth, window.innerHeight - 1);

在我的情况下,那一个像素的高度会触发两个滚动条,这个方法可以解决问题,但似乎并不是一个好的做法。

当然,更糟糕的做法是:

body {
   overflow: hidden;
}

0

在 CSS 中,这也应该可以解决问题:

canvas {
    vertical-align: top;
}

自然也需要来自上方的填充和边距修复


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接