簡體   English   中英

添加到 D3 條形圖的最后一個元素未排序

[英]Last element added to a D3 bar chart doesn't sort

我是 D3 / Javascript 菜鳥,我正在嘗試創建一個圖表,其中包含添加條的選項(通過更新 > 輸入選擇),然后對它們進行重新排序。

但是,最后添加的酒吧拒絕參與重新排序。

誰能告訴我:a)為什么會發生這種情況 b)如何解決它

請參閱 Codepen: https ://codepen.io/benjamesdavis/pen/JjodJwy ? editors = 1010

            //Width and height
            var w = 900;
            var h = 450;

            var array = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
                            11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];

            dataset=[];             
            for(let i=0; i<array.length; i++)
                {dataset[i] = {"key":i, "value": array[i]}}

            var xScale = d3.scaleBand()
                            .domain(d3.range(dataset.length))
                            .rangeRound([0, w])
                            .paddingInner(0.05);

            var yScale = d3.scaleLinear()
                            .domain([0, d3.max(dataset, d=> d.value)])
                            .range([0, h]);

            //Create SVG element
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width", w)
                        .attr("height", h);



            //Create bars
            svg.selectAll("rect")
               .data(dataset)
               .enter()
               .append("rect")
               .attr("x", function(d, i) {
                    return xScale(i);
               })
               .attr("y", function(d) {
                    return h - yScale(d.value);
               })
               .attr("width", xScale.bandwidth())
               .attr("height", function(d) {
                    return yScale(d.value);
               })
               .attr("fill", function(d) {
                    return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
               });




            //On click, update with new data            
            d3.select("#newBar")
                .on("click", function() {

                    //Add one new value to dataset
                    var maxValue = 25;
                    var newNumber = Math.floor(Math.random() * maxValue);
                    newNumber = {"key":dataset.length, "value": newNumber}
                    dataset.push(newNumber);

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

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

                    //Enter…
                    bars.enter()
                        .append("rect")
                        .attr("x", w)
                        .attr("y", function(d) {
                            return h - yScale(d.value);
                        })
                        .attr("width", xScale.bandwidth())
                        .attr("height", function(d) {
                            return yScale(d.value);
                        })
                        .attr("fill", function(d,i) {
                            return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
                        })
                        .merge(bars)
                        .transition()
                        .duration(500)
                        .attr("x", function(d, i) {
                            return xScale(i);
                        })
                        .attr("y", function(d) {
                            return h - yScale(d.value);
                        })
                        .attr("width", xScale.bandwidth())
                        .attr("height", function(d) {
                            return yScale(d.value);
                        });

                });


            //Re-Sort Bars
            d3.select("#sortBars").on("click",function(){
                d3.shuffle(dataset)

                 bars.data(dataset,d => d.key)
                    .transition(2000)
                    .attr("x", function(d, i) {             
                        return xScale(i);
                    })                                  
                })

具體問題是,當您enter()第 70 行的bars選擇並將其合並到bars 83 行的bars時,您並沒有將新的合並選擇保存回bars 因此,當您在第 104 行重新排序時, bars更新選擇不包含最新的條形。

通常,要記住的是,數據綁定選擇始終是更新選擇,並且選擇(從 D3v4 開始)是不可變的,因此當您這樣做時

bars.enter()
    .<do stuff to just the enter selection>
    .merge(bars) // merge the update and enter selections together
    .<do more stuff to the merged update+enter selections>

bars的值仍然是舊的更新選擇。 如果您以后想用它做更多的事情,您必須明確保存合並的選擇。

bars = bars.enter() // note the assignment to bars!
    .<do stuff to just the enter selection>
    .merge(bars) // merge the update and enter selections together
    .<do more stuff to the merged update+enter selections>

我認為是這樣的,當你定義bars時,它是在add-bars函數的范圍內,而不是re-sort函數,所以首先你需要每次都做select。 然后,您需要確保兩次都使用該密鑰。 這是我對您的代碼的看法:

//寬度和高度 var w = 500; 無功h = 200;

    var array = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
                    11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];

    dataset=[];     

    for(let i=0; i<array.length; i++)
        {dataset[i] = {"key":i, "value": array[i]}}

    var xScale = d3.scaleBand()
                    .domain(d3.range(dataset.length))
                    .rangeRound([0, w])
                    .paddingInner(0.05);

    var yScale = d3.scaleLinear()
                    .domain([0, d3.max(dataset, d=> d.value)])
                    .range([0, h]);

    //Create SVG element
    var svg = d3.select("body")
                .append("svg")
                .attr("width", w)
                .attr("height", h);



    //Create bars
    svg.selectAll("rect")
       .data(dataset)
       .enter()
       .append("rect")
       .attr("x", function(d, i) {
            return xScale(i);
       })
       .attr("y", function(d) {
            return h - yScale(d.value);
       })
       .attr("width", xScale.bandwidth())
       .attr("height", function(d) {
            return yScale(d.value);
       })
       .attr("fill", function(d) {
            return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
       });




    //On click, update with new data            
    d3.select("#newBar")
        .on("click", function() {

            //Add one new value to dataset
            var maxValue = 25;
            var newNumber = Math.floor(Math.random() * maxValue);
            newNumber = {"key":dataset.length, "value": newNumber}
            dataset.push(newNumber);

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

            //Select…
             bars = svg.selectAll("rect")
                       .data(dataset,d => d.key) //make sure you use the key here too!


            //Enter…
            bars.enter()
                .append("rect")
                .attr("x", w)
                .attr("y", function(d) {
                    return h - yScale(d.value);
                })
                .attr("width", xScale.bandwidth())
                .attr("height", function(d) {
                    return yScale(d.value);
                })
                .attr("fill", function(d,i) {
                    return "rgb(0, 0, " + Math.round(d.value * 10) + ")";
                })
                .merge(bars)
                .transition()
                .duration(500)
                .attr("x", function(d, i) {
                    return xScale(i);
                })
                .attr("y", function(d) {
                    return h - yScale(d.value);
                })
                .attr("width", xScale.bandwidth())
                .attr("height", function(d) {
                    return yScale(d.value);
                });

        });


    //Re-Sort Bars
    d3.select("#sortBars").on("click",function(){
        d3.shuffle(dataset)
        bars =  svg.selectAll("rect").data(dataset,d => d.key) //redefine bars, and use the key
            .transition(2000)
            .attr("x", function(d, i) {             
                return xScale(i);
            })                                  
        })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM