Обращение массива данных в D3.js с учетом объекта JavaScript с ключом и парой Val - PullRequest
0 голосов
/ 27 октября 2018

Это мой первый день, когда я пробую 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>

Ответы [ 2 ]

0 голосов
/ 27 октября 2018

самое простое - просто перевернуть элемент в массиве данных и использовать индекс для получения координаты x

d3.select( '#reverse' ).on( 'click', function(){
    data.reverse();
    svg.selectAll( 'rect' )
        .data( data )
        .transition()
        .attr( 'x', function( d, i ){
            return x_scale( i );
        });
});
0 голосов
/ 27 октября 2018

У вас есть много вариантов в зависимости от того, что именно вы подразумеваете под «реверсированием» баров.

Если вы хотите сохранить ключи, но повернуть ось, вы можете изменить range in x_scale:

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.

...