【问题标题】:AngularJS Binding to WebGL / CanvasAngularJS 绑定到 WebGL / Canvas
【发布时间】:2013-04-09 21:12:50
【问题描述】:

我很喜欢 AngularJS。我想知道当您的视图使用 HTML5 Canvas 或 WebGL 时是否可以使用它?如果是这样,是否有任何关于如何进行此操作的好的教程?

我见过几款游戏吹嘘它们是使用 AngularJS 制作的,但我不知道这是否仅限于它们的菜单、排行榜和其他仪表板元素。

(我不一定会在游戏中使用 MVC,但显然你可以做的不仅仅是使用 Canvas 和 WebGL 的游戏。)

谢谢!

【问题讨论】:

    标签: javascript model-view-controller canvas angularjs webgl


    【解决方案1】:

    编辑: 我制作了一个 WebGL 指令的完整示例,它使用带绑定的three.js 来调整对象的大小或更改它的材质类型。此外,窗口大小调整和鼠标移动等事件:


    是的,这很有可能。除了菜单、排行榜等之外,您还可以将 canvas 包装到指令中。

    1. 控制器将设置游戏状态
    2. 将此状态、从服务器加载的数据以及您可能拥有的任何其他数据传递给指令
    3. 最后在指令链接函数中初始化画布

    我制作了这个小应用程序来帮助我完成一个学校项目:http://callmethey.herokuapp.com/polygons。这是我使用的指令(画布部分使用了三个.js):

    app.directive('polygon', function() {
      return {
        restrict: 'A',
        scope: { 
          vertices: '=polygon',  
          color: '=color'
        },
        link: function(scope, element, attrs)
        {
          var camera, scene, renderer;
          var polygon;
          var targetRotation = 0;
          var targetYRotation = 0, targetXRotation = 0;
          var targetYRotationOnMouseDown = 0, targetXRotationOnMouseDown = 0;
          var mouseX = 0, mouseY = 0;
          var mouseXOnMouseDown = 0, mouseYOnMouseDown = 0;
          var width = $(element).width();
          var height = 200;
          var widthHalfX = width/2;
          var widthHalfY = height/2;
    
          init();
    
          function init() {
            // Setup scene
            camera = new THREE.PerspectiveCamera( 70, width / height, 1, 1000 );
            camera.position.x = 0;
            camera.position.y = 0;
            camera.position.z = 300;
            scene = new THREE.Scene();
            // Build Polygon
            var geometry =  new THREE.Geometry();
            angular.forEach(scope.vertices, function (v) {
              geometry.vertices.push( new THREE.Vector3( v.x, v.y, v.z ) );
            });
            geometry.faces.push( new THREE.Face3(0, 1, 2 ));
            THREE.GeometryUtils.center( geometry );
            // Push polygon to scene
            var material = new THREE.MeshBasicMaterial( { color: cols[scope.color], side: THREE.DoubleSide } );
            polygon = new THREE.Mesh( geometry, material );
            scene.add(polygon);
            renderer = new THREE.WebGLRenderer();
            renderer.setSize( width, height );
          }
    
         // ..... rest of the code truncated for readability
      };
    });
    

    【讨论】:

    • WebGL 指令,这一定是未来
    • 您的示例在 Mac 上的 chrome 中不起作用。抛出这些错误:创建 WebGL 上下文时出错。 three.min.js:412 TypeError: 无法调用 null 的方法 'getExtension'
    • Chorome 有时会在更新时自动禁用 WEBGL。这似乎是老一代 Macbook 的问题。确保 chrome://flags/#disable-webgl 为 disabled,它将重新开始工作。
    【解决方案2】:

    另一种技术是将 WebGL 场景封装为工厂,并通过返回的工厂 API 向模块公开对 3D 场景的访问。这种方法的一个优点是您可以将场景注入到任何其他控制器或指令中。 Angular 中的工厂是单例的,所以只有 1 个 3D 场景的副本在浮动。

    这种封装方法还允许您将 3D 场景逻辑与应用程序逻辑隔离开来。

    只要您通过公开的 Factory API 初始化工厂,您就应该能够使用大多数预先存在的 WebGL 代码。为此,请将所有 3D 场景代码复制到工厂中,然后从控制器调用注入的 3D 工厂的 init 函数来初始化渲染。

    我在画布元素上使用指令来定义场景交互。点击、选取框、按键、事件。

    【讨论】:

    • 同意!如果您有一个 WebGL 上下文,其中包含多个可以通过 angular 控制和更新的组件,那么这绝对应该是一种方法。
    • 我实际上使用同样的方法来创建多个 WebGL 上下文。只需创建多个工厂并将它们全部注入您要从中操作它们的相同控制器/指令中。如果你使用 requestAnimationFrame 钩子,浏览器会管理 FPS。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 2011-09-14
    • 2017-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多