我如何将 Javascript 代码的单独实例附加到 N angular 视图
How can i attach a separate instance of Javascript code to N angular views
我有一些 HTML5 代码,使用 canvas 绘制图表。我正在尝试创建一个 Angular SPA,它将基于具有 N 个对象的模型绘制 N 个这些图形。这是我所做的简化版本。
- 创建了一个包含 N 个对象数组的控制器。 (名称和值)。
- 创建了一个名为 ccGraph 的自定义 Angular 指令,它引入了一个 HTML 5 模板。
- 使用 ng-repeat 创建了 N divs 包含 ccGraph 元素。 (连接中的 ng-repeat conn)
我在连接所有内容时遇到概念性问题。如果我只是将 {{conn.name}} 放在 HTML 模板中,名称就会在每个 ccGraph div.
中正确显示
我的问题是我不知道如何将用于绘图的 Javascript 代码实例附加到每个 ccGraph div。 Javascript 代码首先找到它嵌入的 canvas,然后从那里开始工作。
- Angular 会为每个 ccGraph 实例创建一个单独的 Javascript 代码实例吗?
- 我该如何处理 "initialising" 名称包含 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 指令?
您认为使用指令来实现这一点是正确的。在 angular 1 中,这是将行为附加到 DOM 元素的方法。它们也可以被多次实例化,例如在 ng-repeat.
中
在你的特定情况下,关于制作一个能够在 canvas 上绘制的指令。我会这样去做。
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。
我有一些 HTML5 代码,使用 canvas 绘制图表。我正在尝试创建一个 Angular SPA,它将基于具有 N 个对象的模型绘制 N 个这些图形。这是我所做的简化版本。
- 创建了一个包含 N 个对象数组的控制器。 (名称和值)。
- 创建了一个名为 ccGraph 的自定义 Angular 指令,它引入了一个 HTML 5 模板。
- 使用 ng-repeat 创建了 N divs 包含 ccGraph 元素。 (连接中的 ng-repeat conn)
我在连接所有内容时遇到概念性问题。如果我只是将 {{conn.name}} 放在 HTML 模板中,名称就会在每个 ccGraph div.
中正确显示我的问题是我不知道如何将用于绘图的 Javascript 代码实例附加到每个 ccGraph div。 Javascript 代码首先找到它嵌入的 canvas,然后从那里开始工作。
- Angular 会为每个 ccGraph 实例创建一个单独的 Javascript 代码实例吗?
- 我该如何处理 "initialising" 名称包含 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 指令?
您认为使用指令来实现这一点是正确的。在 angular 1 中,这是将行为附加到 DOM 元素的方法。它们也可以被多次实例化,例如在 ng-repeat.
中在你的特定情况下,关于制作一个能够在 canvas 上绘制的指令。我会这样去做。
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。