Jump to content


SVG TweenMax.to animation distorts initial scale and transform values

Moderator Tag
Go to solution Solved by GreenSock,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hey all!


In the attached codepen, my tween causes the element in question (a red treble clef) to become huge before moving. Is there a way to stop it from jumping size and positions like that?


As you can see in the codepen:

setTimeout(function() {
  var clef = document.getElementById('Clef_0_1@1');
  TweenMax.to(clef, 10, {
    x: 100,
    y: 100
}, 1000);

The JavaScript only specifies a translation, but I get the sense that the original position is shifted first and it's clear that the original scale is obliterated.


Many thanks for your help!

See the Pen meLoEe by mikesol (@mikesol) on CodePen

Link to comment
Share on other sites

  • Solution

The problem has to do with the fact that your SVG already has transforms applied, and they're in a format that don't get parsed by CSSPlugin. So, for example, your element has this: 

transform="translate(11.0430, 8.0522) scale(0.0040, -0.0040)"

So when you try tweening that to absolute x and y values, it uses a normal matrix (but your transform tells the element to literally scale down to 0.04% of its normal size). In other words, it returns to its "normal" scale of 1. 


There are several options for solutions:


1) Fix your transforms so that they use a standard matrix() which is parseable by GSAP


2) Run this script that should do it for you (well, it fixes the ones that have translate() and scale() both which seems like it's what's needed in your case):

function normalizeSVGTransforms() {
  var svg = document.querySelectorAll("path, rect, circle, text, ellipse, polyline, polygon"),
      i = svg.length,
      _numbersExp = /(?:(-|-=|\+=)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig,
      node, transforms, numbers;

  while (--i > -1) {
    node = svg[i];
    transforms = node.getAttribute("transform");
    if (transforms.indexOf("translate") !== -1 && transforms.indexOf("scale") !== -1) {
      numbers = transforms.match(_numbersExp) || [];
      node.setAttribute("transform", "matrix(" + numbers[2] + ",0,0," + numbers[3] + "," + numbers[0] + "," + numbers[1] + ")");

(You'd run this once BEFORE you do any tweening. 


But in any case, you should be tweening relative values (so use the "+=" prefix) since your elements already have transforms applied. In other words, if #Clef_0_1@1 already has x:-500 and y:30, and then you tween to x:100, y:100, they'll move a lot more than you may have anticipated because those are absolute values. I think this may be what you wanted:



Also, you could streamline your code and make it more performant:

setTimeout(function() {
  var clef = document.getElementById('Clef_0_1@1');
  TweenMax.to(clef, 10, {
    x: 100,
    y: 100
}, 1000);

TweenMax.to(document.getElementById("Clef_0_1@1"), 10, {
  x: 100,
  y: 100,
  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.