Jake
Jake

Reputation: 2912

d3.js: incremental transition translation

I am trying to use d3 transition to translate the below squares incrementally.

First I have 6 squares initially. enter image description here

Then, after pressing update, two squares are added, and it 'pushes' all the original squares to the left. enter image description here

This is the part where I am stuck. I want to, after pressing update again, to add another two squares to the array and push the sequence of squares even further left like below. enter image description here

But my current code below only work from step 1 to 2, and not for 3. Can anyone help? Thanks.

<head>
    <script src="https://d3js.org/d3.v3.min.js"></script> 
</head>


<body style="background-color:black;">
    <button id="update1" class="btn  btn btn-sm">Update</button>
</body>

<script>
    var links = [1,2,3,4,5,6];


    svg = d3.select('body').append("svg")
            .attr("width", 600)
            .attr("height", 80);

    // function to add squares    
    var update = function(){
        rect = svg.append('g').selectAll('rect')
        text = svg.append('g').selectAll('text')


        links
        rect = rect.data(links)
        rect.enter().append("rect")
            .attr("x", function(e, counter){return 100  * (counter)})
            .attr("y", 20)
            .attr({"width":20, "height":20})
            .attr({"fill":'red', "opacity":"1"})


        text = text.data(links)
        text.enter().append('text')
            .attr("x", function(e, counter){return 100  * (counter) + 7})
            .attr("y", 18)
            .attr({"font-size":14, "fill":"white", "font-weight":"bold"})
            .text(function(e) {return e})
    };

    // initial squares
    update()

    // update with two squares
    d3.select("#update1").on("click", function() {
        var update1 = [7,8];

        // insert new data to array
        update1.forEach(function(i){
            links.push(i);
        })

        // remove existing squares in display
        d3.selectAll('svg>g').remove()

        // add new squares
        update()

        shift = update1.length // get no. of new squares
        var translate = "translate(" + -100 * shift + "," + "0" + ')'; // push it by existing no. of new squares
        d3.selectAll('rect,text').transition().attr('transform',translate).duration(1000)
    })

</script>

Upvotes: 1

Views: 224

Answers (1)

REEE
REEE

Reputation: 517

Here's a few problems I could see with your code:

  • You only add links [7, 8] when the '#update1' button is pressed, so that needs to be changed to adding a number that is +1 higher than the last 'link' that was pushed, and one that is +2 higher.
  • When you call your 'update' function, you're running on a larger array but still positioning them based on their index with the 'counter' parameter in the function call for setting the 'x' attribute of the 'rect' and 'text' objects you're creating.

I think I've added the functionality you wanted, here's a codepen: https://codepen.io/anon/pen/MBaoxb?editors=0011

The changes I've made are as follows:

Changed it so that the new links being added can increase based off the last number pushed into the array.

**Line 33:** var update1 = [links[links.length-1] + 1, links[links.length-1] + 2];

Removed the first 2 links from the array (so the position can be set from the index as the code in the 'update' function is currently set up to do).

**Line 56:**     links = links.splice(2, links.length);

Upvotes: 1

Related Questions