1

バックグラウンド

D3.jsで再利用可能なチャートオブジェクトを作成しようとしています。chart()縦棒グラフを作成する関数を設定しました。いずれかの列のclickイベントで、グラフはランダムな数のデータポイントを含む新しいランダムデータ配列で更新されます(つまり、元のグラフは8列である可能性がありますが、更新時に20列または4列である可能性があります) 。

問題

元のデータセットに8つのデータポイント(したがって8つの列)があるとします。ランダムなデータでグラフを更新すると、列の高さが新しい値に適切に調整されますが、新しいバーは追加されません。さらに、列の幅はコンテナの幅と新しいデータポイントの数に合わせて適切に調整されますが、そのデータポイントの数が元のセットより少ない場合、元のデータセットの列の一部は次のように残ります。データポイントの数が元のデータ以上です。

私の最終目標は、新しいデータを動的に追加するか、新しいデータ数の範囲外の古いデータを動的に削除することです。

動作のjsfiddleを作成しました。私が説明している動作を確認するには、列を数回クリックする必要がある場合があります。さらに、以下にコードを貼り付けました。

前もって感謝します!

function chart(config) {
    
    // set default options
    var defaultOptions = {
        selector: '#chartZone',
        class: 'chart',
        id: null,
        data: [1,2,6,4, 2, 6, 7, 2],
        type: 'column', 
        width: 200,
        height: 200,
        callback: null,
        interpolate: 'monotone'
    };

    // fill in unspecified settings in the config with the defaults
    var settings = $.extend(defaultOptions, config);
        
    function my() { // generate chart with this function        
    
        var w = settings.width,
            h = settings.height,
            barPadding = 3,
            scale = 10,
            max = d3.max(settings.data);        
    
        var svg = d3.select(settings.selector) // create the main svg container
            .append("svg")
            .attr("width",w)
            .attr("height",h);
    
        var y = d3.scale.linear().range([h, 0]),
            yAxis = d3.svg.axis().scale(y).ticks(5).orient("left"),
            x = d3.scale.linear().range([w, 0]);
                    
        y.domain([0, max]).nice();
        x.domain([0, settings.data.length - 1]).nice();        

        var rect = svg.selectAll("rect")
          .data(settings.data)
          .enter()
          .append("rect")
          .attr("x", function(d,i) {
            return i * (w / settings.data.length);
          })
          .attr("y", function(d) {
            return h - h * (d / max);
          })
          .attr("width", w / settings.data.length - barPadding)
          .attr("height", function(d) {
            return h * (d / max);
          })
          .attr("fill", "rgb(90,90,90)");
                      
        svg.append("svg:g")
           .attr("class", "y axis")
           .attr("transform", "translate(-4,0)")
           .call(yAxis);        
               
        svg.on("click", function() {
            var newData = [], maxCap = Math.round(Math.random() * 100);
                    
            for (var i = 0; i < Math.round(Math.random()*100); i++) {
                var newNumber = Math.random() * maxCap;
                newData.push(Math.round(newNumber));                
            }    
        
            newMax = d3.max(newData);
        
            y.domain([0, newMax]).nice();
        
            var t = svg.transition().duration(750);
        
            t.select(".y.axis").call(yAxis);
       
            rect.data(newData)
                 .transition().duration(750)
                 .attr("height", function(d) {
                    return h * (d / newMax);
                 })
                 .attr("x", function(d,i) {
                    return i * (w / newData.length);
                 })
                 .attr("width", w / newData.length - barPadding)
                 .attr("y", function(d) {
                    return h - h * (d / newMax);
                 });
            });
        }

    my();

    return my;

}

var myChart = chart();
4

1 に答える 1

3

ここでは実際にいくつかのことが起こっています。ご指摘のとおり、新しいデータ範囲外のデータは削除されませんが、既存のデータ範囲外の新しいデータは追加されません。これはすべて、コードで変更する選択と関係があります。更新関数は、enter()およびexit()選択を使用してこれらを処理する必要があります。「結合を使用した思考」を参照してください。

更新されたフィドルは次のとおりです:http://jsfiddle.net/LPtTm/11/

于 2012-06-24T18:28:19.977 に答える