angularjs - Data update fails for a D3.js chart Angular directive -
for front-end project need visualize data in histogram format. want use custom reusable d3.js chart this. frontend in written in angular 1 , chart angular directive made. custom d3.js chart kept in separate js-file , called in directive.
custom chart
d3.custom = {}; d3.custom.barchart = function module() { var margin = {top: 20, right: 20, bottom: 40, left: 40}, width = 300, height = 300, gap = 0, ease = 'cubic-in-out'; var svg, duration = 1000; function exports(_selection) { _selection.each(function(_data) { var chartw = width - margin.left - margin.right, charth = height - margin.top - margin.bottom; var color = '#c94635'; var formatcount = d3.format(",.0f"); var max = d3.max(_data); var min = d3.min(_data); console.log(max); var x1 = d3.scale.linear() .domain([0, 100]) // .domain([min, max]) // alternative domain based on data .range([0, chartw]); // generate histogram using uniformly-spaced bins. var bins = d3.layout.histogram() .bins(x1.ticks(25)) (_data); console.log(bins); var ymax = d3.max(bins, function(d){return d.length}); var ymin = d3.min(bins, function(d){return d.length}); var colorscale = d3.scale.linear() .domain([ymin, ymax]) .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]); var y1 = d3.scale.linear() .domain([0, ymax]) .range([charth, 0]); var xaxis = d3.svg.axis() .scale(x1) .orient('bottom'); var yaxis = d3.svg.axis() .scale(y1) .orient('left'); if(!svg) { svg = d3.select(this) .append('svg') .classed('chart', true); var container = svg.append('g').classed('container-group', true); container.append('g').classed('chart-group', true); container.append('g').classed('x-axis-group axis', true); container.append('g').classed('y-axis-group axis', true); } svg.transition().duration(duration).attr({width: width, height: height}) svg.select('.container-group') .attr({transform: 'translate(' + margin.left + ',' + margin.top + ')'}); svg.select('.x-axis-group.axis') .attr({transform: 'translate(0,'+charth+')'}) .call(xaxis); svg.select('.y-axis-group.axis') .call(yaxis); bars = svg.select('.chart-group') .selectall('.bar') .data(bins) bars.enter().append('g') .attr("class","bar") .attr("transform", function(d) {return "translate(" + x1(d.x) + "," + y1(d.y) + ")";}) bars.append("rect") .attr("x",0) .attr("width", (x1(bins[0].dx) - x1(0)) - 1) .attr("height", function(d) { return charth - y1(d.y); }) .attr("fill", function(d) { return colorscale(d.y);}); bars.append("text") .attr("dy", ".75em") .attr("y", -12) .attr("x", (x1(bins[0].dx) - x1(0)) / 2) .attr("text-anchor", "middle") .text(function(d) { return formatcount(d.y); }); bars.transition() .duration(duration) .ease(ease) .attr("x", function(d,i) {return x1(i);}) .attr("y", function(d,i) {return y1(i);}) .attr("height", function(d,i) {return charth - y1(i);}); bars.exit().remove(); duration = 500; }); } return exports; }; the directive
(function () { 'use strict'; angular .module('app') .directive('barchart', function(){ var chart = d3.custom.barchart(); return { restrict: 'e', replace: true, template: '<div class="chart"></div>', scope:{ data: '=data', }, link: function(scope, element, attrs) { var chartel = d3.select(element[0]); scope.$watch('data', function (newval, oldval) { chartel.datum(newval).call(chart); }); } } }) }()); on first time $scope.data changed chart appears , there no problems. if selecte second file, causing $scope.data change, chart updated; yet previous bars remain , new bars start previous bar ended.(see figure)
i'm sure problem somewhere in custom chart js-file. more specifically, element in element not removed upon data change , additional element added. looks bad since translation of element specific data. how can update code work?
Comments
Post a Comment