【问题标题】:Releasing OrbitControls in threejs在threejs中发布OrbitControls
【发布时间】:2013-11-11 22:04:13
【问题描述】:

我有一个单页应用程序,里面有很多东西,使用 durandal。在一个页面上,我有一个链接指向另一个渲染 3d 模型的页面。 OrbitControls 用于使模型转动等。这消除了我默认的左键单击和右键单击。离开该页面后,它仍然保持鼠标绑定,并且我的左键单击和右键单击对于某些用途变得无用 - 选择一个意味着无法再次访问输入标签的标签。

如果我知道怎么做,我可以释放绑定并重置它们。关闭该 3d 窗口时会调用一个停用函数,但我不知道该在那里编写什么代码。任何帮助都会非常有用。我怀疑任何代码都有用,所以我不会放任何代码。

谢谢!

根据要求,这里是简化的视图模型:

define(['services/logger'], function (logger) {
    var vm = {
        attached: attached
    };
    return vm;
    function attached(view) {
        var camera, cameraTarget, scene, renderer, controls;
        init();
        animate();
        function init() {
            ...
            controls = new THREE.OrbitControls(camera);
            ...
        }
        function animate(){...}
        function render(){...}
     }
}

视图极其复杂,在这里完整粘贴:

<div id="canvasDiv" style="overflow: hidden; width:100%; height:100%">
</div>

【问题讨论】:

    标签: javascript knockout.js three.js durandal


    【解决方案1】:

    实际上,包含您的代码来设置 OrbitControls 可能会有所帮助(我不熟悉它)。

    解决整个问题的最佳方法可能是编写一个 Knockout 自定义绑定(如果您不知道,请谷歌)。在您设置 OrbitControls 的情况下,自定义绑定是抽象 DOM 操作的好地方。

    假设您有一个设置 OrbitControls 的 div。然后,您可以执行以下操作:

    HTML:

    <div data-bind="myOrbitControlsBinding: { someSetting: true; someOtherSetting: false }"></div>
    

    JavaScript:

    ko.bindingHandlers.myOrbitControlsBinding = {
        init: function (element, valueAccessor) {
            var settings = ko.utils.unwrapObservable(valueAccessor());
            setupOrbitControlsOnElement(element, settings); // This should be your setup code for OrbitControls
            ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
                // Here, you should unbind the event handlers for mouse clicks. How you do this depends on how OrbitControls sets them up. Please refer to their documentation for this. Maybe there is a generic dispose function?
                disposeOrbitControls(element);
            });
        }
    }
    

    编辑: 啊,我不知道你用的是三。我快速浏览了他们的文档,看看他们是否使用了某种捕获事件的输入模块。他们似乎没有。这可能意味着在您的代码中的某些地方,有关键字“addEventListener”(搜索它)。这将是捕获事件的地方。

    由于您使用的是 durandal,因此您的视图可能附加了一个视图模型。在视图模型中,添加一个“停用”方法(并返回它)。在此方法中,您需要再次移除事件监听器。您可能已经猜到了,但该方法称为 removeEventListener(请参阅https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.removeEventListener 了解说明)

    我仍然强烈建议您创建自定义绑定来设置三。与现在相比,这将使您对创建/删除有更多的控制。如果您不想这样做,请确保在视图模型中的 activate 方法中也初始化了 Three。

    让我知道这是否有帮助,否则一些视图模型/三个初始化代码会有所帮助。

    【讨论】:

    • 用简化的视图模型更新了问题。我几天前才开始使用三天,所以无法真正详细回答发生了什么。我不需要任何真正的绑定,因为我只是在预览模型,而不是编辑器。
    • 也更新了我上面的帖子
    • 我看了一点,我重新阅读了你的问题,发现你已经有一个停用回调。我用谷歌搜索了 OrbitControls。这是你用的吗? tileableart.com/code/natureof/js/three/js/controls/… 因为我扫描了该文件以查找 addEventListener。出现了六次。您需要在 deactivate 回调中再次删除这些事件侦听器,并且您的鼠标单击(和其他事件)应该再次属于您 :)
    • 就是这个。我刚刚更改了 Orbit 控件的初始化:controls = new THREE.OrbitControls(camera, myDomElement); 其中myDomElement 是 html 中的 div。这样,只有在那个 div 中才是给予 OrbitControls 的控件。谢谢!你让我彻底看透了这段代码,然后我才意识到该怎么做;)
    • 更好。我忽略了在构造函数中提供元素的可能性。很高兴能提供帮助,即使您自己找到了最好的解决方法;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多