Javascript 如何使用基于D3的角度指令处理不断变化的数据

Javascript 如何使用基于D3的角度指令处理不断变化的数据,javascript,angularjs,d3.js,data-visualization,ngresource,Javascript,Angularjs,D3.js,Data Visualization,Ngresource,下面是一个饼图的角度指示,我想在整个应用程序中重用它。指令被放置在由控制器驱动的视图中——控制器可以在任何时候更新传递给指令的数据集 一旦我确定数据发生了变化,我需要一种干净的方法来彻底清理我的饼图,并用新数据重新绘制。我在指令的数据参数上有一个$watch,它可以工作(在值发生变化时触发),但是,我似乎找不到一个好的、干净的方法来处理重新绘制饼图。也许更新现有饼图更容易;也许一个新的馅饼更容易完全从头开始。假设对现有饼图的更新是最好的,我如何才能做到这一点 (是的,我知道该指令的大部分内容并不

下面是一个饼图的角度指示,我想在整个应用程序中重用它。指令被放置在由控制器驱动的视图中——控制器可以在任何时候更新传递给指令的数据集

一旦我确定数据发生了变化,我需要一种干净的方法来彻底清理我的饼图,并用新数据重新绘制。我在指令的数据参数上有一个$watch,它可以工作(在值发生变化时触发),但是,我似乎找不到一个好的、干净的方法来处理重新绘制饼图。也许更新现有饼图更容易;也许一个新的馅饼更容易完全从头开始。假设对现有饼图的更新是最好的,我如何才能做到这一点

(是的,我知道该指令的大部分内容并不完整;我只担心馅饼的更新,所以请不要介意)

“严格使用”;
module.exports=函数(ngModule){
指令('pie',函数(){
var=0;
返回{
限制:'E',
范围:{
数据:'=',
预设:“@”
},
模板:“”,
替换:正确,
链接:功能(范围、元素){
//一旦DOM准备好了。。。
元素。就绪(函数(){
//为D3饼图容器元素创建唯一ID
scope.uniqueId='pie'+graphId++;
//如果仪表板数据集选择发生更改,我们需要了解它
范围:$watch(“数据”);
//设置(在预设之前未定义)
var graphSettings={};
//预设
开关(范围预设){
案例“仪表板”:
graphSettings.color=d3.scale.category20b();
graphSettings.graphHeight=500;
graphSettings.graphWidth=700;
graphSettings.outerRadius=150;
graphSettings.innerRadius=graphSettings.outerRadius/2;
graphSettings.sortMethod=null;
graphSettings.startAngle=0;
graphSettings.endAngle=2*Math.PI;
graphSettings.TransitionLay=0;
graphSettings.transitionDuration=1500;
graphSettings.legendSize=18;
graphSettings.legendSpacing=4;
graphSettings.legendXOffset=-4;
打破
违约:
log('Default preset!');
}
var svg=d3.select(元素[0])
.append('svg')
.attr('height',graphSettings.graphHeight)
.attr('width',graphSettings.graphWidth)
.append('g')
.attr('transform','translate('+graphSettings.outerRadius+','+graphSettings.outerRadius+'));
var arc=d3.svg.arc()
.内半径(图形设置.内半径)
.outerRadius(图形设置。outerRadius);
var pie=d3.layout.pie()
.价值(功能(d){
返回d.count;
})
.startAngle(图形设置.startAngle)
.端角(图形设置.端角)
.排序(图形设置.排序方法);
var path=svg.selectAll('path')
.数据(pie(范围数据))
.输入()
.append('路径')
.attr('fill',函数(d){
返回图形设置.颜色(d.数据.标签);
})
.transition().delay(graphSettings.transitionDelay)。duration(graphSettings.transitionDuration)
.attrween('d',函数(d){
var i=d3.插值(d.startAngle+0.1,d.endAngle);
返回函数(t){
d、 端角=i(t);
返回弧(d);
};
});
var legend=svg.selectAll(“.legend”)
.data(graphSettings.color.domain())
.输入()
.append('g')
.attr('类','图例')
.attr('transform',函数(d,i){
变量高度=graphSettings.legendSize+graphSettings.legendSpacing;
var offset=height*graphSettings.color.domain().length/2;
var x=graphSettings.legendXOffset*graphSettings.legendSize;
变量y=i*高度-偏移量;
返回“translate”(“+x+”、“+y+”)”;
});
//传奇大便
legend.append('rect')//LOL rekt
.attr('height',graphSettings.legendSize)
.attr('width',graphSettings.legendSize)
.style('fill',graphSettings.color);//这取决于之前设置的颜色域
图例.append('text')
.attr('x',graphSettings.legendSize+graphSettings.legendSpacing)
.attr('y',graphSettings.legendSize-graphSettings.legendSpacing)
.style('font-family','fontsawesome')
.文本(功能(d){
'use strict';

module.exports = function(ngModule) {
    ngModule.directive('pie', function() {

        var graphId = 0;

        return {
            restrict: 'E',
            scope: {
                data: '=',
                preset: '@'
            },
            template: '<div id="{{::uniqueId}}"></div>',
            replace: true,
            link: function(scope, element) {

                // Once the DOM is ready...
                element.ready(function() {

                    // Create our unique ID for our D3 pie chart container element
                    scope.uniqueId = 'pie' + graphId++;

                    // If the dashboard data set selection changes, we need to know about it
                    scope.$watch('data');

                    // Settings (undefined until presets)
                    var graphSettings = {};

                    // Presets
                    switch(scope.preset) {
                        case 'dashboard':
                            graphSettings.color = d3.scale.category20b();
                            graphSettings.graphHeight = 500;
                            graphSettings.graphWidth = 700;
                            graphSettings.outerRadius = 150;
                            graphSettings.innerRadius = graphSettings.outerRadius / 2;
                            graphSettings.sortMethod = null;
                            graphSettings.startAngle = 0;
                            graphSettings.endAngle = 2 * Math.PI;
                            graphSettings.transitionDelay = 0;
                            graphSettings.transitionDuration = 1500;
                            graphSettings.legendSize = 18;
                            graphSettings.legendSpacing = 4;
                            graphSettings.legendXOffset = -4;
                            break;
                        default:
                            console.log('Default preset!');

                    }

                    var svg = d3.select(element[0])
                        .append('svg')
                        .attr('height', graphSettings.graphHeight)
                        .attr('width', graphSettings.graphWidth)
                        .append('g')
                        .attr('transform', 'translate(' + graphSettings.outerRadius + ', ' + graphSettings.outerRadius + ')');

                    var arc = d3.svg.arc()
                        .innerRadius(graphSettings.innerRadius)
                        .outerRadius(graphSettings.outerRadius);

                    var pie = d3.layout.pie()
                        .value(function(d) {
                            return d.count;
                        })
                        .startAngle(graphSettings.startAngle)
                        .endAngle(graphSettings.endAngle)
                        .sort(graphSettings.sortMethod);

                    var path = svg.selectAll('path')
                        .data(pie(scope.data))
                        .enter()
                        .append('path')
                        .attr('fill', function(d) {
                            return graphSettings.color(d.data.label);
                        })
                        .transition().delay(graphSettings.transitionDelay).duration(graphSettings.transitionDuration)
                        .attrTween('d', function(d) {
                            var i = d3.interpolate(d.startAngle + 0.1, d.endAngle);

                            return function(t) {
                                d.endAngle = i(t);

                                return arc(d);
                            };
                        });

                    var legend = svg.selectAll('.legend')
                        .data(graphSettings.color.domain())
                        .enter()
                        .append('g')
                        .attr('class', 'legend')
                        .attr('transform', function(d, i) {

                            var height = graphSettings.legendSize + graphSettings.legendSpacing;
                            var offset = height * graphSettings.color.domain().length / 2;
                            var x = graphSettings.legendXOffset * graphSettings.legendSize;
                            var y = i * height - offset;

                            return 'translate(' + x + ', ' + y + ')';
                        });

                    // Legend shit
                    legend.append('rect') // LOL rekt
                        .attr('height', graphSettings.legendSize)
                        .attr('width', graphSettings.legendSize)
                        .style('fill', graphSettings.color); // This is dependent on the color domain being set previously

                    legend.append('text')
                        .attr('x', graphSettings.legendSize + graphSettings.legendSpacing)
                        .attr('y', graphSettings.legendSize - graphSettings.legendSpacing)
                        .style('font-family', 'FontAwesome')
                        .text(function(d) {
                            return d;
                        });
                });
            }
        };
    });
};