Jump to content
Search Community

Scroll, zoom and pin into SVG logo

aok test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hi folks, I'm having a bit of an issue trying to figure out how to zoom into an SVG on scroll, which upon ending returns to the regular scroll.

 

I have created a CodePen, which works well but I have an issue in that the scale level is relative to the window size and not the SVG. I'd like it, regardless of browser size, to always completely zoom into the white before ending the ScrollTrigger. Am I making this difficult for myself and is this possible?

See the Pen yLrqdQm by richardcool (@richardcool) on CodePen

Link to comment
Share on other sites

There's two approaches for this. The path of least math would be to use FLIP https://gsap.com/docs/v3/Plugins/Flip/, having your target container set at 500vw (seeing as your target white space is 1/5 the width of the SVG) (for mobile devices you could set a breakpoint for portrait mode). The other approach would be to calculate the amount it needs to scale based on viewport width... The math would look something like: (window.innerWidth / svgElement.offsetWidth) * 5. Note that this would need to be recalculated on each screen resize. (Also note you may need to re-math this for mobile devices.)

  • Like 1
Link to comment
Share on other sites

8 minutes ago, ryan_labar said:

There's two approaches for this. The path of least math would be to use FLIP https://gsap.com/docs/v3/Plugins/Flip/, having your target container set at 500vw (seeing as your target white space is 1/5 the width of the SVG) (for mobile devices you could set a breakpoint for portrait mode). The other approach would be to calculate the amount it needs to scale based on viewport width... The math would look something like: (window.innerWidth / svgElement.offsetWidth) * 5. Note that this would need to be recalculated on each screen resize. (Also note you may need to re-math this for mobile devices.)

Thanks for this, @ryan_labar  – I've never used FLIP before so would need to do some reading but the idea of the other approach, for example, `(window.innerWidth / svgElement.offsetWidth) * 5` makes sense.

Link to comment
Share on other sites

The following seems to work well but on resize it does throw things off. I've implemented some resize checks but maybe that's not enough and needs to update the trigger start/end?

 

const landing = ref(null)
const logo = ref(null)

onMounted(() => {

	let logoToScale = (window.innerWidth / logo.value.$el.getBBox().width) * 5

	const landingResize = () => {
		logoToScale = (window.innerWidth / logo.value.$el.getBBox().width) * 5
	}

	ScrollTrigger.addEventListener('refreshInit', landingResize)

	const timelineHeader = gsap.timeline({
		scrollTrigger: {
			id: "ZOOM",
			trigger: landing.value,
			scrub: true,
			start: "top top",
			end: "+=100% 0",
			pin: true,
			markers: true,
			invalidateOnRefresh: true,
		}
	})

	timelineHeader
	.to(logo.value.$el, {
		scale: logoToScale
	})

})

 

Link to comment
Share on other sites

Hi,

 

Without a minimal demo is hard for us to see what could be the issue, but based on your first demo, this seems more related to your SVG rather than something else. Keep in mind that even if your SVG tag is resized to use the entire height and width of it's parent, the content of the SVG has it's own coordinates system based on the viewbox attribute and the path you have in it. If I was you I'd start backwards, get the SVG scaled up working in different scree sizes and then add GSAP and ScrollTrigger to the mix.

 

Happy Tweening!

Link to comment
Share on other sites

Thanks @Rodrigo – I can update my original post/CodePen with the scale calculation but what is the best method for wanting to update a value in ScrollTrigger so it changes on resize based on my rough example above…

Link to comment
Share on other sites

Hi,

 

If I understand you correctly you can use the invalidateOnRefresh config option ScrollTrigger has. From the ScrollTrigger docs:

invalidateOnRefresh
Boolean - If true, the animation associated with the ScrollTrigger will have its invalidate() method called whenever a refresh() occurs (typically on resize). This flushes out any internally-recorded starting values.

 

You have that in your latest code snippet but not in your demo 🤷‍♂️

 

Finally I'd try to have everything at a large size at the start and then use a from instance that takes the element from a smaller scale to the natural scale/size

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Thanks again, @Rodrigo – with what @ryan_labar kindly shared I've updated the CodePen () and on load it's working perfectly but when I resize it gets out of sync.

 

Am I using the correct methods? I've used `refreshInit` to update the scale but wasn't sure if I needed anything else?

Link to comment
Share on other sites

Sorry but is not clear at all what is wrong/off here, since you haven't specified what is not working after a screen resize. Unfortunately vague descriptions like not working, is broken, wrong, off, etc. Don't tell us exactly what to look at.

 

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

That's fair. Apologies.

 

On load when the user scrolls it zooms into the SVG based on a scale set `logoToScale = (window.innerWidth / logo.getBBox().width) * 5` as suggested by @ryan_labar as this makes sense. This is so on scroll zoom on the animation zooms in far enough to go completely white.

7 hours ago, ryan_labar said:

The other approach would be to calculate the amount it needs to scale based on viewport width... The math would look something like: (window.innerWidth / svgElement.offsetWidth) * 5

However as soon as I resize the browser, which might happen, on scrolling the scaling is off as either scaling too much or too little depending on resizing up or down. I understand why but from my code I believe I'm updating the scaling correctly.

Link to comment
Share on other sites

  • Solution

Hi,

 

Mainly the issue is that when using invalidateOnRefresh with ScrollTrigger your values need to be function based. This is what was happening, invalidateOnRefresh was flushing the starting values of the scale tween, but nothing more. The final value was always the same.

 

This seems to fix the problem:

let logoToScale = () => (window.innerWidth / logo.getBBox().width) * 5;

const timelineHeader = gsap.timeline({
  scrollTrigger: {
    id: "ZOOM",
    trigger: "div.landing",
    scrub: true,
    start: "top top",
    end: "+=100% 0",
    pin: true,
    markers: true,
    invalidateOnRefresh: true
  }
});

timelineHeader.to(logo, {
  duration: 1.5,
  ease: "none",
  scale: () => logoToScale()
});

Here is a fork of your demo:

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

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

7 hours ago, aok said:

so I don't need to use refreshInit at all as we're using `invalidateOnRefresh`? As this is essentially doing exactly that?

Not reallly, your method was making the calculations, but the value being used by GSAP wasn't being updated. GSAP records the initial value of the properties you want to tween and then iterates between that value and the final one you're passing in the config. In order to optimize this process GSAP doesn't do constant read/write operations, it does that once and then just iterates between the values. Invalidating a GSAP instances removes the initial values (the value the element currently has) but not necessarily the target value. If you want to update the target value that's when function based values come in handy, because that tells GSAP to update both the initial and final values in this particular case.

 

Your method was updating the value of a variable, the approach I use is to call a function that returns a value. You could use other approaches to get the same result but using a function is always the cleanest one IMHO.

 

Hopefully this clear things up.

Happy Tweening!

  • Like 1
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...