1

I have circles that is dynamically generated on my view with different sizes (d3.pack()) . Now I added a click event on it so that as it gets clicked it expands. Now, I want to elegantly reset when another circle is clicked? I did my reset similar to this answer D3 - Resetting an SVG object animation

But here's a snippet of my code

 var objects= [
                { id: '1477', amounts: 7, color: '#ffd800' },
                { id: '1490', amounts: 10, color: '#b65959' },
                { id: '1300', amounts: 90, color: '#ff006e' },
                { id: '4000', amounts: 50, color: '#ffd800' },
                { id: '9000', amounts: 20, color: '#b20101' },
                { id: '1212', amounts: 28, color: '#ff006e' },
                { id: '2323', amounts: 7, color: '#ffd800' }
            ]

 var width = 700,
            height = 800,
            color = d3.scale.category20b(),
            maxDiameter = 500;

        var container = d3.select('.chart')
        var svg = container.append('svg')
                    .attr('width', maxDiameter * 2)
                    .attr('height', maxDiameter)
                    .attr('class', 'bubble')

        var bubble = d3.layout.pack()
                        .sort(null)
                        .size([maxDiameter, maxDiameter])
                         .value(function (d) { return d.size; })
                        .padding(1.5)

        var nodes = bubble
                    .nodes(processData(objects))
                    .filter(function (d) {
                        return !d.children;
                    })

        var gCircle = svg.append('g')
        var circle = gCircle.selectAll('circle')
                        .data(nodes)
                        .enter()
                        .append('circle')
                        .attr('transform', function (d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        })
                        .attr('r', function (d) {
                            return d.r;
                        })
                        .attr('fill', function (d) { return d.color;})
                        .attr('class', function (d) { return d.className; })

    // onclick

    circle.on('click', function (e, i) {
        d3.select(this).transition()
              .attr("x", function (d) {
                  console.log('d x ' + d.x);
                  return d.x;
              })
              .attr("y", function (d) {
                  console.log('d y ' + d.y);
                  return d.y;
              })
              .attr("r", function (d) {
                  console.log('d r ' + d.r);
                  return d3.select(this).attr('r') == d.r ? (d.r * 100) : d.r;
              })
              .duration(500);

        });
    function processData(data) {
            var obj = data;

            var newDataSet = [];

            for (var l = 0; l < obj.length; l++) {
                var objInData= obj[l];
                newDataSet.push({ name: objInData.id, className: objInData.id, size: objInData.amounts, color: objInData.color });
            }
            return { children: newDataSet };
        }
Community
  • 1
  • 1
gdubs
  • 2,724
  • 9
  • 55
  • 102

1 Answers1

1

Before expanding the clicked circle, set all other circles to the initial size:

circle.transition()
    .duration(500)
    .attr('r', function (d) {
        return d.r;
    });

Here is the demo:

 var objects= [
                { id: '1477', amounts: 7, color: '#ffd800' },
                { id: '1490', amounts: 10, color: '#b65959' },
                { id: '1300', amounts: 90, color: '#ff006e' },
                { id: '4000', amounts: 50, color: '#ffd800' },
                { id: '9000', amounts: 20, color: '#b20101' },
                { id: '1212', amounts: 28, color: '#ff006e' },
                { id: '2323', amounts: 7, color: '#ffd800' }
            ]

 var width = 500,
            height = 400,
            color = d3.scale.category20b(),
            maxDiameter = 500;

        var container = d3.select('body')
        var svg = container.append('svg')
                    .attr('width', maxDiameter * 2)
                    .attr('height', maxDiameter)
                    .attr('class', 'bubble')

        var bubble = d3.layout.pack()
                        .sort(null)
                        .size([maxDiameter, maxDiameter])
                         .value(function (d) { return d.size; })
                        .padding(1.5)

        var nodes = bubble
                    .nodes(processData(objects))
                    .filter(function (d) {
                        return !d.children;
                    })

        var gCircle = svg.append('g')
        var circle = gCircle.selectAll('circle')
                        .data(nodes)
                        .enter()
                        .append('circle')
                        .attr('transform', function (d) {
                            return 'translate(' + d.x + ',' + d.y + ')';
                        })
                        .attr('r', function (d) {
                            return d.r;
                        })
                        .attr('fill', function (d) { return d.color;})
                        .attr('class', function (d) { return d.className; })

    // onclick

    circle.on('click', function (e, i) {
    circle.transition().duration(500).attr('r', function (d) {
                            return d.r;
                        })
        d3.select(this).transition()
              .attr("x", function (d) {
                  return d.x;
              })
              .attr("y", function (d) {
                  return d.y;
              })
              .attr("r", function (d) {
                  return d3.select(this).attr('r') == d.r ? (d.r * 2) : d.r;
              })
              .duration(500);

        });
    function processData(data) {
            var obj = data;

            var newDataSet = [];

            for (var l = 0; l < obj.length; l++) {
                var objInData= obj[l];
                newDataSet.push({ name: objInData.id, className: objInData.id, size: objInData.amounts, color: objInData.color });
            }
            return { children: newDataSet };
        }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

PS: instead of expanding to r*100, in this demo the circles are expanding to just r*2.

Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
  • that worked perfectly! thanks!!! btw, i tried adding a movetoback prototype on the circles so that the rest are viewable on top. but it seems like the movetoback happens first and stops the animation to expand. i did this http://stackoverflow.com/questions/14167863/how-can-i-bring-a-circle-to-the-front-with-d3 – gdubs Nov 17 '16 at 16:15
  • If you used d3 v4 you could do that in a single line: `selection.lower();`. – Gerardo Furtado Nov 17 '16 at 16:23