Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

nonoumasy

Members
  • Posts

    18
  • Joined

  • Last visited

nonoumasy's Achievements

  1. Thank you! That works! I'm going to update all my react app with this new selector util.
  2. Thanks for the tip on the selector util. Is that new? At any rate, I got the scrollytelling thing to work: https://codesandbox.io/s/elegant-meninsky-hwvu5?file=/src/App.js It's a bit hacky. In particular, the only way to get the lat and lon values is to add them as a div elements. I might have to use something like the intersection observer to make it cleaner. If thats the case, I wouldn't need scrollTrigger. Btw, I was able to create the array of items by mapping the q('.card). I didn't see that in the documentation so it took awhile to figure it out. useEffect(() => { q(".card").map((item) => { ScrollTrigger.create({ trigger: item, start: "top center+=150", end: "top center", toggleActions: "start reverse none start", onEnter: () => myEnterFunc(item), onLeave: myLeaveFunc, onEnterBack: () => myEnterFunc(item), onLeaveBack: myLeaveFunc, markers: "true", scrub: "true" }) }) }, [])
  3. https://codesandbox.io/s/elegant-meninsky-hwvu5?file=/src/App.js Essentialy, I'm trying to create a scrollyTelling feature. I would like to trigger a flyTo function on the map using scrollTrigger rather than a click. I want to pass arrayItem objects(which has latitude, longitude values) to the Scrolltiger.create onEnter property so that it can pass these values to the actual flyTo() function which moves the map around. Since scrollTrigger is the one triggering each event based on an item on the array, I figure you somehow need to involve it. Still trying to figure this out. Thanks for any help. I'm using useRef in react to get a reference to the card div so it can create an array of refs for scrollTrigger. const revealsRef = useRef([]) const data = [ { id: "foo1", title: "lorem ipsum", latitude: 38, longitude: -118 }, { id: "foo2", title: "lorem", latitude: 39, longitude: -119 }, { id: "foo3", title: "lorem", latitude: 37, longitude: -117 } ] revealsRef.current = [] const addToRefs = (item) => { if (item && !revealsRef.current.includes(item)) { revealsRef.current.push(item) } } {data.map((item, index) => ( <div className="card" key={index} ref={addToRefs} style={{ cursor: "pointer" }} onClick={() => flyTo({ data, id: item.id })} > <div>{item.title} </div> <div>{item.latitude} </div> <div>{item.longitude} </div> </div> ))} ... I tried logging mapped items from these revealCurrents. I get this: <div class="card" style="cursor: pointer;"> <div>lorem </div> <div>37 </div> <div>-117 </div> </div> so I can probably do some querySelector to get that lat and lon values from this and pass this to the flyTo function. However, I was wondering if there was a more elegant way to do this with ScrollTrigger. I apologize if this is more of a React/javascript thing more than a scrollTrigger, but just thought I would ask. ps. just adding this. Would it be better not to include scrollTrigger to trigger the flyTo() function. Maybe I can just listen to when the card div hits a scrollPosition Y and then call the flyTo() and pass the lat and lon that way?
  4. Yes! Thank you so much. I was missing the 'querySelector' as a way to reference the elements I wanted to animate. Also, yes the timeline is much cleaner to work with. I have refactored my code and updated the CSB. 😀
  5. https://codesandbox.io/s/gsap-story-with-text-yhb9w I'm revealing each card one by one using scrollTrigger. Sometimes I would like to render different elements from a .map one after another instead of the same time. I would like to have a different animation for each one, eg image, title, description. However, I only have access to the 'item' object which the ref contains. How would I seperate these? I tried destructuring the object but that didn't work. I also tried combining item with 'div' and other combinations. Cheers and thanks in advance for any help. n
  6. https://codesandbox.io/s/travel-conditions-wj96q?file=/src/components/GridComponent.js I used the same code for a Nextjs however it doesn't seem to work for this React app. If I save, then it will (sort of) work until a refresh. The GSAP part is in the component/GridComponent
  7. Here is the code I used that worked with NextJS: (however, this didn't work for me in a React app)...any ideas? import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/dist/ScrollTrigger"; gsap.registerPlugin(ScrollTrigger); import data from '../data' export default function ReactComponent () { //GSAP section const revealsRef = useRef([]); revealsRef.current = []; useEffect(() => { revealsRef?.current.map((el, index) => { gsap.fromTo( el, { autoAlpha: 0 }, { duration: 1, autoAlpha: 1, ease: "power2", scrollTrigger: { id: `section-${index + 1}`, trigger: el, start: "top center+=300", end: "bottom top", toggleActions: "restart none none reverse", // markers: "true", scrub: "true" } } ); }); }, []); const addToRefs = (el) => { if (el && !revealsRef.current.includes(el)) { revealsRef.current.push(el); } }; //end of GSAP section return ( <> {data.map((item) => { return ( <div ref={addToRefs} key={item.id}> ... </div> ) } </> ) ) }
  8. Finally got this scrollTrigger to work. Demo: https://oocbl.sse.codesandbox.io/
  9. I tried both. I added gsapAnim to fetchData which was called in useEffect. That didnt work so I just added it after fetchData in the useEffect. and that didnt work either, well sometimes it did, but not consistent. Then when I added the useTimeout, it did work.
  10. I did add it last. The only way i could make it work was to add a little timeout. useEffect(() => { fetchData() setTimeout(()=> { gsapAnim() }, 1000); }, []) const fetchData = async () => { const db = firebase.firestore() const data = await db.collection('trips').doc(id).get() const item = await data.data() const data2 = await db.collection('trips').doc(id).collection('chapters').get() const item2 = await data2.docs.map(doc => (doc.data())) await setJournal(item) await setChapters(item2) // await gsapAnim() } const gsapAnim = () =>{ gsap.from(headerRef.current, { autoAlpha: 0, ease: 'none', delay: 1 }); revealRefs?.current?.map((el, index) => { gsap.fromTo(el, { autoAlpha: 0 }, { duration: 1, autoAlpha: 1, ease: 'power2', scrollTrigger: { id: `section-${index + 1}`, trigger: el, start: 'top center+=0', end: 'bottom top', toggleActions: 'restart none none reverse', // markers: 'true', scrub: 'true', } }); }); }
  11. Ok, i finally fixed this with useEffect(() => { fetchData() setTimeout(()=> { gsapAnim() }, 1000); }, []) so that 1 second gave it just enough time to fetch the data. still not sure if the array had more items if this trick would work.
  12. That was exactly it. I added the gsap() function after setChapters() in the fetchData function and now it works some of the time. Can you pls take a look at : https://tripmap.netlify.app/journals/gGKrNrmT8JAYDSqBBt0X Sometimes the section has more height sometimes less. Is this still part of the problem of not waiting for the fetched data? I added awaits on most of the fetching stuff so I'm not sure what else I can do to make sure the state is finished before calling the GSAP function. FYI, on mobile its not that bad. the sections end in the right place. thanks.
  13. I used this as a guide for ScrollTrigger and React with dynamic data being mapped. https://ihatetomatoes.net/react-and-greensock-tutorial-for-beginners/ So it sort of works. Sort of. My code is pretty much the same as the demo above except I'm fetching data from Firebase Firestore with a useEffect to fetch the data and then to invoke the GSAP animation. A Couple of things: 1) just like the demo, my headerRef does animate (and that is using the fetched data) but only that. The array of items that is mapped from the fetched data doesn't get the animation. 2)also, something wierd, if I make a change and save my React app, this will actually make the animation work, but as soon as I hit refresh on the browser, it goes back to not working. I've turned the markers on and I only see them at this time. 3)I would have added a CodePen but since this requires a Firebase and React, I thought I would just paste the relevant code below: Hope someone can help. const DetailScreen = ({ }) => { const headerRef = useRef(null); const { id } = useParams() const [journal, setJournal] = useState([]) const [chapters, setChapters] = useState([]) const revealRefs = useRef([]); revealRefs.current = []; const addToRefs = el => { if (el && !revealRefs.current.includes(el)) { revealRefs.current.push(el); } }; useEffect(() => { fetchData() gsapAnim() }, []) const fetchData = async () => { const db = firebase.firestore() const data = await db.collection('trips').doc(id).get() const item = data.data() const data2 = await db.collection('trips').doc(id).collection('chapters').get() const item2 = data2.docs.map(doc => (doc.data())) setJournal(item) setChapters(item2) } const gsapAnim = () => { gsap.from(headerRef.current, { autoAlpha: 0, ease: 'none', delay: 1 }); chapters && revealRefs.current.map((el, index) => { gsap.fromTo(el, { autoAlpha: 0 }, { duration: 1, autoAlpha: 1, ease: 'none', scrollTrigger: { id: `section-${index + 1}`, trigger: el, start: 'top center+=100', toggleActions: 'play none none reverse', markers: 'true' } }); }); } return ( <div className={"detailContainer"}> <div ref={headerRef} className={"headerSection"}> <img className={"journalImage"} src={journal.journalImage} alt='' /> <h2 className={"title"}>{journal.title}</h2> <h4 className={"author"}>{journal.author}</h4> <div className={"tagsSection"}> {journal.tags && journal.tags.map(tag => (<Tags tag={tag} />))} </div> <div className={"summarySection"}> <div style={{ fontSize: 24, fontWeight: 'bold' }}>Summary:</div> <div className={"summary"}> {journal.summary} </div> </div> </div> <div className={"entrySection"} style={{ marginTop: 120, }} > {chapters.map(item => ( <div key={item.id} ref={addToRefs}> <Entry item={item} /> </div> ))} </div> </div> ) }
  14. thanks. good to know. I might just do smaller animations like these at first.
  15. Thanks for the clarification. It helps put it in context. 'tweening engine' is a good mental model. I assume thats its core feature or do the other plugins offer different tooling that make it interactive , etc. It's good to know it can be done albeit with a different workflow and toolset. cheers
×