Javascript AngularJS+;D3视图中使用的多个指令只有一个更新
我有一个仪表图指令,需要在视图中放置多次,但控制器中的更新方法似乎只更新视图中的最后一个指令。起初,我认为可能我没有将作用域设置为一个孤立的作用域,但事实并非如此,这会引发一个错误,但视图确实加载了所有图表,但它只更新了一个图表 我对指令进行了一个简单的描述以提供帮助,并在下面包含了指令和控制器的基本存根。注意:刚刚开始使用D3并在指令中实现它,因此当您调整浏览器大小时,指令会成倍增加(试图使其响应),因此您可能在代码笔中调整浏览器窗口大小后点击了保存Javascript AngularJS+;D3视图中使用的多个指令只有一个更新,javascript,css,angularjs,d3.js,Javascript,Css,Angularjs,D3.js,我有一个仪表图指令,需要在视图中放置多次,但控制器中的更新方法似乎只更新视图中的最后一个指令。起初,我认为可能我没有将作用域设置为一个孤立的作用域,但事实并非如此,这会引发一个错误,但视图确实加载了所有图表,但它只更新了一个图表 我对指令进行了一个简单的描述以提供帮助,并在下面包含了指令和控制器的基本存根。注意:刚刚开始使用D3并在指令中实现它,因此当您调整浏览器大小时,指令会成倍增加(试图使其响应),因此您可能在代码笔中调整浏览器窗口大小后点击了保存 .directive('d3Gauge
.directive('d3Gauge', [
'D3GaugeConfig',
function(D3GaugeConfig) {
return {
restrict: 'E',
scope: {
title: '@chartTitle',
config: '=chartConfig',
data: '=chartData'
},
link: link,
template: '<div>{{d3GaugeCtrl.title}}</div>',
controller: 'D3GaugeController',
controllerAs: 'd3GaugeCtrl',
bindToController: true
};
function link($scope, $element, $attrs) {
...
// Browser onresize event
$window.onresize = function() {
$scope.$apply();
};
// Watch for resize event
$scope.$watch(function() {
return angular.element($window)[0].innerWidth;
}, function() {
render($element, $scope.data);
});
$scope.update = update;
}
function render(element, newValue) {
...
}
function update(newValue, newConfiguration) {
...
}
}
])
.controller('D3GaugeController', [
'$scope',
function($scope) {
var vm = this;
function updateReadings() {
// Just pump in random data here...
if (angular.isDefined($scope.update)) {
$scope.update(Math.random() * 100);
}
}
// Every few seconds update reading values
updateReadings();
setInterval(function() {
updateReadings();
}, 5 * 1000);
}
]);
.directive('d3Gauge'[
“D3GaugeConfig”,
功能(D3GaugeConfig){
返回{
限制:'E',
范围:{
标题:“@chartTitle”,
配置:'=chartConfig',
数据:'=图表数据'
},
链接:链接,
模板:“{d3GaugeCtrl.title}}”,
控制器:“D3GaugeController”,
controllerAs:'d3GaugeCtrl',
bindToController:true
};
函数链接($scope、$element、$attrs){
...
//浏览器调整大小事件
$window.onresize=function(){
$scope.$apply();
};
//注意调整大小事件
$scope.$watch(函数(){
返回angular.element($window)[0].innerWidth;
},函数(){
render($element,$scope.data);
});
$scope.update=更新;
}
函数呈现(元素,newValue){
...
}
函数更新(新值、新配置){
...
}
}
])
.控制器('D3GaugeController'[
“$scope”,
职能($范围){
var vm=这个;
函数updateReadings(){
//在这里输入随机数据。。。
if(角度.isDefined($scope.update)){
$scope.update(Math.random()*100);
}
}
//每隔几秒钟更新一次读取值
updateradings();
setInterval(函数(){
updateradings();
}, 5 * 1000);
}
]);
最后一个仪表发生变化的原因是:
您正在存储存储最后一条路径的变量指针
pointer = pg.append('path')
.attr('d', pointerLine)
.attr('transform', 'rotate(' + config.minAngle + ')');
那么现在当你这么做的时候
pointer
.duration(config.transitionMs)
.ease('elastic')
.attr('transform', 'rotate(' + newAngle + ')');
只有最后一个指针将使用新的转换进行更新
因此,如果要为相同的随机值更新所有仪表路径,请执行以下操作:
//select all the path in all svg with group class pointer
d3.selectAll("svg .pointer path").transition()
.duration(config.transitionMs)
.ease('elastic')
.attr('transform', 'rotate(' + newAngle + ')');//update the new angle
工作代码
希望这有帮助 嗨,如果我想让每一个都独立更新怎么办?这是不可能的。。。哦,我想我明白你的意思了(没有双关语),因为我把指令值存储在link函数之外,它们都共享这些值。在应用程序中,每个图表将相互独立,并根据不同的数据集进行更新。您通常如何设置一个D3指令,该指令是可重用的,而不必传递大量的函数参数。是否可以将指令实例包装到服务或其他东西中?如果我希望每个实例都独立更新,那么您的查询是不可能的:是的,您可以通过对变量实现$watch来实现这一点。因此,当变量更改时,手表将触发您的函数,您可以在其中更新路径。我已将“间隔”和“更新”函数移动到渲染中,因此现在它可以正常工作。在调整大小时,请检查代码中的另一个错误调用渲染方法…但在渲染方法中,您添加了svg和组件…等等你会发现你的仪表号在增加。为了修复上面提到的这个调整大小的错误,我制作了doResize函数,它将改变svg的宽度和高度,而不是调用render函数。