Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rotate an object around the center in d3.js

I have two simple objects in d3.js, they should be circling around the center of the viewport (like planets around the sun).

I am new to d3.js and I know that I have to use transitions but as the planets have to circle all the time and not just on enter or exit I don't know where and how to set the transition.

Here is my current code:

var planets = [
    {d:100,r:2},
    {d:150,r:4}
];

var w = 500, h = 400, svg, circle;

function init(){

    svg = d3.select("#drawArea").append("svg").attr({width: w, height: h});

    var center = {
        x: Math.floor(w/2),
        y: Math.floor(h/2)
    };

    svg.append('circle').attr({
        'cx': center.x,
        'cy': center.y,
        'r': 10,
        'class': 'sun'
    });

    circle = svg.selectAll(".planet")
        .data(planets)
        .enter()
            .append("circle")
                .attr("class", "planet")
                .attr("r", function(s){return s.r});

    circle.attr({
        // distance from the center
        'cx': function(s){ return center.x - s.d; },
        // center of the screen
        'cy': function(s){ return center.y; }
    });

}

And here is a jsfiddle to play around.

like image 386
Marc Avatar asked Feb 14 '13 10:02

Marc


2 Answers

You need to:

  1. Place your planets in g groups in a g that is centered on your sun
  2. Create an d3.timer in which you rotate your group.

For, example of the use of d3.timer see Mike Bostocks Epicyclic Gearing example. Using that example, I put together something similar to what you asked: http://bl.ocks.org/4953593

Core of the example:

  var w = 800, h = 800;
  var t0 = Date.now();

  var planets = [
    { R: 300, r:  5, speed: 5, phi0: 90},
    { R: 150, r: 10, speed: 2, phi0: 190}
  ];


  var svg = d3.select("#planetarium").insert("svg")
    .attr("width", w).attr("height", h);

  svg.append("circle").attr("r", 20).attr("cx", w/2)
    .attr("cy", h/2).attr("class", "sun")

  var container = svg.append("g")
    .attr("transform", "translate(" + w/2 + "," + h/2 + ")")

  container.selectAll("g.planet").data(planets).enter().append("g")
    .attr("class", "planet").each(function(d, i) {
      d3.select(this).append("circle").attr("class", "orbit")
        .attr("r", d.R);
      d3.select(this).append("circle").attr("r", d.r).attr("cx",d.R)
        .attr("cy", 0).attr("class", "planet");
    });

  d3.timer(function() {
    var delta = (Date.now() - t0);
    svg.selectAll(".planet").attr("transform", function(d) {
      return "rotate(" + d.phi0 + delta * d.speed/200 + ")";
    });
  });
like image 180
Jan van der Laan Avatar answered Sep 20 '22 11:09

Jan van der Laan


I know this might come too late. But I do hope this can help future readers if they also are facing the same problem. I created fiddles and add some explanation in here, hope it can help:

http://www.zestyrock.com/data-visualization/d3-rotate-object-around-the-center-object-part-2/

Here is the code:

var start = Date.now();

var mode = 0;

var svg = d3.select("#canvas")
    .append("svg")
    .attr("width", 500)
    .attr("height", 500);

svg.append("circle")
    .attr("r", 50)
    .attr("cx", 250)
    .attr("cy", 250)
    .attr("fill", "#e05038");

var rotateElements = svg.append("g");

rotateElements.append("circle")
    .attr("r", 25)
    .attr("cx", 250)
    .attr("cy", 50)
    .attr("fill", "#f2b632")
    .attr("class", "orangeNode");

rotateElements.append("line")
    .attr("x1", 250)
    .attr("y1", 75)
    .attr("x2", 250)
    .attr("y2", 200)
    .attr("class", "edge")
    .attr("stroke", "grey");


d3.select("#start")
    .on("click", startAnimation);

function startAnimation() {
    if (mode === 0) {
        d3.timer(function() {
            var angle = (Date.now() - start);
            var transform = function() {
                return "rotate(" + angle + ", 250, 250)";
            };
            d3.selectAll(".orangeNode, .edge")
                .attr("transform", transform);

            if (mode === 0) {
                return true;
            } else {
                return false;
            }
        });
        mode = 1;
    } else {
        mode = 0;
    }

}
like image 39
catlovespurple Avatar answered Sep 20 '22 11:09

catlovespurple