Jump to content
GreenSock

samjm

Pinning sections with different html content within a large SVG with scrolltriger

Recommended Posts

Hi all!

 

I'm wondering if you can show me a clue on how to perform the next operation I haven't been able to do.


I have a mega svg on which I want to scroll down and show elements of the svg along with other html elements by pinning multiple sections of the large svg.

At certain position I want to display an image in background while the svg elements appear in front while scrolling, let's say that the svg will be divided in four sections that will show a few animations using the ScrollTrigger. 

 

After some adjustments I've made to the css properties of the svg I've managed to approach a little to what I need but I'm still not sure if I'm going in a correct direction.

 

What I want to achieve is to display text (video, or any other html element) in front and an image in background while scrolling through the large svg by pinnning a section of the svg to display the content, then scroll and pin again to the next section and so on.

 

In my test, basically I have merged an image parallax with an svg pinning animation.

Is there any suggestion or better approach you could advise me to do this.

 

Thanks a lot in advance for your appreciated help!

See the Pen XWzEoby by samjm-the-decoder (@samjm-the-decoder) on CodePen

Link to comment
Share on other sites

Welcome to the forums, @samjm

 

I'm a little fuzzy on exactly what you're asking here. Could you clarify? The simpler and more focused you make your minimal demo, the more likely you'll be to get an answer :) 

 

If there's a GSAP-specific question in there, we'd be glad to help. 

Link to comment
Share on other sites

Hi Jack, thanks for the welcome and answer!

 

I'm sorry for not answering quickly, I have been testing and trying to refine my example in order to make it minimal.

I guess I tried to wrap many things in a single request and as you mentioned, it turned out a little fuzzy to understand.
I hope it can be a little more clear now.

 

Basically I will have a large svg with many elements that will animate while scrolling. Besides, text and images will appear at certain positions, these elements are not part of the svg but are placed in html sections.

 

In my code example I just have an svg with some squares placed in different positions, on the other hand I have a set of sections on which I'm displaying text in front and images (with height of the size of the viewport) on the back of the svg content.

 

The svg part:

<svg id="svg-init" x="0px" y="0px" width="1024px"
     height="2000px" viewBox="0 0 1024 2000" enable-background="new 0 0 1024 2000" xml:space="preserve">
  <g id="square1">
    <rect x="96" y="200" fill="#1A1AFF" width="344" height="223"/>
  </g>
  <g class="marker2">
    <rect x="96" y="500" fill="#1A1AFF" width="50" height="100vh"/>
  </g>
  <g id="square2">
    <rect x="96" y="700" fill="#FF390B" width="344" height="223"/>
  </g>
  <g class="marker3">
    <rect x="96" y="1000" fill="#1A1AFF" width="50" height="100vh"/>
  </g>
  <g id="square3">
    <rect x="96" y="1200" fill="#15FF31" width="344" height="223"/>
  </g>
</svg>


The sections part:

<section id="section_01">
 <!-- some content-->
</section>
<section id="section_02">
 <!-- some content-->
</section>
<section id="section_03">
 <!-- some content-->
</section>

 

The thing I'm having trouble to understand is how to trigger the svg animations in a synchronized manner with the text and images that I have in the sections tags.

 

After some tests I added (as part of the svg) other elements (squares) which I called marker2 and marker3 before the squares in order to use those markers only to trigger the squares movement, I'm not sure if this trick could be a good idea as it works depending on the height I set on these markers or the squares. (in the example above, the movement can bee seen working better when in full size).


Visually the operation works more or less as expected, i.e. the square's movement is triggered when each section appear on the viewport, however is kind of tricky to specify when to trigger the movement as I would like to specify that the square2 should start to move when the section_02 is visible (make the square appear always in the same position when the section is displayed). The marker's trick worked a little but is not so easy to see.

 

I'm wondering if maybe is possible, for instance, use an id of an html section as trigger and when the section appears in the viewport I could have control over the svg elements.

 

Thanks again for your help and hope it can be a little easier to understand!

 

Link to comment
Share on other sites

34 minutes ago, samjm said:

I'm wondering if maybe is possible, for instance, use an id of an html section as trigger and when the section appears in the viewport I could have control over the svg elements.

You can use any HTML element as a trigger, sure. It's totally flexible. You can even use a different endTrigger if you want. 

gsap.to("#svg", {
  rotation: 360,
  scrollTrigger: {
    trigger: "#someDiv",
    ...
  }
});

 

I read your latest post and I'm still pretty fuzzy on what GSAP-specific question you're asking (other than "can I use a non-SVG element as a trigger for animations of an SVG element" - yes). If you still need help, please provide a very minimal demo and ask a pointed question and we'll do our best to answer. 

 

Happy tweening!

Link to comment
Share on other sites

Thanks a lot Jack!

I think I'm still confused on how the trigger element works as part of the scrollable components.


Maybe more specific to gsap and scrollTrigger is that if it's possible to move both svg and html elements as part of the same timeline in a synchronized way, e.g. to display an image that is in a section and animate an element of the svg at the same time when the top of each section reaches 50% of the viewport.

I guess the answer is true but the svg elements should be in a relative position according to each section right?

 

I'll try to make it a little simpler and keep you informed! I just found the sample of:

 

See the Pen qBbBLyB by creativeocean (@creativeocean) on CodePen

on which there is text and images inside the svg, which I think gives more control over the position of all the elements -more or less what I want to achieve-. Do you think this approach could be better instead of having text and images separated from the svg elements?


Thanks again for your help! 
 

Link to comment
Share on other sites

1 hour ago, samjm said:

I guess the answer is true but the svg elements should be in a relative position according to each section right?

 

Sorry, I'm having a really difficult time understanding what you mean. Perhaps it'll help if I explain...

 

ScrollTrigger simply calculates when the trigger element is going to hit the "start" and "end" positions (scrollbar position) and reacts accordingly. So if the trigger is 100px below the bottom of the viewport initially and your start is set to "top bottom" (top of the element hits the bottom of the viewport), ScrollTrigger maps it so that it'll start when the scrollbar moves 100px. 

 

It has absolutely nothing to do with synchronized animations or anything like that. 

 

So I'm struggling to understand what you're trying to do because it almost sounds like you are trying to set up a trigger based on when TWO (or more?) things are hitting a specific spot at the same time(?) 

 

It might help to focus on just your animations first (unrelated to scrolling). Once you get them the way you want, THEN hook them up to ScrollTrigger once they look the way you want.

 

If you still need help, please provide a minimal demo with as little code and as few elements as possible, just to illustrate the problem you're trying to solve.  

Link to comment
Share on other sites

 

Thanks Jack!

 

4 hours ago, GreenSock said:

ScrollTrigger simply calculates when the trigger element is going to hit the "start" and "end" positions (scrollbar position) and reacts accordingly. So if the trigger is 100px below the bottom of the viewport initially and your start is set to "top bottom" (top of the element hits the bottom of the viewport), ScrollTrigger maps it so that it'll start when the scrollbar moves 100px. 

yes! thank you, I think I have it clear so far.

 

3 hours ago, GreenSock said:

So I'm struggling to understand what you're trying to do because it almost sounds like you are trying to set up a trigger based on when TWO (or more?) things are hitting a specific spot at the same time(?) 

I'm sorry, my bad, what I mean is to trigger both things when maybe a third one used as trigger reaches a spot in the the viewport.

 

e.g.

animate both the square1 inside the svg

<svg id="svg-init" x="0px" y="0px" width="1024px" height="2000px">
  <g id="square1">
    <rect x="96" y="200" fill="#1A1AFF" width="344" height="223"/>
  </g>
</svg>

and image_01 when the 50% of section_01used as trigger reaches top of the viewport

<section id="section_01">
 <img id="image_01" src="image.png" /> <!-- image in background with height 100vh -->
 <h1>Section 1</h1>
</section>

The thing here is that the elements in the svg might not always be exactly within the section_01 height size as it is independent of it and might not move at the same time as the image_01 which is in fact within the section_01.

 

I'll focus on that approach, first focus and create the general schema to use both image and svg and then move to ScrollTrigger.

 

Thanks again Jack!

 

 

Link to comment
Share on other sites

4 hours ago, samjm said:

animate both the square1 inside the svg

<svg id="svg-init" x="0px" y="0px" width="1024px" height="2000px">
  <g id="square1">
    <rect x="96" y="200" fill="#1A1AFF" width="344" height="223"/>
  </g>
</svg>

and image_01 when the 50% of section_01used as trigger reaches top of the viewport

<section id="section_01">
 <img id="image_01" src="image.png" /> <!-- image in background with height 100vh -->
 <h1>Section 1</h1>
</section>

 

Sure, that's simple: 

let tl = gsap.timeline({
  scrollTrigger: {
    trigger: "#section_01",
    start: "50% top",
    end: "+=500", // or whatever
    toggleActions: "play none none reverse"
  }
});
tl.to("#square1", {...})
  .to("#image_01", {...}, 0); 

 

4 hours ago, samjm said:

The thing here is that the elements in the svg might not always be exactly within the section_01 height size as it is independent of it and might not move at the same time as the image_01 which is in fact within the section_01.

This is where I get fuzzy.

 

It doesn't matter if those animating things are independent or move at slightly different spots in the timeline that has the ScrollTrigger. 

Link to comment
Share on other sites

  • 4 months later...

hi Jack!

 

I'm sorry I couldn't reply before, has been a few months since I started working on this but I couldn't continue until now. I think I get now why my doubts were fuzzy as I hadn't understand that part, now I've changed my approach a little. Basically, from a large vertical svg I'm using a div as trigger and creating timelines for each item based on the start/end percentages relative to the trigger.

 

Something like:

 

<body>
  <div class="wrapper">
    <svg>
    	<g id="itemX">
          ...
        </g>
		...
    </svg>
  </div>

<script>
var tl = gsap.timeline({
        scrollTrigger:{
          trigger: ".wrapper",
          	...
          start: '15% top',
          end: '30% 80%',
        }
    }).from('#itemX', {drawSVG: 0}, 0);
...
</script>
</body>

 

A result of what I want to achieve can be seen here http://polifonias.com.mx/v4/pruebas/historia-1/

 

do you think this approach is correct?

 

If so, now I have performance issues as the svg can be quite large and have other media on it. I was reading the optimization points from

 

 

and started to doubt if I might be going in the wrong way or if I should maybe consider using PixiJS to improve the rendering process.

 

What do you think about it?

 

Thanks again for you help!

 

Link to comment
Share on other sites

Yes, that looks like a LOT of SVG that's eating up a ton of screen real estate, so you're asking a lot of the browser to render all that. It has nothing to do with GSAP. I'd recommend either using regular images (so it's not vectors whose pixels must be fabricated dynamically) or use something like PixiJS - that will almost surely give you better performance but it's more painful to build.

 

Good luck. 

Link to comment
Share on other sites

Maybe changing vectors to png images but keeping the svg structure as it is?

I have a few images and a foreignObject to place a video inside the svg, I'm thinking if just converting the vector items to png (or webP) images could work?

 

In case of using PixiJS, I saw a little on canvas and using: 

 as initial reference to work with scrollTrigger, but how recommended could it be comparing to the first option.

 

 

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.
×