How to set transform origin in SVG

If you're like me and want to pan and then zoom with transform-origin, you'll need a little more.

// <g id="view"></g>
var view = document.getElementById("view");

var state = {
  x: 0,
  y: 0,
  scale: 1
};

// Origin of transform, set to mouse position or pinch center
var oX = window.innerWidth/2;
var oY = window.innerHeight/2;

var changeScale = function (scale) {
  // Limit the scale here if you want
  // Zoom and pan transform-origin equivalent
  var scaleD = scale / state.scale;
  var currentX = state.x;
  var currentY = state.y;
  // The magic
  var x = scaleD * (currentX - oX) + oX;
  var y = scaleD * (currentY - oY) + oY;

  state.scale = scale;
  state.x = x;
  state.y = y;

  var transform = "matrix("+scale+",0,0,"+scale+","+x+","+y+")";
  //var transform = "translate("+x+","+y+") scale("+scale+")"; //same
  view.setAttributeNS(null, "transform", transform);
};

Here it is working: http://forresto.github.io/dataflow-prototyping/react/


To rotate use transform="rotate(deg, cx, cy)", where deg is the degree you want to rotate and (cx, cy) define the centre of rotation.

For scaling/resizing, you have to translate by (-cx, -cy), then scale and then translate back to (cx, cy). You can do this with a matrix transform:

transform="matrix(sx, 0, 0, sy, cx-sx*cx, cy-sy*cy)"

Where sx is the scaling factor in the x-axis, sy in the y-axis.


If you can use a fixed value (not "center" or "50%"), you can use CSS instead:

-moz-transform-origin: 25px 25px;
-ms-transform-origin:  25px 25px;
-o-transform-origin: 25px 25px;
-webkit-transform-origin:  25px 25px;
transform-origin: 25px 25px;

Some browsers (like Firefox) won't handle relative values correctly.


svg * { 
  transform-box: fill-box;
}

applying transform-box: fill-box will make an element within an SVG behave as a normal HTML element. Then you can apply transform-origin: center (or something else) as you would normally

that's right, transform-box: fill-box. These days, there's no need for any complicated matrix stuff