Jump to content
Search Community

SVG Image out of center after scaling

sabertooth test
Moderator Tag

Go to solution Solved by mvaneijgen,

Recommended Posts

Hello all, 

 

I am sitting on a scale topic right now. I tried it all and watched every video but came not up with a proper soluting. 
My problem is as follwos: 

I am animating paths on a map SVG-image. at the end I have a "scrolltrigger" set that scales the div element with the map and the paths inside. This is working fine until the screen size changes. Without the scaling, the map image is centered as it should be. Once I scale the div with the map image inside it is not centered anymore. E.g. on a mobile you can only see parts of the map after scaling.  Does anyone here knows a way to ensure the div stays centered (on any device) even after scaling?


Here is the code I am using for that: 


gsap.to('.image-wrap', {
  scale: 1.4,
  duration: 20,
  scrollTrigger: {
    trigger: '.image-wrap',
    scrub: 10,
    start: "bottom -250%",
    transformOrigin: "50% 50%",
  }
})


To center the warpper I use this code. It is working fine, but the scaling sets it off:

 

  // move .image-wrap so that it follows .cen.
  gsap.ticker.add(() => {
    gsap.to(".image-wrap", {
      duration: 0.5,
      x: -gsap.getProperty("#cen", "x"),
      y: -gsap.getProperty("#cen", "y")
    });
  });

 

  // center the wrapper using left and top on initial load and any resize
  window.onload = window.onresize = () => {
    gsap.set(".image-wrap", {
      left: window.innerWidth / 2,
      top: window.innerHeight / 2
    });
  };
}

Link to comment
Share on other sites

Hi @sabertooth welcome to the forum!

 

Hard to figure out what is going on without seeing the code in action, have you tried setting the transformOrigin: "center center" in GSAP? If that doesn't help could you maybe include a minimal demo so that we can dive directly into the code and see what is going on. Hope it helps and happy tweening! 

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo:

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

  • Like 1
Link to comment
Share on other sites

Thank your for your response @mvaneijgen. I tried to make a codepen but it is not working.
Maybe you can still make any use out of it? I tried to get it to run but it wont work.... I am newbie therefore I would need some help. I hope my problem is only a small one but I am trying to solve it since 3 days no without any success. 

See the Pen WNmOMzb by Peter-Paul-the-sans (@Peter-Paul-the-sans) on CodePen

Link to comment
Share on other sites

We'd love to help, but vague details like 'it's broken' or 'it doesn't work' are very difficult for people to help with. Here are some tips that will increase your chances of getting a relevant answer:

  • A clear description of the expected result - "I am expecting the purple div to spin 360degrees"
  • A clear description of the issue -  "the purple div only spins 90deg"
  • A list of steps for someone else to recreate the issue - "Open the demo on mobile in IOS safari and scroll down to the grey container" 
  • A minimal demo - if possible, using no frameworks, with minimal styling, only include the code that's absolutely necessary to show the issue. Please don't include your whole project. Just some colored <div> elements is great.

If you'd like more help, please make sure you provide a very clear minimal demo that illustrates the problem. I couldn't tell by looking at your CodePen what you're trying to do. The map was way too big and I don't really understand the effect you're going for. 

 

Also, this definitely looks problematic to me: 

gsap.ticker.add(() => {
  gsap.to(".image-wrap", {
    duration: 0.5,
    x: -gsap.getProperty("#cen", "x"),
    y: -gsap.getProperty("#cen", "y")
  });
});

Literally on every single tick (60 times per second), you're creating an entirely new tween for the same properties of the same element, so you'll have about 30 of them all fighting for control of the same properties at any given time. That's extremely inefficient. I'm sure there's a better way to accomplish what you're attempting there. Maybe find in your code where you're changing the "#cen" x/y properties, and fire off a tween like this at that point and make sure you set overwrite: "auto" (or true if you want it to kill all other tweens of the same element).

 

Good luck!

Link to comment
Share on other sites

  • Solution

I think the issue is your SVG. I've never worked with SVGs where another SVG gets loaded as an image. I've removed some of your code to see what the SVG is doing and as you can see it is really wide and the subject is not in the middle. My advise would be modify your SVG so that everything is at a known position (eg the middle) and base you're code on that. Trying to fix the issues inside an SVG with code will result in a bad time. 

 

See the Pen WNmOYZp by mvaneijgen (@mvaneijgen) on CodePen

 

If I remove some of the SVG properties to get it to behave a little bit beter, now it is in the middle of the SVG and thus its would be much easier to add some CSS and JS to transform it from a position to something new.  When working with SVGs the hardest part will be to prepare the SVG for animating and then the GSAP code will be trivial. Hope it helps and happy tweening! 

 

See the Pen QWogZoN?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

  • Like 2
Link to comment
Share on other sites

Hi,

 

On top of Mitchel's great advice we strongly recommend NOT animating the trigger element

gsap.to(".image-wrap", {
  scale: 1.4,
  duration: 20,
  scrollTrigger: {
    trigger: ".image-wrap",
    scrub: 10,
    start: "bottom -250%",
    onEnter: (self) => {
      gsap.set(self.target, {
        transformOrigin: "50% 50%",
        xPercent: 70,
        yPercent: -50
      });
    }
  }
});

// Move .image-wrap to follow .cen
gsap.ticker.add(() => {
  gsap.to(".image-wrap", {
    duration: 0.5,
    x: -gsap.getProperty("#cen", "x"),
    y: -gsap.getProperty("#cen", "y")
  });
});

You have basically two different GSAP instances animating the same element that is being used as a trigger by ScrollTrigger and on top of that you're animating it on the Y axis with scale and Y. That could lead to unexpected behaviour. I'd recommend you to keep the element with the class image-wrap as the trigger but animate the actual image inside the SVG tag.

 

Happy Tweening!

  • Like 2
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.
×
×
  • Create New...