如何将Javascript代码的单独实例附加到N个角度视图

How can i attach a separate instance of Javascript code to N angular views

本文关键字:视图 实例 Javascript 代码 单独      更新时间:2023-09-26

我有一些HTML5代码,使用画布绘制图形。我正在尝试创建一个Angular SPA,它将基于具有N个对象的模型绘制其中N个图。这是我所做工作的简化版本。

  1. 创建了一个具有N个对象阵列的控制器。(名称和值)
  2. 创建了一个名为ccGraph的自定义Angular指令,该指令引入了HTML5模板
  3. 使用ng repeat创建包含ccGraph元素的N个div。(ng个重复连接)

我有一个概念上的问题,把所有的东西都连接起来。如果我只是在HTML模板中放入{{conn.name}},名称就会正确地显示在每个ccGraph分区中。

我的问题是,我不知道如何将用于绘图的Javascript代码的实例附加到每个ccGraph分区。Javascript代码从找到它嵌入的画布开始,然后从那里开始工作。

  1. Angular会为ccGraph的每个实例创建一个单独的Javascript代码实例吗
  2. 如何使用包含div的名称来"初始化"Javascript代码?(在我的独立HTML代码中,我使用onLoad()完成了所有的初始绘制。)

好的,从代码的角度来看,我有工作索引。像这样的HTML;

<BODY  onload="initialise();" >
<div class="usageMeter" width="200px" height="500px" > 
    <canvas id="testIndicator" class="usageScale" width="200px" height="500px" >
        Fallback content, in case the browser does not support Canvas.
    </canvas>

和绘制图形的Javascript代码,如下所示:

function initialise() {
mCanvas = document.getElementById("testIndicator");
ctx = mCanvas.getContext("2d");
ctx.translate(0.5, 0.5);
scaleWidth = mCanvas.width * 0.4;
scaleHeight = mCanvas.height * 0.8;
scaleX = mCanvas.width * 0.25;
scaleY = mCanvas.height * 0.1;
loadImages();
drawScale();
elapsedTime = 0.0;
oldElapsedTime = 0.0;
tid = setInterval(updateTime, tickInterval);
}

现在,我想用一个角度SPA来画N个这样的图。所以,让我们只说我的Angular代码还没有开始。从概念上讲,我如何将上面的代码转换为由角度模型驱动的角度指令?

您认为使用指令实现这一点是正确的。在angular 1中,这是将行为附加到DOM元素的方式。它们也可以被实例化多次,例如在ng repeat中。

在你的特殊情况下,关于制作一个能够在画布上绘制的指令。我会这样做的。

app.directive('painter', function($interval) {
  return {
    restrict: 'E',
    templateUrl: 'painter.html', // the template to instantiate
    scope: {
      stuffToDraw: '=' // bind(2-way-binding) the stuff-to-draw attribute on the host element to scope.stuffToDraw (via reference)
    },
    // the link function gets called once for the directive
    // it is usually used in directives that do dom manipulation directly
    // will most likely be deprecated in angular 1.5
    link: function(scope, element, attrs) {
      // get the canvas from the template and the context to draw on the angular way
      // element is the host element of the directive
      var canvasCtx = element.children()[0].getContext('2d');
      canvasCtx.fillStyle = "red";
      var rotate = 0;
      var textToDraw = '';
      // add a watcher on the value in the scope so we know if/when it changes
      scope.$watch('stuffToDraw', function(newValue, oldValue) {
        if (newValue) { // 1st time it will be undefined
          textToDraw = newValue;
        }
      });
      // save the interval promise so we can cancel it later when the directive is destroyed
      var intervalPromise = $interval(function() {
        rotate++;
        drawStuff();
      }, 30);
      // when the scope is destroyed (eg the element is removed from dom) stop the interval
      scope.$on('$destroy', function() {
        $interval.cancel(intervalPromise);
      });
      function drawStuff(newValue) {
        canvasCtx.clearRect(0, 0, 200, 500);
        canvasCtx.save();
        canvasCtx.translate(10, 200);
        canvasCtx.rotate(rotate);
        canvasCtx.translate(-10, -200);
        canvasCtx.fillText(textToDraw, 10, 200);
        canvasCtx.restore();
      }
    }
  }
});
<!-- painter.html -->
<!-- this content will be inserted in the painter(host) element -->
<canvas class="usageScale" width="200px" height="500px">
  Fallback content, in case the browser does not support Canvas.
</canvas>

<!-- main/usage -->
<!-- itterate over the values array and instantiate a directive for each value. bind the array elements as the stuff-to-draw value (scope.stuffToDraw) -->
<!-- painter will be the host element for our directive instances -->
<painter ng-repeat="value in values" stuff-to-draw="value"></painter>

这并不是实现这一点的唯一方法,您还可以在控制器中完成大量工作。

如果你想了解更多关于指令实际如何工作的信息,你可以在这里找到更多。

最新版本的plunker可以在这里找到。