反转 D3.js 中的数据数组给定 JavaScript 具有键值对的对象

Reversing the Data Array in D3.js Given a JavaScript Object with Key, Val Pair

这是我尝试 D3.js 的第一天。我正在关注一个在线教程,该教程展示了如何在键中传递 .data() 方法以唯一地标识每个具有数据元素的 SVG 元素。我想知道如何使用此 属性 来反转条形图中条形的顺序。我试过更改键的顺序并更改值的顺序。由于某种原因似乎没有任何变化......

<!DOCTYPE html>
<html>

    <meta charset="utf-8">
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <style> 
         #chart svg{
            /* width: 800px;
            height: 400px; */
            display: block;
            background-color: #f7f7f7;
            margin: 0 auto;
        }
        button{
            display: block;  
            margin: 0 auto; 
        }
    </style>

    <body>  
        <div id="chart">
        </div>
        <br/>
        <button id ="reverse" type="button">
            Reverse Array
        </button>
    </body>


    <script>
var data            =   [
    { key: 0, num: 6 },
    { key: 1, num: 20 }
];

var key             =   function(d){
    return d.key;
};

// Create SVG Element
var chart_width     =   800;
var chart_height    =   400;
var bar_padding     =   5;
var svg             =   d3.select( '#chart' )
    .append( 'svg' )
    .attr( 'width', chart_width )
    .attr( 'height', chart_height );

var x_scale         =   d3.scaleBand()
    .domain( d3.range( data.length ) )
    .rangeRound([ 0, chart_width ])
    .paddingInner( 0.05 );
var y_scale         =   d3.scaleLinear()
    .domain([
        0, d3.max(data, function( d ){
            return d.num;
        })
    ])
    .range([ 0, chart_height ]);

// Bind Data and create bars
svg.selectAll( 'rect' )
    .data( data, key )
    .enter()
    .append( 'rect' )
    .attr( 'x', function( d, i ){
        return x_scale( i );
    })
    .attr( 'y', function(d ){
        return chart_height - y_scale(d.num);
    })
    .attr( 'width', x_scale.bandwidth() )
    .attr( 'height', function( d ){
        return y_scale(d.num);
    });

// Events
d3.select( '#reverse' ).on( 'click', function(){
    // do something to reverse the order, not sure what to do here
    svg.selectAll( 'rect' )
        .data( data, key )
        .transition()
        .attr( 'y', function(d ){
            return chart_height - y_scale(d.num);
        })
        .attr( 'height', function( d ){
            return y_scale(d.num);
        });
});


    </script>
</html>

根据 'reversing' 条形图的确切含义,您有多种选择。

如果你想保留按键但反转轴,你可以在x_scale中更改range

var x_scale = d3.scaleBand()
    .domain( d3.range( data.length ) )
    .rangeRound([ chart_width, 0 ])
    .paddingInner( 0.05 );

如果您还想更改底层数组,只需更新键即可:

data = data.map(d => ({
    key: data.length - d.key - 1,
    num: d.num
}));

但您还需要将更改通知d3。使用更新-进入-退出模式,您应该修改示例的最后一个函数:

d3.select( '#reverse' ).on( 'click', function(){
data = data.map((d, i) => ({
    key: data.length - d.key - 1,
    num: d.num
}));
// do something to reverse the order, not sure what to do here
svg.selectAll( 'rect' )
    .data( data )
    .transition()
    .attr( 'x', function( d, i ){
        return x_scale( d.key );
    });
});

最后,用你的例子:

var data            =   [
    { key: 0, num: 6 },
    { key: 1, num: 20 }
];

var key             =   function(d){
    return d.key;
};

// Create SVG Element
var chart_width     =   800;
var chart_height    =   400;
var bar_padding     =   5;
var svg             =   d3.select( '#chart' )
    .append( 'svg' )
    .attr( 'width', chart_width )
    .attr( 'height', chart_height );

var x_scale         =   d3.scaleBand()
    .domain( d3.range( data.length ) )
    .rangeRound([ 0, chart_width ])
    .paddingInner( 0.05 );
var y_scale         =   d3.scaleLinear()
    .domain([
        0, d3.max(data, function( d ){
            return d.num;
        })
    ])
    .range([ 0, chart_height ]);

// Bind Data and create bars
svg.selectAll( 'rect' )
    .data( data, key )
    .enter()
    .append( 'rect' )
    .attr( 'x', function( d, i ){
        return x_scale( i );
    })
    .attr( 'y', function(d ){
        return chart_height - y_scale(d.num);
    })
    .attr( 'width', x_scale.bandwidth() )
    .attr( 'height', function( d ){
        return y_scale(d.num);
    });

// Events
d3.select( '#reverse' ).on( 'click', function(){
    data = data.map((d, i) => ({
        key: data.length - d.key - 1,
        num: d.num
    }));
    // do something to reverse the order, not sure what to do here
    svg.selectAll( 'rect' )
        .data( data )
        .transition()
        .attr( 'x', function( d, i ){
            return x_scale( d.key );
        });
});
#chart svg{
    /* width: 800px;
    height: 400px; */
    display: block;
    background-color: #f7f7f7;
    margin: 0 auto;
}
button{
    display: block;  
    margin: 0 auto; 
}
<!DOCTYPE html>
<html>

    <meta charset="utf-8">
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <body>  
        <div id="chart">
        </div>
        <br/>
        <button id ="reverse" type="button">
            Reverse Array
        </button>
    </body>
</html>

请注意,在上面的示例中,我使用了 ES6 表示法。

最简单的就是将数据数组中的元素取反,然后使用索引得到x坐标

d3.select( '#reverse' ).on( 'click', function(){
    data.reverse();
    svg.selectAll( 'rect' )
        .data( data )
        .transition()
        .attr( 'x', function( d, i ){
            return x_scale( i );
        });
});