【问题标题】:Reversing the Data Array in D3.js Given a JavaScript Object with Key, Val Pair给定一个带有键值对的 JavaScript 对象,在 D3.js 中反转数据数组
【发布时间】:2018-10-27 09:48:39
【问题描述】:

这是我尝试 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>

【问题讨论】:

    标签: javascript arrays d3.js reverse


    【解决方案1】:

    您有很多选择,具体取决于您“反转”条形的确切含义。

    如果你想保留键但反转轴,你可以在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。使用 update-enter-exit 模式,您应该修改示例的最后一个函数:

    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 表示法。

    【讨论】:

    • 感谢您的及时。通过反转条形,我的意思是让一个像 [1,2,3] 这样的条形数组变成 [3,2,1]。更改 x_scale 是否比更改键(它们的顺序)更习惯?
    • 我更新了我的答案,看看是不是你需要的:)
    【解决方案2】:

    最简单的就是把数据数组中的元素倒过来,用索引得到x坐标

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-08
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 2018-12-22
      • 2018-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多