【问题标题】:How can i attach a separate instance of Javascript code to N angular views如何将单独的 Javascript 代码实例附加到 N 角度视图
【发布时间】:2016-03-23 01:10:54
【问题描述】:

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

  1. 创建了一个包含 N 个对象数组的控制器。 (名称和值)。
  2. 创建了一个名为 ccGraph 的自定义 Angular 指令,它引入了一个 HTML 5 模板。
  3. 使用 ng-repeat 创建 N 个包含 ccGraph 元素的 div。 (连接中的 ng-repeat conn)

我在连接所有内容时遇到了概念性问题。如果我只是将 {{conn.name}} 放在 HTML 模板中,则名称会正确显示在每个 ccGraph div 中。

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

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

好的,从代码的角度来看,我有这样的 index.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);
}

现在,我想使用 Angular SPA 来绘制 N 个这些图。所以,假设我的 Angular 代码还没有启动。从概念上讲,我如何将上述代码转换为由 Angular 模型驱动的 Angular 指令?

【问题讨论】:

  • 分享你的一些代码会有所帮助。 :)
  • 这是你想要做的吗?如果是,我可以回答解释会发生什么。 :) plnkr.co/edit/wgJo1gCnI9x9OKpuTlsp?p=preview
  • 绝对正确。我会研究你的代码,看看你是怎么做的。如果你想用基本的解释做一个简短的回答,我很乐意接受。
  • 抱歉耽搁了。我对正在发生的事情做了更深入的回答。如果仍有不清楚的地方,请告诉我,我会尝试修改答案。

标签: javascript angularjs html5-canvas


【解决方案1】:

您认为使用指令来实现这一点是正确的。在角度 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>

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

如果您想了解更多关于指令的实际工作原理,您可以找到更多here

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

【讨论】:

    猜你喜欢
    • 2014-01-29
    • 1970-01-01
    • 2021-07-24
    • 2021-01-20
    • 2023-04-10
    • 2017-08-10
    • 2019-10-11
    • 2012-12-24
    • 2017-01-14
    相关资源
    最近更新 更多