D3.js条形图动画未正确退出

时间:2016-09-16 20:40:51

标签: javascript jquery d3.js

我在D3.js中有一个条形图,如果用户点击了一个显示

的p标签
  

点击此处删除栏

然后它应该删除最左边的栏。对于动画,我希望条形图飞到屏幕的左侧,然后将其他条形放置到正确的位置。我遇到的问题是,最右边的条形图被删除了,另一个条被推到了图形之外,不再能够被查看,看起来条形图的值被切换了。

我创建了一个能够重新创建此问题的jsfiddle:jsFiddle

这里还有执行创建的javascript代码和条形图的动画:

// chart dimensions
var margin   = { top: 20, right: 30, bottom: 20, left: 70 },
    width    =  $('#chart').width() - margin.left - margin.right,
    height   =  $(window).height() / 3.5 - margin.top - margin.bottom;

// color palette for graph
var colors = [ '#4398B5', '#ADC4CC', '#92B06A', '#E09D2A', '#DE5F32' ];

var dataset = [ 100, 200, 300, 400, 500 ];

var xScale = d3.scaleBand()
               .domain( d3.range( dataset.length ) )
               .range( [ 0, width ] )
               .padding( 0.1 );


var yScale = d3.scaleLinear()
               .domain( [ 0, d3.max( dataset )  ] )
               .range( [ height, 0 ] );


var xAxis = d3.axisBottom( xScale );
var yAxis = d3.axisLeft( yScale );

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

svg.selectAll( 'rect' )
   .data( dataset )
   .enter()
   .append( 'rect' )
       .attr('x', function ( d, i ) {
            return xScale( i );
       })
       .attr( 'width', xScale.bandwidth() )
       .attr('fill', function( d, i ) {
           return colors[ i ];
       })
       .attr( 'y', function( d, i ) {
           return yScale( d );
       })
       .attr( 'height', function( d ) {
           return height - yScale( d );
       });

svg.append( 'g' )
   .attr( 'class', 'yAxis' )
   .attr( 'transform', 'translate(0, ' + (-1) + ')')
   .call( yAxis );

d3.select("p")
        .on("click", function() {

            dataset.shift();
            //Update scale domains
            xScale.domain( d3.range( dataset.length ) );
            yScale.domain( [ 0 , d3.max( dataset ) ] );

            //Select…
            var bars = svg.selectAll("rect")
                          .data(dataset );

            bars.transition()
                .duration(500)
                .attr("x", function(d, i) {
                    return xScale(i);
                })
                .attr("y", function(d) {
                    return height - yScale(d);
                })
                .attr("width", xScale.bandwidth())
                .attr("height", function(d) {
                    return yScale(d);
                });

            bars.exit()
                .transition()
                .duration(500)
                .attr("x", -xScale.bandwidth())
                .remove();
            });

非常感谢任何帮助。

谢谢!

1 个答案:

答案 0 :(得分:1)

阅读.data' key function上d3文档的部分。

默认情况下,d3将使用元素索引作为键功能。当您.shift数据时,它认为最后一个索引是退出元素,因为长度减少了一个。解决此问题的正确方法是修改数据,以便每个数据都有一些唯一标识符。你真的想在这里做数据驱动,所以我会做这样的事情:

var dataset = [ 
{
  value: 100,
  color: '#4398B5',
  id: 1
},{
  value: 200,
  color: '#ADC4CC',
  id: 2
},{
  value: 300,
  color: '#92B06A',
  id: 3
},{
  value: 400,
  color: '#E09D2A',
  id: 4
},{
  value: 500,
  color: '#DE5F32',
  id: 5
}];

您的关键功能是:

.data( dataset, function(d){ return d.id; } )

注意,我在数据中添加了一个id,但你也可以使用颜色,只要它是唯一的。

这里有一个快速的refactor,其数据阵列有所改进。