使用 onWindowResize() 函数更改窗口大小时按比例更改几何的大小 [英] Changing proportionally the size of a geometry when the window size changes using onWindowResize() function

查看:116
本文介绍了使用 onWindowResize() 函数更改窗口大小时按比例更改几何的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 javascript 进行编码.我做了一些课程,现在我正在使用 Three.js 探索 webgl 世界

我正在试验这个函数,这个函数在 Threes.org 的所有例子中都非常有用:

 函数 onWindowResize() {camera.aspect = window.innerWidth/window.innerHeight;相机.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}

有了这个功能,我可以在缩小或增加浏览器窗口的宽度时将几何图形居中,当我缩小或增加浏览器窗口的高度时,我可以使几何图形变小或变大.

但现在的问题是,当我降低窗口的高度时,我可以看到我的几何图形,因为它居中且更小.但是当我减小窗口的宽度时,我看不到所有几何图形,因为它居中但不小.

在这个例子中:

我的 iphone 中这个不完整的几何体:

你有什么建议吗?这个问题有办法解决吗?

解决方案

欢迎来到 js/Three.js 的世界!感谢您整理小提琴.这是我建议的解决方案.

1) 您在第 44 行有一个不幸的错字

object.scale.devideScalar(1.5);

应该

object.scale.divideScalar(1.5);

在浏览器中使用 javascript 时,打开您的开发工具(chromefirefox 或您选择的浏览器).它会抛出类似的东西:

未捕获的类型错误:object.scale.devideScalar 不是函数

2) 解决这个问题,您仍然有问题.您编写的代码行通过将比例缩小 66%每次调用 onWindowResize() 来改变(更改)three.js 多维数据集.正如您所想象的那样,0.66^many 会很快变为零并且立方体消失.无赖.

我认为您想要的是对象的比例以匹配屏幕的比例.因此,无论是起始屏幕还是调整大小的屏幕,立方体始终占据大约 50%(或其他)的 div.

首先,简要说明为什么您的场景似乎在垂直方向而不是水平方向调整大小.three.js 透视相机 fov(视野,即视角相机收集到您的渲染中)取决于垂直空间.当您更新相机的可用空间时,相机会进行调整以使场景保持相同的视野.您可以在高大"手机中看到这一点;立方体在垂直空间中的表观高度相同,但侧面被切断.

这会导致一个问题.可以像您注释掉的那样处理对象的比例:

object.scale.set(factor, factor, factor);

这可以使事情保持一致,但是当您有多个立方体或您开始转换对象(比例尺到处都是)时,就会变得笨拙.在不扭曲 3d 投影的情况下,渲染器无法按照您建议的方式进行拉伸.这样想一想:如果你有一个立方体,那个立方体可以通过扭曲来填充任何屏幕吗?矩形屏幕将具有:空白空间、截断立方体或扭曲比例.

我还假设最终目标不仅仅是一个矩形(您可以使用任意数量的 2d javascript 或 css 解决方案来模拟它,并且 CPU 和头痛时间更少).

所以,我的激进解决方案是不要让画布调整大小以完全填满容器.修改后的示例将内容放在部分填充窗口的包含 div 中.根据自己的喜好更改 css.填充窗口的一种方法是:

宽度:100%;高度:100vh;

无论如何,通过调整画布来调整预览窗口和我的代码的大小.我将此比例设置为 16:9(普通电视),但您也可以随意更改.容器本身是紫色的,渲染画布是浅蓝色的,立方体是蓝色的.真正的新代码是:

var targetAspectRatio = 16/9;//电影!功能方面大小(可用宽度,可用高度){var currentRatio = availableWidth/availableHeight;如果(currentRatio > targetAspectRatio){//那么高度是限制因素返回 {宽度:availableHeight * targetAspectRatio,高度:可用高度};} 别的 {//宽度是限制因素返回 {宽度:可用宽度,高度:availableWidth/targetAspectRatio};}}

本质上,大于 0 的任何大小的矩形要么不够宽,要么不够高.在有限的维度中占用尽可能多的空间,而不是只使用将保持纵横比在另一个维度上的空间.

还有一些黑线 (68:69) 将渲染器置于容器的中心.如果容器是窗口,则渲染器将居中.

希望对您有所帮助并祝您工作顺利.

I am making my first steps coding with javascript. I made some courses and now I am exploring the webgl world using Three.js

I am experimenting with this function very used in all the examples of threes.org:

        function onWindowResize() {

          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();

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

        }

With this function I can center my geometry when I reduce or increase the width of my browser's window and I can make my geometry smaller or bigger when I reduce or increase the height of my browser's window.

But now the thing is that when I reduce the height of my window I can see my geometry because it's centered and smaller. But when I reduce the width of my window I can't see all my geometry because it's centered but not smaller.

In this example: http://codepen.io/gnazoa/pen/BjoBZz I tried to avoid this problem using object.scale.devideScalar(1.5); in my onWindowResize() function, but it doesn't makes a change.

I am searching a solution for this because I consider it really important for a correct experience, because for the moment, I see this geometry in my desktop screen:

And this incomplete geometry in my iphone:

Do you have some suggestion? Is this problem something possible to solve?

解决方案

Welcome to the world of js/Three.js! And thanks for putting together a fiddle. Here's my suggested solution.

1) You have an unfortunate typo on line 44

object.scale.devideScalar(1.5);

should be

object.scale.divideScalar(1.5);

When working with javascript in the browser, open up your dev tools (chrome, firefox, or your browser of choice). It will throw something like:

Uncaught TypeError: object.scale.devideScalar is not a function

2) Fixing that, you still have a problem. The line as you've written it mutates (changes) the three.js cube by reducing the scale by 66% every call to onWindowResize(). As you'll imagine, 0.66^many becomes zero very quickly and the cube vanishes. Bummer.

I think what you want is the scale of object to match the scale of the screen. So a cube always takes up roughly 50% (or whatever) of your div, no matter the starting or resized screen.

First, a brief explanation as to why your scene seems to resize on the vertical and not the horizontal. The three.js perspective camera fov (field of view, ie the angle of viewing the camera collects into your render) depends on the vertical space. As you update the camera's available space, the camera adjusts to keep the scene in the same fov. You can see that in you 'tall' phone; the apparent height of the cube is the same in vertical space, but the sides are cut off.

This leads to a problem. Messing with the object's scale can be done like you commented out:

object.scale.set(factor, factor, factor);

This can kind of get things in line, but becomes unwieldy when you have more than one cube or you start transforming your objects (scales are all over the place). The renderer can't be stretched in the way you suggest without distorting your 3d projection. Think about it this way: if you have a cube, can that cube fill any screen with being distorted? A rectangular screen will either have: empty space, cut off cube, or distort the scale.

I'm also assuming the end goal isn't just a rectangle (which you could emulate with any number of 2d javascript or css solutions with less cpu and headache time).

So, my radical solution is don't have your canvas resize to completely fill the container. The modified example puts the content in a containing div that partially fill the window. Change the css to your liking. One way to fill the window would be:

width: 100%;
height: 100vh;

In any case, resize the preview window and my code with adjust the canvas. I set this ratio at 16:9 (common tv), but you can change that as you like too. The container itself is purple, the render canvas is light blue, and the cube is blue. The real new code is:

var targetAspectRatio = 16 / 9; //cinematic!
function aspectSize(availableWidth, availableHeight) {
  var currentRatio = availableWidth / availableHeight;
  if (currentRatio > targetAspectRatio) {
    //then the height is the limiting factor
    return {
      width: availableHeight * targetAspectRatio,
      height: availableHeight
    };
  } else {
    // the width is the limiting factor
    return {
      width: availableWidth,
      height: availableWidth / targetAspectRatio
    };
  }
}

Essentially, a rectangle of any size over 0 will either be not wide enough or not tall enough. Take up as much space in the limited dimension than only use what will keep the aspect ratio in the other.

There are also some hacked lines (68:69) that center the renderer in the container. If the container is the window, the renderer will be centered in that.

I hope that helps and good luck with your work.

这篇关于使用 onWindowResize() 函数更改窗口大小时按比例更改几何的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆