NickWoodward Posted September 6 Posted September 6 Hello! Couple of questions if someone has a sec or two please?😊 https://codesandbox.io/p/devbox/7p786f Is there a better way to sync the masking reveal of the text with the pinning here? Obviously it's a bit of a matter of taste, but maybe with the duration of the pinning, or so that at least the reveal happens after the pinning? I've had a bit of a play around, but I'm just mindful of learning bad habits. Also - the responsive splitting - the background text is obviously responsive, but the split text isn't. The docs reference autosplit, but I'm a little confused how to create the splitting animation in the onSplit callback if it's part of a larger timeline? I'm also seeing a lot of the bug in the screenshot - where resizing makes content and triggers 'jump'. I'm just not sure how to debug them tbh Hope I've explained that well enough! Nick
Sam Tremblay Posted September 6 Posted September 6 Hello! Â Instead of calculating each line, you could use background-clip: text on each line, or set up mix-blend-mode with layered elements at different depths. Then, you can animate the background clip using a GSAP stagger based on the section, or apply a specific translate or scale to a div if you go with the mix-blend-mode approach.
Solution Sam Tremblay Posted September 6 Solution Posted September 6 Hello again! Â I do an example for you with background-clip: text. Â You can inspect behavior here:Â https://studiochampgauche.com/demo/ Â Here is my JS: 'use strict'; import React, { useEffect, useRef } from 'react'; import { Link } from 'react-router-dom'; import { gsap } from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; import { SplitText } from 'gsap/SplitText'; import Image from './components/Image'; const Demo = () => { const ref = useRef(null); const innerRef = useRef(null); const containerRef = useRef(null); const textRef = useRef(null); const paragraphRef = useRef([]); useEffect(() => { gsap.registerPlugin(SplitText); let killEvents = []; /* * Pin inner element */ let pinAnimation = ScrollTrigger.create({ trigger: ref.current, start: 'top top', end: 'bottom bottom', pin: innerRef.current, pinSpacing: false, scrub: true }); /* * Split Text */ let split = SplitText.create(paragraphRef.current, { type: 'lines', linesClass: 'line', }); /* * Anim split */ let splitAnimation = gsap.to([paragraphRef.current[0].querySelectorAll('.line'), paragraphRef.current[1].querySelectorAll('.line')], 1, { backgroundPositionY: 0, stagger: .6, ease: 'none', scrollTrigger: { trigger: ref.current, start: 'top top', end: 'bottom bottom', scrub: true } }); killEvents.push(() => { if(pinAnimation){ pinAnimation.kill(); pinAnimation = null; } if(split){ split.revert(); split = null; } if(splitAnimation){ splitAnimation.revert(); splitAnimation = null; } }); return () => { killEvents?.forEach(killEvent => killEvent()); killEvents = []; } }); return( <> <section ref={ref} id="demo-1"> <div ref={innerRef} className="inner"> <div ref={containerRef} className="container"> <div ref={textRef} className="text"> <p ref={el => paragraphRef.current[0] = el}>Lorem ipsum dolor sit amet consectetur adipisicing elit. Excepturi laborum repellendus.</p> <p ref={el => paragraphRef.current[1] = el}>Rerum assumenda dolore neque mollitia praesentium adipisci amet commodi sint aliquid pariatur.</p> </div> </div> </div> </section> <section className="fake" style={{ height: '100svh' }}> <div className="container"> <p>Silence is golden</p> </div> </section> </> ); } export default Demo; Â Here is my SCSS: //@use '../inc/variables' as *; //@use '../inc/functions' as *; //@use '../inc/mixins' as *; #demo-1{ height: 300svh; padding: 0 30px; .inner{ display: flex; height: 100svh; align-items: center; justify-content: center; will-change: transform; .container{ width: 100%; max-width: 1640px; .text{ width: 100%; margin: 0 auto; max-width: 1088px; p{ font-size: 45px; line-height: 140%; //color: transparent; .line{ position: relative; background-image: linear-gradient(to top, #ff0000 50%, #00ff00 0); background-position-y: 100%; background-size: 100% 200%; background-clip: text; color: transparent; .word{ .char{ } } } & + p{ margin: 25px 0 0; } } } } } } Â 1
NickWoodward Posted September 7 Author Posted September 7 Cool effect - I never would have thought of doing it that way. Like how it also handles multiple paragraphs. Thanks! I assume with useGSAP I don't have to set up that killEvents array? And for responsiveness I'd just have to use a screen width value in the useEffect/GSAP dependency array? Thanks again!
Sam Tremblay Posted September 10 Posted September 10 Thanks chief! Â About useGSAP, I don't know because I use all time useEffect. I never install the react part of GSAP. Â And for the responsive, it's depend. You have multiple ways. I love use px/vw/vh units directly in CSS (with clamp & some breakpoints) and gsap.matchMedia in JavaScript for start or kill some animations based on media query. 1
NickWoodward Posted September 27 Author Posted September 27 Sorry to bother you again @Sam Tremblay, but I don't suppose you can see why my implementation of your effect isn't animating please? (it's instantly switching the background position, for all lines). I just can't see why it's not working, looks functionally the same to me? Your working code example:Â https://codesandbox.io/p/devbox/fkgtrg Mine:Â https://codesandbox.io/p/devbox/creed-hero-forked-pzsnfr?workspaceId=ws_3p4VjtDpEFGetZAxu6vymW Â
NickWoodward Posted September 27 Author Posted September 27 ahhh, for some reason - that I haven't yet worked out - your scrolltrigger is twice the size as mine. if i add "+=20%" to my 'end' - end: "bottom+=20% bottom" it works, but I don't really know why. I mean it works!😄
Sam Tremblay Posted September 29 Posted September 29 Hey @NickWoodward! I'm not sure to understand the problem, my english is not super good hehe. I see you use +=100% now instead of 20%.... Maybe you need that because you have the pinSpacing to true. Try to turn this parameter to false. Â Does it help? Â Â EDIT: hmmmm... Or maybe it's because I have a pinned container 100vh moving in a div 300vh and not you ? 1
NickWoodward Posted September 29 Author Posted September 29 7 hours ago, Sam Tremblay said: maybe it's because I have a pinned container 100vh moving in a div 300vh and not you yeah i did think it might be this. it's ok though, i've got it working well now, with the autoSplit/onSplit callback. thanks a lot for your help. your english seems great btw 🙂 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now