如何使用基于D3的Angular Directive处理更改数据

时间:2015-08-12 18:51:40

标签: javascript angularjs d3.js data-visualization ngresource

下面是一个饼图的Angular指令,我希望在我的应用程序中重用它。该指令放置在由控制器驱动的视图中 - 控制器可以更新在任何时候传递给指令的数据集。

一旦我确定数据已经改变,我需要一个很好的清洁方法来彻底清除我的馅饼并重新绘制新数据。我对我的指令的数据参数有一个$ watch并且它可以工作(将触发价值变化)但是,我似乎无法找到一个好的&干净的方式来处理重绘馅饼。也许更新现有的馅饼更容易;或许用一个新的馅饼更容易完全重新开始。假设现有馅饼的更新最好,我该如何实现?

(是的,我知道这条指令的大部分都没有完整;我只是担心馅饼刷新所以不用担心)

'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;
                        });
                });
            }
        };
    });
};

0 个答案:

没有答案