How to manipulate translate transforms on a SVG element with javascript in chrome?

user1360990 picture user1360990 · Apr 27, 2012 · Viewed 53k times · Source

I want to manipulate the transform="translate(x,y)" attribute of a SVG element using JavaScript.

So I got this HTML code:

<body>

<svg id="test" preserveAspectRatio="xMidYMid meet" viewBox="0 0 100% 100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <rect transform="translate(100,100)" width="300" height="100" style="fill:rgb(0,0,255);stroke-width:1;stroke:rgb(0,0,0)" />
    <rect transform="translate(400,400)" width="300" height="400" style="fill:red; stroke-width:1; stroke: yellow" />
</svg>

</body>

And this JavaScript code:

var positioner = (function(domUtils){

   var svg = document.getElementById("test");
   var elementOffset = 100;

   function getAbsoluteX(leftElement) {
    return domUtils.getWidth(leftElement) + elementOffset; 
   }

   function getAbsoluteY(topElement) {
    return domUtils.getHeight(topElement) + elementOffset;
   }   

   var rectangles = document.querySelectorAll("rect");
   for(var i = 0; i < rectangles.length; ++i) {
    var spaceLeft = 0;
    if(i > 0) {
      spaceLeft = getAbsoluteX(rectangles[i-1]);
    }
    var rect = rectangles[i];
    var attrValue = "translate(" + spaceLeft + ", 100)";
    rect.setAttribute('transform', attrValue);
   };
 })(domUtils);

Where getAbsoluteX() is a self-defined function.

It's working nice in firefox but not in chrome. Anyone knows a workaround or how to solve this?

Thanks. Regards.

Answer

Phrogz picture Phrogz · Apr 27, 2012

There are two ways to get/set transform values for SVG elements in Chrome, Firefox, IE, or any standards-fearing SVG user agent:

Handling Transforms via Attributes

// Getting
var xforms = myElement.getAttribute('transform');
var parts  = /translate\(\s*([^\s,)]+)[ ,]([^\s,)]+)/.exec(xforms);
var firstX = parts[1],
    firstY = parts[2];

// Setting
myElement.setAttribute('transform','translate(30,100)');

Pros: Simple to set and understand (same as the markup).
Cons: Have to parse the string value to find what you want; for animated values, can't ask for the base value when the animation is active; feels dirty.

Handling Transforms via SVG DOM Bindings

// Getting
var xforms = myElement.transform.baseVal; // An SVGTransformList
var firstXForm = xforms.getItem(0);       // An SVGTransform
if (firstXForm.type == SVGTransform.SVG_TRANSFORM_TRANSLATE){
  var firstX = firstXForm.matrix.e,
      firstY = firstXForm.matrix.f;
}

// Setting
myElement.transform.baseVal.getItem(0).setTranslate(30,100);

Pros: No need to try to parse strings on your own; preserves existing transform lists (you can query or tweak just a single transformation in the list); you get real values, not strings.
Cons: Can be confusing to understand at first; more verbose for setting simple values; no convenient method for extracting rotation, scale, or skew values from the SVGTransform.matrix, lack of browser support.

You may find a tool I wrote for exploring the DOM helpful in this.

  1. Go to http://objjob.phrogz.net/svg/object/131
  2. Click the "Show inherited properties/methods?" checkbox
  3. See that the SVGRectElement has a transform property that is an SVGAnimatedTransformList.
  4. Click on SVGAnimatedTransformList to see the properties and methods that object supports.
  5. Explore!