【问题标题】:Changing proportionally the size of a geometry when the window size changes using onWindowResize() function使用 onWindowResize() 函数改变窗口大小时按比例改变几何形状的大小
【发布时间】:2016-08-11 08:52:07
【问题描述】:

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

我正在试验这个在threes.org的所有示例中非常常用的功能:

        function onWindowResize() {

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

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

        }

使用此功能,当我减小或增加浏览器窗口的宽度时,我可以使我的几何图形居中,当我减少或增加浏览器窗口的高度时,我可以使我的几何图形变小或变大。

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

在这个例子中:http://codepen.io/gnazoa/pen/BjoBZz 我试图在我的onWindowResize() 函数中使用object.scale.devideScalar(1.5); 来避免这个问题,但它没有做出任何改变。

我正在为此寻找解决方案,因为我认为这对于获得正确的体验非常重要,因为目前,我在桌面屏幕上看到了这个几何图形:

而我 iphone 中的这个不完整的几何图形:

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

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    欢迎来到 js/Three.js 的世界!谢谢你把小提琴放在一起。这里是my suggested solution

    1) 不幸的是,第 44 行有一个错字

    object.scale.devideScalar(1.5);
    

    应该是

    object.scale.divideScalar(1.5);
    

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

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

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

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

    首先,简要解释一下为什么您的场景似乎在垂直方向而不是水平方向上调整大小。 three.js perspective camera fov(视野,即摄像机收集到渲染中的视角)取决于垂直空间。当您更新相机的可用空间时,相机会进行调整以使场景保持在相同的视野中。您可以在“高”手机中看到这一点;立方体的表观高度在垂直空间中是相同的,但边被切掉了。

    这会导致一个问题。可以像您注释掉的那样弄乱对象的比例:

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

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

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

    所以,my radical solution 没有调整画布大小以完全填满容器。修改后的示例将内容放在部分填充窗口的包含 div 中。根据自己的喜好更改 css。填充窗口的一种方法是:

    width: 100%;
    height: 100vh;
    

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

    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
        };
      }
    }
    

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

    还有一些黑线 (68:69) 使渲染器在容器中居中。如果容器是窗口,则渲染器将居中。

    希望对你的工作有所帮助并祝你好运。

    【讨论】:

    • 非常感谢!令人惊讶的是,我正在查看您编写的代码,它对我有很大帮助。我看到并试图解决的唯一问题是,当我减小屏幕宽度时立方体的可视化与我在打开页面之前减小屏幕宽度时的可视化不同。你知道为什么会这样吗?
    • 在我整理的演示中,我故意在init()中执行纵横比来演示差异。要摆脱该演示,您希望初始化代码执行与 resize() 相同的工作。第 10,32 行需要更改以使用 aspectSize() 的结果,第 68:69 行需要在第 34 行附近的某个地方调用(提示:这应该是一个函数调用)
    • 非常感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 2021-04-27
    • 2012-10-24
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    相关资源
    最近更新 更多