ErmannoS
ErmannoS

Reputation: 315

Rotation with transition

As stated in previous questions (for example d3.js Odd Rotation Behavior), when you want to rotate an SVG object on its place you should use

.attr('transform','rotate(45,100,100)')

where the first number is the rotation degrees, and the other two are the coordinates of the rotation origin.

The problem here is that I want to execute the rotation inside a transition:

.transition()
.attr('transform', 'rotate(45,100,100)')
.duration(300)

and I get a strange behaviour, I can see a translation before the expected rotation. You can see the result here: http://jsfiddle.net/uwM8u/121/

Is there a better way to obtain this?

Upvotes: 0

Views: 216

Answers (2)

Robert Longson
Robert Longson

Reputation: 124059

Add a parent <g> element with the translation so you are actually rotating the shape about the origin.

var svg = d3.select("body")
            .append("svg")
            .attr("width", 400)
            .attr("height", 300);
        svg         
            .append("text")
            .text("click the square")
            .attr("x", w/2)
            .attr("y", w/2)
        svg
            .append("g")
            .attr("transform", "translate(" + diamond.x + "," + diamond.y +")")
            .append("rect")
            .attr("transform", "rotate(" + rotation + ")")
            .attr("x", -diamond.width / 2)
            .attr("y", -diamond.width / 2)
            .attr("height", diamond.width)
            .attr("width", diamond.width)
            .attr("fill", "teal")
            .on("mousedown", function(){
              d3.select(this)
                  .transition()
                  .attr("transform", "rotate("+ (rotation+=45) +")")
                 .duration(300)           
            });

or as a jsfiddle

Upvotes: 1

Lars Kotthoff
Lars Kotthoff

Reputation: 109232

The D3 way to do this is to use a custom tween function, which in this case is a simple string interpolation:

.attrTween("transform", function() {
  return d3.interpolateString(d3.select(this).attr("transform"),
      "rotate(" + (rotation+=45) + "," +
        (diamond.x+diamond.width/2) + "," +
        (diamond.y+diamond.width/2) + ")");
})

Complete demo here.

Upvotes: 3

Related Questions