使用angularjs和d3.js在一个页面中显示多个图形

时间:2015-01-28 09:39:34

标签: javascript angularjs d3.js

我刚开始学习AngularJS和D3.js来绘制条形图。我成功地在一个页面中绘制了一个条形图。但是我有一个问题是用不同的数据绘制多个图表。例如:我的app.js如下所示:

// Module name to be included in html app
var app = angular.module('App', []);

// FundamoCtrl controller which holds the data from the JSON
app.controller("FundamoCtrl", function($scope) {

    $scope.tags = [
      {'#text': "author-vimal",    '@pass':  4},
      {'#text': "author-raj",      '@pass':  8},
      {'#text': "tt-positive",     '@pass': 15},
      {'#text': "tt-negative",     '@pass': 16},
      {'#text': "author-selvam",   '@pass': 23},
      {'#text': "author-inba",     '@pass': 42}
    ];

});

// Custom filter for the json data
app.filter('filterData', function() {

    return function(data, searchFor) {
        var property = Object.keys(searchFor)[0];
        var result = [];

        for (var i = 0; i < data.length; i++) {
            if (data[i][property].indexOf(searchFor[property]) > -1) {
                result.push(data[i]);
            }
        }

        return result;
    };

});

// Bar Graph to show the result
app.directive('barGraph', [
    '$filter',
    function($filter) {
        return {
            restrict: 'EA',
            scope: {
                data: '=',
                filtername: '=',
                filtervalue: '=',
            },
            link: function(scope, element, attrs) {
                var margin = {top: 20, right: 30, bottom: 30, left: 40}, 
                    width = 500 - margin.left - margin.right,
                    height = 300 - margin.top - margin.bottom;

                var x = d3.scale.ordinal()
                                .rangeRoundBands([0, width], .1);
                var y = d3.scale.linear()
                                .range([height, 0]);

                var xAxis = d3.svg.axis()
                                .scale(x)
                                .orient("bottom");
                var yAxis = d3.svg.axis()
                                .scale(y)
                                .orient("left")
                                .ticks(5);

                var svg = d3.select(element[0])
                                .append("svg")
                                .attr("class", "chart");

                scope.render = function(data) {

                    x.domain(data.map(function(d) { return d['#text']; }));
                    y.domain([0, d3.max(data, function(d) { return d['@pass']; })]);

                    var chart = d3.select(".chart")
                                .attr("width", width + margin.left + margin.right)
                                .attr("height", height + margin.top + margin.bottom)
                                .append("g")
                                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                    var bar = chart.selectAll("g")
                                .data(data)
                                .enter()
                                .append("g")
                                .attr("transform", function(d, i) { return "translate(" + x(d['#text']) + ", 0)"; });

                    bar.append("rect")
                        .attr("class", "rect-bar")
                        .attr("y", function(d) { return y(d['@pass']); })
                        .attr("height", function(d) { return height - y(d['@pass']); })
                        .attr("width", x.rangeBand());

                    bar.append("text")
                        .attr("x", x.rangeBand() / 2)
                        .attr("y", function(d) { return y(d['@pass']) + 15; })
                        .attr("dy", ".5em")
                        .text(function(d) { return d['@pass']; })
                        .attr("class", "bar-text");

                    chart.append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + height + ")")
                        .call(xAxis);

                    chart.append("g")
                        .attr("class", "y axis")
                        .call(yAxis)
                        .append("text")
                        .attr("transform", "rotate(-90)")
                        .attr("y", 0 - margin.left)
                        .attr("x", 0 - (height / 2))
                        .attr("dy", "1em")
                        .style("text-anchor", "middle")
                        .text("Pass Count");
                };

                scope.$watch('data', function(data) {
                    data = $filter(scope.filtername)(data, scope.filtervalue);
                    scope.render(data);
            }, true);
            }
        };
    }
]);

在我的身体部分下的html模板中,我的内容如下:

<div ng-controller="MyCtrl">
    <bar-graph id="bar1" data="tags" filtername="'filterData'" filterValue="{'#text': 'author-'}"></bar-graph>

    <bar-graph id="bar2" data="tags" filtername="'filterData'" filterValue="{'#text': 'tt-'}"></bar-graph>
</div>

在输出中,bar2散布在bar1的顶部。我想把bar2放在bar1旁边,我无法做到。请帮我解决这个问题。

有关详细信息,请参阅此Plunker

1 个答案:

答案 0 :(得分:2)

好的,所以我发现问题所在。我将g标记附加到class属性,其中类值为chart。因此它需要第一个chart并一次又一次地附加到同一个图表。所以一团糟。

现在我正在创建一个动态id,它将在运行时附加到svg元素,解决了上述问题。

有关详细信息,请参阅Plunker