给定下面的代码。我能够创建一个由随机数据填充的条形图,并使其正确显示。不幸的是,对我来说,我无法获得update
图形的正确渲染。
轴似乎正在相应地更新,但是图形的条形图未相对于其轴显示在正确的位置。下面有一个JSFiddle来说明问题。您会注意到沿x轴在各个位置渲染的条。
var Chart = (function (){
function Chart(options){
this.chart = d3.select(options.el);
this.margin = options.dimensions.margin;
this.height = options.dimensions.height;
this.width = options.dimensions.width;
this.data = options.data;
}
return Chart;
}());
var BarChart = (function(){
function BarChart(options){
Chart.call(this, options);
this.xscale;
this.vguidescale;
this.vaxis;
this.haxis;
this.height = this.height - this.margin.top - this.margin.bottom;
this.width = this.width - this.margin.left - this.margin.right;
this.barcolors = createBarColors(options.barcolors);
this.verticalTickCount = options.verticalTickCount;
this.horizontalTickRangeCount = options.horizontalTickRangeCount || 10;
this.chart = this.chart
.append('svg')
.attr('class', 'metric-chart')
.attr('width', this.width + this.margin.left + this.margin.right)
.attr('height', this.height + this.margin.top + this.margin.bottom)
.append('g')
.attr('class', 'metric-chart__chart-bar')
.attr('transform', 'translate('+ this.margin.left +', '+ this.margin.top +')');
this.vguide = d3.select('svg').append('g');
this.hguide = d3.select('svg').append('g');
}
BarChart.prototype = Chart.prototype;
BarChart.prototype.update = function(data) {
var that = this;
this.xscale = _getAxisScaleX(data, this.width);
this.yscale = _getAxisScaleY(data, this.height);
this.bars = this.chart.selectAll('rect')
.data(d3.values(data))
.order();
this.bars.remove()
this.bars.enter()
.append('rect')
.style('fill', function(d,i) { return that.barcolors[i % that.barcolors.length]; })
.attr('width', that.xscale.rangeBand())
.attr('x', function(d,i) {
return that.xscale(i);
})
.attr('height', 0)
.attr('y', this.height)
.transition()
.attr('height', function(d) { return that.yscale(d); })
.attr('y', function(d) {
return that.height - that.yscale(d);
})
.duration(1500)
.ease('elastic');
this.bars.exit().transition().attr('height', 0).remove();
this.vguidescale = _getVerticalGuideScale(data, this.height);
this.haxis = d3.svg.axis()
.scale(this.xscale)
.orient('bottom')
.tickValues(this.xscale.domain().filter(function(d, i) {
var remainder = i % that.horizontalTickRangeCount;
return remainder === 0;
}));
this.vaxis = d3.svg.axis()
.scale(this.vguidescale)
.orient('left')
.ticks(this.verticalTickCount);
this.vguide
.attr('transform', 'translate(' + this.margin.left + ', ' + this.margin.top + ')')
.attr('class', 'metric-chart__vert-guide');
this.hguide
.attr('transform', 'translate(' + this.margin.left + ', ' + (this.height + this.margin.top) + ')')
.attr('class', 'metric-chart__horz-guide');
this.vaxis(this.vguide);
this.haxis(this.hguide);
};
function _getAxisScaleX (data, width) {
return d3.scale.ordinal()
.domain(d3.range(0, data.length))
.rangeBands([0, width], 0.2);
}
function _getAxisScaleY (data, height) {
return d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, height]);
}
function _getVerticalGuideScale (data, height) {
return d3.scale.linear()
.domain([0, d3.max(data)])
.range([height, 0]);
}
function createBarColors(colors){
return colors || ['#363636','#565656', '#868686'];
}
return BarChart;
}());
用法:
var chartDimensions = {
margin : { top: 10, right: 10, bottom: 25, left: 25 },
height : 200,
width : 500
}, chartoptions;
chartoptions = {
el : '.graph',
data: genRandomArray(0, 50),
dimensions : chartDimensions,
verticalTickCount : 10,
horizontalTickRangeCount : 5
};
/* generate bar chart and update on an interval ... */
var chart = new BarChart(chartoptions);
(function updateChart(){
chart.update(genRandomArray(0, genrandom(10, 90)));
setTimeout(updateChart, 4000);
}());
问题演示:
我认为您稍微误用了D3选择的概念:当您this.bars = ... .data() ...
选择更新选择时,即所有值从此以后发生变化的元素都结束了。在该选择上,您调用了.remove()
,表示应删除已更改的元素。这显然不是您想要的。之后,您可以正确地处理enter()
和exit()
选择,添加新元素并删除不再需要的旧元素。如果仅将第一个呼叫移至呼叫this.bars.remove()
之前this.bars.enter()
,则看起来更像您可能想要的:尾部(条形数量的更改)按预期方式工作。只是,磁头仍未正确更新。为此,您将需要使用之前的更新选择。enter()
调用,以修改杆的相应的属性(例如x
,y
,height
),也许使用过渡。
这是更新的小提琴。它仍然看起来并不完美,因为每当条形数量发生变化时,您都会更改x比例。因此,更换杆需要水平移动,而退出的杆则不能同步移动,因此这两个选择会短暂重叠。您可能应该考虑在单独的过渡中更新轴。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句