Rotate SVG elements

A general solution to the problem of getting SVG rotation animations to work cleanly without wobble.

by rdickert

HTML

<svg>
    <g class="single-rect">
        <g class="rect-container">
            <rect class="rotate-me" width=200 height=100 />
        </g>
    </g>
    
    <g class="group">
        <g class="g-container">
            <g class="rotate-me">
                <rect width=200 height=100 />
                <rect width=200 height=100 x=250 />
            </g>
        </g>
    </g>
</svg>

CoffeeScript

# Clean SVG rotations - general solution
# See explanation at http://stackoverflow.com/a/14883942/406226


centerToOrigin = (el) ->
    # Returns transform coordinates to center the object or group on the origin
    # source http://japhr.blogspot.com/2010/07/always-use-getbbox-for-raphael.html
    boundingBox = el.getBBox()
    return {
        x: -1 * Math.floor(boundingBox.width/2),
        y: -1 * Math.floor(boundingBox.height/2) 
    }
    
#clean rotation - single element
rect = d3.select("rect.rotate-me")
center = centerToOrigin(rect.node())
rect.attr("transform", "translate(#{center.x}, #{center.y})")

d3.select("g.rect-container")
    .transition()
    .duration(1000)
    .attr("transform", "rotate(180)")
d3.select('g.single-rect').attr("transform", "translate(300,100)")


#clean rotation - group of two elements
group = d3.select("g.rotate-me")
center = centerToOrigin(group.node())
group.attr("transform", "translate(#{center.x}, #{center.y})")

d3.select("g.g-container")
    .transition()
    .duration(1000)
    .attr("transform", "rotate(180)")
d3.select('g.group').attr("transform", "translate(300,300) scale(.5)")