Marc Marc - 1 year ago 108
Javascript Question

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 = [

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

function init(){

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

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

'cx': center.x,
'cy': center.y,
'r': 10,
'class': 'sun'

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

// 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.


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:

Core of the example:

  var w = 800, h = 800;
  var t0 =;

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

  var svg ="#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 + ")")

    .attr("class", "planet").each(function(d, i) {"circle").attr("class", "orbit")
        .attr("r", d.R);"circle").attr("r", d.r).attr("cx",d.R)
        .attr("cy", 0).attr("class", "planet");

  d3.timer(function() {
    var delta = ( - t0);
    svg.selectAll(".planet").attr("transform", function(d) {
      return "rotate(" + d.phi0 + delta * d.speed/200 + ")";