【问题标题】:Place element in DOM in AngularJS在AngularJS中的DOM中放置元素
【发布时间】:2017-04-27 18:18:18
【问题描述】:

假设我们在作用域中有一个数组,其中包含画布元素。

AngularJS

$scope.canvasElements =
 [document.createElement('canvas'), document.createElement('canvas')];

HTML

<element replace-with="currentCanvas" ng-click="alert('clicked')"></element>

currentCanvas 是一个变量,它将引用数组中当前选定的画布。

$scope.currentCanvas = null;

假设我们更改了$scope.currentCanvas 如下:

$scope.currentCanvas = $scope.canvasElements[0];

现在当前选定的画布元素 ($scope.currentCanvas) 应该替换 DOM 中的 &lt;element&gt;

附加到&lt;element&gt; 的所有事件我想转移到新元素(在本例中为画布),它会替换它。

如果变量$scope.currentCanvas发生变化,像这样:

$scope.currentCanvas = $scope.canvasElements[1];

应该会发生同样的事情(我认为应该在这里使用范围监视)。

有什么解决办法吗??

非常感谢您提前提供的帮助。

【问题讨论】:

    标签: javascript angularjs canvas


    【解决方案1】:

    我不确定您为什么需要满足这些条件以及您需要转移哪些确切事件:

    所有附在&lt;element&gt;的事件我要转移到新的 替换它的元素(在本例中为画布)

    但是,假设click 事件对您来说已经足够了,实现您的目标的最简单和最快的方法是以下指令:

    angular.module('app').directive('fakeElement', function() {
        return {
            replace: true,
            restrict: 'E',
            scope: { replaceWith: '=' },
            link: function(scope, elem, attrs) {
                scope.$watch(
                    'replaceWith',
                    () => elem.html('').append(scope.replaceWith)
                );                  
            },
            template: '<div class="wrapper"></div>'
        };
    });
    

    指令监听replaceWith参数的变化并相应地修改指令的内容。

    由于事件的冒泡性质,无需将 click 处理程序转移到新元素。

    你可以玩here。每次点击 &lt;div&gt; 都会将当前的 &lt;div&gt; 替换为下一个。

    如果您不仅要动态替换常规 HTML 元素,还要动态替换自定义指令,您还必须在添加之前$compile 新元素。

    【讨论】:

      【解决方案2】:

      下面的代码回答了我的问题!

      这段代码主要是`'el'`指令,其余的只是为了演示指令的工作原理。

      希望这也能帮助其他开发者!

      angular.element.prototype.cloneCanvas = function(){
        if (!this.is('canvas')) return this;
        var canvas = this[0];
        var newCanvas = document.createElement('canvas');
        var context = newCanvas.getContext('2d');
        newCanvas.width = canvas.width;
        newCanvas.height = canvas.height;
        context.drawImage(canvas, 0, 0);
        return newCanvas;
      };
      
      angular.module('app', [])
      
      .directive('el', function($compile){
        return {
          restrict: 'E',
          scope: {
            element: '='
          },
        compile: function(element, attrs){
          return function(scope){
            var currentElement = element;
            scope.$watch('element', function (newValue, oldValue) {
              if (newValue && typeof newValue === "object") {
                var newOb = angular.element(newValue)[0];
                if (typeof newOb.style === "object") {
                  var clone = angular.element(newOb).is('canvas') ? 
                    angular.element(newOb).cloneCanvas() : angular.element(newOb).clone();
                  var attrs = angular.element(element)[0].attributes;
                  angular.forEach(attrs, function(attr){
                    angular.element(clone).attr(attr.name, attr.value);
                  });
                  var clone = $compile(clone)(scope.$parent);
                  currentElement.replaceWith(clone);
                  currentElement = clone;
                }
              }
            });
          }
        }
        };
      })
      
      .controller('mainCtrl', function($scope){
        $scope.canvasElements = [document.createElement('canvas'),document.createElement('canvas'),document.createElement('canvas')];
        
        $scope.canvasElements.forEach(function(canvas, i){
          var ctx = canvas.getContext('2d');
          canvas.width = 100;
          canvas.height = 100;
          ctx.fillStyle = "#EEE";
          ctx.fillRect(0, 0, canvas.width, canvas.height);
          ctx.fillStyle = "red";
          ctx.font="20px Arial";
          ctx.fillText("Canvas "+(i+1),7,55);
          ctx.save();
        });
        
        $scope.currentCanvas = $scope.canvasElements[0];
        
        $scope.setNextCanvasAsCurrent = function(){
          $scope.currentCanvas = $scope.canvasElements.indexOf($scope.currentCanvas) < 0 ? $scope.canvasElements[0] : $scope.canvasElements.indexOf($scope.currentCanvas) == $scope.canvasElements.length-1 ? $scope.canvasElements[0] : $scope.canvasElements[ $scope.canvasElements.indexOf($scope.currentCanvas) + 1]
        };
      })
          
      <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
      
      <div ng-app="app" ng-controller="mainCtrl">
      
        <el element="currentCanvas"></el>
      
        <br>
        <button ng-click="setNextCanvasAsCurrent()">Set Next Canvas As Current</button>
        
        
        {{canvasElements.indexOf(currentCanvas) + 1}}
        /
        {{canvasElements.length}}
      
      
      </div>

      【讨论】:

        猜你喜欢
        • 2014-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-03
        • 1970-01-01
        • 2016-01-27
        • 1970-01-01
        相关资源
        最近更新 更多