Three.js 调整画布大小
Posted
技术标签:
【中文标题】Three.js 调整画布大小【英文标题】:Three.js Resizing Canvas 【发布时间】:2013-12-15 22:10:58 【问题描述】:我一直在做一个 3D 项目,我们使用 Three.js 库在网络浏览器中显示 3D 对象。
问题是:
1st 模型显示在一个小的 dom 元素中或当浏览器窗口本身很小时。 然后当窗口(或 dom 元素调整大小)时,模型变得像素化以下是一些截图:
调整大小前:
调整大小后:
调整大小后应该如何:
这是设置模型尺寸(高度和宽度)的代码部分,如果触发了调整大小事件,则会调用此函数:
console.log("domChanged fired")
instance.domBoundingBox = instance.dom.getBoundingClientRect();
instance.domCenterPos.x = instance.domBoundingBox.width / 2 + instance.domBoundingBox.left;
instance.domCenterPos.y = instance.domBoundingBox.height / 2 + instance.domBoundingBox.top;
var width = instance.dom.clientWidth, height = instance.dom.clientHeight;
instance.domWidthHalf = width / 2, instance.domHeightHalf = height / 2;
// TODO: fire event to expose it to site developers
// here we should update several values regarding width,height,position
if(instance.cameraReal)
instance.cameraReal.aspect = instance.dom.clientWidth / instance.dom.clientHeight;
instance.cameraReal.updateProjectionMatrix();
if(instance.renderer3D)
instance.renderer3D.setSize(instance.dom.clientWidth, instance.dom.clientHeight);
谁能给我一个提示?我已经研究了几天了,但目前还没有任何线索
【问题讨论】:
AFAIKsetSize
为您更改画布 width
/height
(渲染分辨率)并为 glViewport
使用新尺寸。你能仔细检查instance.dom.clientWidth/Height
是否真的在改变?看起来画布正在改变大小而不是其内部分辨率。
【参考方案1】:
因此,canvas 元素可以像其他所有元素一样调整大小。您要做的是告诉渲染器和相机也调整画布内容的大小。
window.addEventListener( 'resize', onWindowResize, false );
function onWindowResize()
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
【讨论】:
它已经完成了,你可以在我分享的代码片段中看到它 只是想将答案与可能有此问题的其他任何人分开。顺便说一句,很酷的建筑。 好的,谢谢帮助:),其实问题现在已经解决了,我会争取找时间写一个答案 初学者不要在这里使用window,你可能正在使用自己的容器作为渲染器,用那个容器代替window【参考方案2】:问题终于解决了,实际问题出在因为应用程序使用THREE.EffectComposer
对象,在类构造函数中创建了一个composer对象,如下所示:
this.composer = new THREE.EffectComposer(this.renderer3D);
所以对于渲染器,作曲家需要在事件处理函数之后更新大小,如下所示:
if(instance.renderer3D)
instance.renderer3D.setSize(instance.dom.clientWidth, instance.dom.clientHeight);
if(instance.composer)
instance.composer.setSize(instance.dom.clientWidth, instance.dom.clientHeight);
这完美地解决了这个问题:)
【讨论】:
【参考方案3】:我通过 React JS 应用了 Shawn Whinnery 的回答来满足我的需求:
在Mount上启动监听器:
componentDidMount()
window.addEventListener('resize', this.handleResize, false)
移除监听 onUnmount(因为我们喜欢垃圾回收):
componentWillUnmount()
window.removeEventListener('resize', this.handleResize, false)
安装处理函数:
handleResize = () =>
this.camera.aspect = window.innerWidth / window.innerHeight
this.camera.updateProjectionMatrix()
this.renderer.setSize(window.innerWidth, window.innerHeight)
胖箭头语法用于避免绑定this
。如果你有这个代码将不起作用:handleResize() ...
,但当然,如果你将它添加到你的构造函数中它会起作用:
this.handleResize = this.handleResize.bind(this)
最后说明:确认你的相机是this.camera
,你的渲染器是this.renderer
。除此之外,你应该可以把它全部粘贴进去。
【讨论】:
【参考方案4】:对于那些在谷歌上搜索的人,如果您想快速开始使用可以为您调整大小的帮助工具,请查看此 github:https://github.com/jeromeetienne/threex.windowresize
您唯一需要做的就是通过bower
安装并初始化它:
new THREEx.WindowResize(renderer, camera)
【讨论】:
这种方法最简单。只需包含 js 文件并初始化大小调整器。完美运行。【参考方案5】:这很简单。即使调整浏览器窗口大小,这三个.js 代码也不会改变。
代码:
//Simple Cube Example
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( color: "rgb(255, 0, 0)" );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
camera.position.z = 5;
var edges = new THREE.EdgesHelper( cube, "rgb(0, 0, 0)" );
edges.material.linewidth = 5;
scene.add( edges );
function animate()
requestAnimationFrame( animate );
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render( scene, camera );
animate();
function rot()
requestAnimationFrame( rot );
edges.rotation.x += 0.01;
edges.rotation.y += 0.01;
rot();
//this will not change it's size when browser is resized, but use css and correct it.
//this is the code. it does not work use a div and use the javascript
.code
float: left;
width: 100vw; /*fullscreen*/
height: 100vh;
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="robots" content="index, follow" />
<link rel="canonical" href="http://" />
<meta name="author" content="">
<meta name="google-site-verification" content="">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Hammersmith+One|Lato" rel="stylesheet">
<title></title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="https://threejs.org/build/three.js"></script>
</body>
</html>
【讨论】:
【参考方案6】:尝试使用抗锯齿属性将像素化问题解决 50 - 70%
例如:var renderer = new THREE.WebGLRenderer(antialias:true);
【讨论】:
这里的“像素化”是由于二次采样,因为渲染器没有放大到新的窗口大小,而不是由于锯齿。以上是关于Three.js 调整画布大小的主要内容,如果未能解决你的问题,请参考以下文章