Jump to content

Search the Community

Showing results for tags 'react'.

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


  • GreenSock Forums
    • GSAP
    • Banner Animation
    • Jobs & Freelance
  • Flash / ActionScript Archive
    • GSAP (Flash)
    • Loading (Flash)
    • TransformManager (Flash)

Product Groups

  • Club GreenSock
  • TransformManager
  • Supercharge


There are no results to display.

Find results in...

Find results that contain...

Date Created

  • Start


Last Updated

  • Start


Filter by number of...


  • Start



Personal Website



Company Website



  1. Hello, I'm trying to figure out how to use MorphSVG with React. When I do a gsap.from(start, 2, {x:400}) for a regular animation, everything works fine. But when I try to morph the square into the start, nothing happens. Any help is appreciated! I should mention that I have installed the club GreenSock packages correctly. This is what my component looks like: import React, { useRef, useEffect } from "react"; import gsap, { TweenMax, Power4 } from "gsap"; import MorphSVGPlugin from "gsap/MorphSVGPlugin"; gsap.registerPlugin(MorphSVGPlugin); const MorphShape = () => { let start = useRef(null); let end = useRef(null); console.log("start", start); useEffect(() => { console.log("start", start); console.log("end", end); // gsap.from(start, 3, {x: 400}) gsap.to(start, {duration: 1, morphSVG:end}); }); return ( <> <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1125 1125" > <title>developer</title> <rect id="start" width="1125" height="1125" fill="#a39274" ref={(el) => (start = el)} /> <polygon id="end" points="562.5 71.54 689.62 439.36 1078.72 446.6 768.19 681.16 881.54 1053.46 562.5 830.61 243.46 1053.46 356.81 681.16 46.28 446.6 435.38 439.36 562.5 71.54" fill="none" stroke="#515151" stroke-miterlimit="10" stroke-width="18" ref={(el) => (end = el)} /> </svg> </> ); }; export default MorphShape;
  2. I have a React component that I'm trying to toggle the width of when a button is clicked. When the button is clicked again, it goes back to the original width. The problem is the original width could be anything, depending on the viewport size as it's responsive. On small devices it's 75%, large it's 25% with a few others in the middle. There's also another animation that animates the opacity and position of the element I'm targeting here. Here's what I have so far; useEffect(() => { const tween = gsap.to(slashRef.current, { width: '100%', ease: 'power3', paused: true, }); if (menuOpen) { tween.play(); } else { tween.reverse(); } }, [menuOpen]); I've tried starting it as paused, and when the `menuOpen` is true it animates the width fine. When it's `false` it's not reversing it back to its original position as I would expect — clearly I'm missing something. I've tried a bunch of different approaches using state and ref to set the original width and trying to access that but I've had no joy so far. I'm sure it's something simple I'm missing. Thanks for any help, Chrish
  3. Hi there, I'm new with gsap, and I would love to integrate it with my react projects. For what I understood, to use gsap to animate my elements, I need first to target them with ref and useRef(), I was wondering in case I need to create a grid based on data coming from an api call, let's say a not definied number of tiles with images, and I want them to appear with a staggered animation, how should I proceed ? I am a bit confused because I don't know how to target them with useRef() I hope that my question makes sense, in case I'm happy to clarify Cheers
  4. The transition group does not work. Also try your example, and it is not working properly I'm sorry for the pictures, I couldn't do the same in the pan code
  5. Hey ! I'm experimenting with React JS, and I'm wondering what is the best method to start an animation when the DOM's ready with React JS. Plus, I don't know what method is the best to target elements in React JS. I need some advices : Should I use useCallback hook, or simply the States and Refs ? Here's an example of what I did. This is very simple and minimalist. https://codesandbox.io/s/prod-river-xqvuu Actually, the animation works, but as I said I would like to know if my method looks good or not. If someone could take a look... Thanks !! Take care Lucie
  6. Hi. I need some basic help with gsap.timeline() in a react environment. See my code below: import React, { useRef, useEffect } from 'react' import gsap, { TweenMax, Linear } from 'gsap'; import { ReactComponent as Twitter } from '../assets/svg/social/twitter.svg' const NavBar = () => { let twitterIcon = useRef(null); const tl = gsap.timeline() // this is the hover effect, making it glow green (all attributes are correct) const glowAnimation = (icon) => { tl.to(icon, 0.3, {attr: {style: "fill: rgb(48,223,171)"}, ease: Linear}) } // This just sets the initial colour of the black svg to white useEffect(() => { TweenMax.set(twitterIcon, {attr: {"style": "fill: rgb(255,255,255)"}}) }) return ( <div className="navbar"> <a title="Twitter" target="_blank" rel="noopener noreferrer" // onMouseEnter={ glowAnimation({twitterIcon}) } // onMouseLeave={ something? reverse of tl } href="redacted"> <Twitter // This is an SVG imported as ReactComponent className="navbar__icon" title="Twitter" ref={el => {twitterIcon = el}} /> </a> </div> ) } export default NavBar The basic premise of this is that it is part of my header. It has only one twitter icon (svg) right now. I want to be able to add more icons in the future (e.g. facebook, github) hence why I want to be able to pass in some reference to an icon into a single gsap timeline to describe the hover animation (defined as glowAnimation function) when mouse over an icon, and reverse that timeline when mouse leaves that icon. So I created a function with that timeline. But I'm unsure how to pass the twitterIcon reference (made using useRef) into the onMouseEnter attribute. What am I doing wrong? And also, what can I put in the onMouseLeave attribute to reverse the glowAnimation function? Sorry if this is stupid
  7. I've recently found a very nice codepen containing almost the exact same animation I wanted done in GSAP, and I've been trying to convert it to GSAP 3 to use it in a web app using pretty much just react hooks all over. It uses timeScale tweening to simulate acceleration and deceleration of a rotating svg, with a play/pause button. However, I can't seem to get the acceleration/deceleration effect to work on Firefox/Chrome, and it won't pause, either. The codepen I linked is the effect I'm trying to achieve, and I've linked a minimal reproducible example below: https://codesandbox.io/s/blissful-hill-boo2n There is just one condition that I'd like to include for my app besides using hooks and gsap 3, and that is that I need to fade the rotation in and out based on the state of the parent element, and as far as I can see that's working alright (as evidenced by the isActive! isNotActive! console logs). That state is currently set by the playButton element, via the setActiveCallback function. I'm not sure this is what's breaking everything, since the animation itself doesn't look like it's working properly on it's own with either react hooks or gsap 3. TL;DR: I can't get codesandbox the animation to pause, and the intended acceleration/deceleration effect is borked. Any help will be very much appreciated!
  8. Hello, I hope you can help me with this. I am trying to create a custom hook for creating an image parallax using intersectionObserver API. Seems work partially but when I scroll I get this error: backend.js:6 Invalid property y set to 47.666666666666664 Missing plugin? gsap.registerPlugin() My goal: using Y or backgroundPosition from/to everytime the element is visible. import React, { useEffect } from 'react'; import { gsap } from 'gsap/all'; function useImageParallax(imagesParentSelector) { useEffect(() => { const appWrapper = document.querySelector('.app--layout'); const elements = document.querySelectorAll(imagesParentSelector); const scrollHandler = () => { let options = { root: null, }; // parallax effect let observer = new IntersectionObserver(function(entries) { entries.forEach((entry) => { const offset = appWrapper.scrollTop / 3; gsap.to(entry, { y: offset }); }); }, options); for (let elm of elements) { observer.observe(elm); } }; appWrapper.addEventListener('scroll', scrollHandler, { capture: false, passive: true }); return () => { appWrapper.removeEventListener('scroll', scrollHandler, { capture: false, passive: true }); }; }, [gsap]); } export default useImageParallax;
  9. Hi community , this is my first project with React and GSAP. I really love the work we have created, but we have a big issue: In the project, we are using server side render with reactjs.NET. When we try to render a component with the gsap library we got this error: setTimeout is not supported in server-rendered Javascript Here is an image with the error too. please, help me with some ideas, I made great things with gsap and I dont want to dont finally use the library and I have to finish the project next week... thank you very much
  10. Hi everyone. Firstly, I'd like to say thanks to an amazing forum, I've learnt so much here over the last few weeks. The effort you lot put into this is unreal. Unfortunately, I can't seem to find a solution to the issues I'm having, hence this post. I'm trying to stagger animate a list in and out that changes length and properties. I'm using gsap3 with react hooks. I'm sure this is common and I'm just approaching it wrong so I would really appreciate someone taking a look at the link below: https://stackblitz.com/edit/gsap-react-listobject-stagger Thanks so much!
  11. Hi! i'm trying to create a confetti animation in my react projecta, following some tutorial and code example i found but there are something that im not understand. See code: import React from 'react'; import { gsap, TweenMax } from 'gsap'; class Stars extends React.Component { render() { TweenMax.to('img', { xPercent: '-50%', yPercent: '-50%', }); const total = 70; const container = document.getElementById('container'); let w = container?.offsetWidth; let h = container?.offsetHeight; for (let i = 0, div; i < total; i++) { div = document.createElement('div'); div.className = 'dot'; container?.appendChild(div); gsap.set(div, { x: R(0, w || 1), y: R(-100, 100), opacity: 1, scale: R(0, 0.5) + 0.5, backgroundColor: 'hsl(' + R(170, 360) + ',50%,50%)', }); animm(div); } function animm(elm) { TweenMax.to(elm, R(0, 5) + 3, { y: h, ease: Linear.easeNone, repeat: -1, delay: -5, }); TweenMax.to(elm, R(0, 5) + 1, { x: '+=70', repeat: -1, yoyo: true, ease: Sine.easeInOut, }); TweenMax.to(elm, R(0, 1) + 0.5, { opacity: 0, repeat: -1, yoyo: true, ease: Sine.easeInOut, }); } return <p>oi</p>; } } export default Stars; what is the "R" function which set a value to 'x' and 'y' coords?
  12. Hi guys! Good morning. I'm newbie with GSAP and i'm learning it but i'm also trying to use it in my react project. so, i'll show peaces of my code before i explain the error: import { gsap, TweenLite } from 'gsap'; class MainScreen extends React.Component<IProps, IState> { constructor(props: IProps) { super(props); gsap.registerPlugin(TweenLite); this.state = { myElement: null, myTween: null, canInitCircles: true, }; } private initCircles = (div: any, canInitCircles: boolean) => { if (canInitCircles) { this.setState({ myElement: div, myTween: TweenLite.to(this.state.myElement, 1, { x: 500, y: 500 }), canInitCircles: false, }); } }; public render() { const { classes } = this.props; const { canInitCircles } = this.state; return ( <Wrapper className={classes.root}> <Circles ref={(div: any) => this.initCircles(div, canInitCircles)} /> <Planet /> <Navbar /> </Wrapper> ); } nothing hard to understand! I have a component called Circles which is a bundle of img html tags with some SVG in each of then and i'm trying to move this component, just to practice GSAP with React. (note: the prop 'ref' in Circles component, receive any). but i'm taking this warning: can anyone knows what its going on? i had already registered the TweenLite plugin at the constructor method. Also, i installed the GSAP by NPM, see on my package.json: "gsap": "^3.1.1",
  13. Hello, In the learning process of React + GSAP and I've run into a situation where I can't find the easy solution. Should be a quick answer In previous projects, (javascript + html for example) I would write up a timeline, then set an array of elements with a { clearProps: "all" } to essentially reset it The code I'm working with now is React with inline styles. It seems that clearing the props in the same fashion removes all of the inline styles, and since it's not set in a css sheet, the animation doesn't reset but breaks and it seems this is working as intended. Is there a recommended way to approach resetting inline styles in react? Or should I start pushing to refactor all of the code into css files? Thanks for any of your time!
  14. Hello greensockers, I got a little problem here. So the onComplete function recall every time the toggleStartAnim function, and not just once. So I do not understand why... normally the cycle is finish, any idea... here some of my code : import React, { useEffect, useState } from "react"; import GifFusee from "../assets/gif/fuseeQuiGalere.gif"; import { gsap, MotionPathPlugin, TimelineMax } from "gsap/all"; import WayToMars from "./WayToMars"; import "../assets/stylesheets/Intro.css"; const Intro = () => { let currentTimeScale; const [animStart, setAnimStart] = useState(false); // gsap.registerPlugin(MotionPathPlugin); const takeTime = () => { // currentTimeScale = gsap.globalTimeline.time(); }; const tl = new TimelineMax({ onUpdate: takeTime, yoyo: false, repeatDelay: 1 }); const toggleStartAnim = () => { setAnimStart(!animStart); console.log("toggleStartAnim pop"); }; function test2() { return new Promise(resolve => { tl.set(".intro-container", { autoAlpha: 1 }) .set("#takeoff", { autoAlpha: 1 }) .to("#takeoff", 5, { rotation: 360, ease: "linear" }) .set("#fuseehop", { autoAlpha: 1 }) .set("#fuseeKiDecol", { autoAlpha: 1 }) .to("#fuseeKiDecol", { y: -10, scaleY: -0.1, scaleX: -0.1, duration: 10, onComplete: () => { toggleStartAnim(); resolve(); }, onCompleteParams: {} }); }); } useEffect(() => { test2().then(() => { console.log("test2 done"); }); console.log(animStart); }); useEffect(() => { gsap.globalTimeline.pause(); }, []); return ( <div> {/* Debut intro */} <div className="intro-container"> {/* Debut decollage fusee */} <div id="fuseehop" className="container-fusee"> <img alt="fuseekidecol" id="fuseeKiDecol" className="container-fusee" src={GifFusee} /> </div> {/* Debut rotation terre */} <div className="takeoffplanet"> <div id="takeoff" /> </div> </div> <WayToMars animStart={animStart} changeState={toggleStartAnim} /> </div> ); }; export default Intro; Edit: problem solved in an other way: set the hooks by false like that i'm sure that even if the function is anormally call every x time, i'll set it by true in the child component after really i do not understand why onComplete repeat every time if everybody got an idea why :s const toggleStartAnim = () => { setAnimStart(false); };
  15. Hello, I need to set my react state inside my timeline after first animation ends and then continue with animations: const tl = gsap.timeline(); tl.to(pTitle, 1.5, { x: -550 }).setNewState after previous animation.to(pTitle,1.5,{x:150}) so far I could achive it with that: tl.to(pTitle, 1.5, { x: -550 }).add( setTimeout(() => { //setNewState }, 1500) ).to(pTitle, 1.5, { x: "-4%" }); is this proper way of implementing this? Or is there "smoother" way of achieving it like with delayedCall() - which is not available in timeline
  16. Hi Greensockers, First of all i want to thank you everyone. This forum and this community have been very helpfull from the begining. Now here is the problem ^^ Im trying to do animations in a React (Gatsby) website. I have a slider section where i want to change lot of stuff on my site when i switch from a slide to another (color menu, color buttons, color title...) So i use React Redux with state to do this and call my action to change my color. Everything is working, the function is called, but at the begining of the timeline, before all the previous one. I think i have syntax a problem, i tried to separate functions and parameters in the call function but without success. Thank you for your help.
  17. I'm new to GSAP and am trying to both have an Image Component <Transition> and have an onHover animaiton using Tween. I have both of them working although I can't use them both. I don't know how to use <transition> unless its within an object returning a <transition>. Can you use Tween within an Object or does it have to be Component level. Suggestions? Feel free to use my github work in progress for more info. Please be gentle with me (I couldn't get Codepen to work) const Ball = props => { const url = `/imagines/${props.index + 1}_ball.png`; const { in: show, remove, card } = props; return <Transition timeout={1000} mountOnEnter unmountOnExit appear in={show} addEndListener={(node, done) => { TweenMax.to(node, 0.35, { y: 0, autoAlpha: show ? 1 : 0, onComplete: done, delay: !show ? 0 : card.init ? props.index * 0.5 : 0 }); }} > //other stuff
  18. Hi I am working with Gsap on React and I need to destroy elements after my animation is complete. I am using a state and conditional rendering and it works fine if animate a parent element and destroy its children, but in other cases I need to destroy the element I am animating, but I get an infinite error saying "Cannot tween a null target". Do you guys have an idea or a better approach to destroying elements after animating them? Please note that I will need them back later. My code looks something like this: TweenLite.to(this.paths, 0.3, { opacity: 0, onComplete: this.destroyIntro, }); destroyIntro = () => { this.setState({ destroyIntro: true }); }; {!destroyIntro && ( <div ref={div => this.paths = div}>Content Here</div> )}
  19. Hi all, I started working on an idea and want to stop before I go further and ask a few questions and get some criticism on best practices. I'll preface with saying that I'm only concerned with modern browsers. First, GSAP performance. Is there a better approach I could take to accomplish the same thing and would perform better? Second, React with GSAP. This should probably be a separate question... I've been building react apps via `create-react-app` for a while and in the past, I had some issues using GSAP in React. Mostly, with using plugins that `require TweenLite`, requiring me to eject the `create-react-app` and customize the webpack config to resolve the alias. (As an aside, I now get around ejecting for simple things like this by using react-app-rewired). There are some edge case issues in particular I'm trying to solve. When you move the mouse quickly from left to right, sometime the cube will spin too much. I've played around with some boolean checks to see if I'm overlapping tweens or something but nothing seems to help. I suspect it's based on the way I'm "snapping" the cube's most forward face to the center when the mouse moves back to the center. EDIT 1... is it possible that this is related to React state? I wonder if react-gsap-enhancer would help. EDIT 2... looks like the codepen may even have other issues that aren't present in my local setup. If you move the mouse too far past the cube it stops, which should only occur when the mouse is over the cube. And it's more difficult to see the real issue I'm trying to solve in the codepen.
  20. Hello! React + GSAP tutorials are pretty rare (imho), but I just stumbled on this channel. The videos are concise and the creator explains everything well. Hope this is helpful https://www.youtube.com/channel/UCqrxiLP9RHz2GxDJaZuTRBw/videos Blessings, Yeti
  21. Hi everyone! I'm trying to ease a progress bar filling animation but when it gets triggered it jumps straight to 100%. I want the animation to be triggered only once. I'm using react-scrollmagic and react-gsap. Progress bar is from Bulma framework. This is my code: <Controller> <Scene pin={false} reverse={false} indicators={true} triggerElement= "#trigger1" duration={0} > <Tween staggerFrom={{ value: 0, ease: 'Expo.easeOut' }} staggerTo={{ value: 100, ease: 'Expo.easeOut' }} stagger={0.15}> <div id="trigger1"></div> <progress className="progress is-primary" value="0" max="100"></progress> </Tween> </Scene> </Controller> The same tween without the scrollmagic scene instead works perfectly. Any ideas how to fix this?
  22. Hello Community - my second post as I'm very stuck trying to integrate a range-slider in React that will be friends with the progress() method to move through the timeline! I can pass around the value I need to my slider, but getting undefined errors when I try to pass this over to this.tl.progress(this.state.value) etc? I've read through several posts, but none look very current...in fact most are going back 2-3 years and the react-way has changed! Looking through the 'getting started with react post from Rodrigo' there are some useful hints, but it seems overly complex, compared to how easy it was to plugin the play, pause, reverse and restart methods into a button with an onClick event handler. Do we really need a separate state management file to pass down the state as props to a child component just to get the slider to move through the timeline without breaking? I also got some very good support already (This gives you more of an idea what I am working on...sorry for the lack of a reduced codepen example as this is a large full-stack application! coming soon I promise!) Here's some code of how I got the play, pause, reverse, and restart methods working...these plugged right in! (FYI ButtonGroup and Button components are from React-Bootstrap): <Row> <Col md={12}> <ButtonGroup className="animationControls"> <Button bsStyle="primary" onClick={() => this.tl.play()}> <Glyphicon glyph="play" /> {"Play"} </Button> <Button bsStyle="primary" onClick={() => this.tl.pause()}> <Glyphicon glyph="pause" /> {"Pause"} </Button> <Button bsStyle="primary" onClick={() => this.tl.reverse()}> <Glyphicon glyph="backward" /> {" Reverse"} </Button> <Button bsStyle="primary" onClick={() => this.tl.restart()}> <Glyphicon glyph="step-backward" /> {"Restart"} </Button> </ButtonGroup> </Col> </Row> Until bootstrap-4 is up and running with react, you do not have range slider in your form components, so I had to look elsewhere. After trying a few different versions, the npm package rc-slider seems to be the most lightweight (little to no boilerplate required!) create your styles for the slider before your class function: const railStyle = { position: "relative", width: "90%", margin: "0% 0% 0% 3%", height: 10, borderRadius: 7, cursor: "pointer", backgroundColor: "#afafaf" }; const handleStyle = { height: 15, width: 15, backgroundColor: "white", borderTopLeftRadius: 10, borderTopRightRadius: 10, border: "3px solid #E5F1FC", top: -2, position: "absolute" }; AND be sure to set your starting value in the constructor....probably 0 since that would be the start of your timeline.... constructor(props) { super(props); this.tl = new TimelineMax(); this.state = { center: [46.8, 8.3], zoom: 1, value: 0 }; this.handleZoomIn = this.handleZoomIn.bind(this); this.handleZoomOut = this.handleZoomOut.bind(this); this.handleReset = this.handleReset.bind(this); this.handleSliderChange = this.handleSliderChange.bind(this); } Next, I have two functions...please note that onSliderChange and onAfterChange are pre-built methods for the react rc-slider component. these successfuly track and log the value as you drag along the timeline, but kill the animation! onSliderChange = value => { this.setState({ value }); console.log("Value is: ", value); }; onAfterChange = value => { console.log(value); this.tl.progress(value / 100); }; .....And lastly, the slider component itself, inside render() <Slider className="slider" style={railStyle} handleStyle={handleStyle} min={0} max={bookingData.length} value={this.state.value} onChange={this.onSliderChange} //onInput={this.handleSliderChange} onAfterChange={this.onAfterChange} /> I know this may be hard to digest without a working example. I'll try to make a reduced case, but here's the issue...inside the Slider component, if you drag the slider around, it will successfully log the value I need. Where can I pass the value to this.tl.progress(this.state.value / 100) etc to get the timeline to respond? I've tried a dozen different ways, and I either get that value is undefined, or when I try to pass this in to the onSliderChange I get my fav error about expected a function, but instead saw an expression, no unused expressions. dragging the slider around kills the timeline, or depending where I do it, will make the animated elements disappear from the screen. Grrrrr! React is very powerful, but the need to constantly update the state of components during their lifecycle make these kinds of things very frustrating! If anyone has solved this or can send a link to an example of how to do this it would be greatly appreciated! If I figure it out on my own I will update the post - I know I'm close! Thanks community!
  23. Hi there, First post here! I'm working on a React/Gatsby app which references this tutorial. I've solved most of the issues except for the following error: TypeError: Cannot read property 'easeOut' of undefined I've tried a bunch of variations of imports destructuring etc but Quad is never defined. My code is as follows: import React, { Component } from "react" import Layout from "../components/layout" import SEO from "../components/seo" import { TweenMax, Quad, Sine, Back } from "gsap/TweenMax" const prettyLetter = require( 'pretty-letters' ) export default class IndexPage extends Component { componentDidMount() { var options = { groupClass: 'char-group-', groupTag: 'span' } prettyLetter('a', options) const lineEq = (y2, y1, x2, x1, currentVal) => { // y = mx + b var m = (y2 - y1) / (x2 - x1), b = y1 - m * x1 return m * currentVal + b } const lerp = (a,b,n) => (1 - n) * a + n * b const distance = (x1,x2,y1,y2) => { var a = x1 - x2 var b = y1 - y2 return Math.hypot(a,b) } const getMousePos = (e) => { let posx = 0 let posy = 0 if (!e) e = window.event if (e.pageX || e.pageY) { posx = e.pageX posy = e.pageY } else if (e.clientX || e.clientY) { posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop } return { x : posx, y : posy } } let winsize; const calcWinsize = () => winsize = {width: window.innerWidth, height: window.innerHeight} calcWinsize() window.addEventListener('resize', calcWinsize) // The feDisplacementMap element const feDisplacementMapEl = document.querySelector('feDisplacementMap') class Menu { constructor() { this.DOM = { svg: document.querySelector('svg.distort'), menu: document.querySelector('nav.menu') } // The images (one per menu link) this.DOM.imgs = Array.from(Object.assign.apply(Object, [this.DOM.svg.querySelectorAll('g > image')])) // The menu links this.DOM.menuLinks = Array.from(Object.assign.apply(Object, [this.DOM.menu.querySelectorAll('.menu__link')])) // Mouse position this.mousePos = {x: winsize.width/2, y: winsize.height/2} // Last mouse positions (one to consider for the image translation movement, another for the scale value of the feDisplacementMap element) this.lastMousePos = { translation: {x: winsize.width/2, y: winsize.height/2}, displacement: {x: 0, y: 0} } // feDisplacementMap scale value this.dmScale = 0 // Current menu link position this.current = -1 this.initEvents() requestAnimationFrame(() => this.render()) } initEvents() { // Update mouse position window.addEventListener('mousemove', ev => this.mousePos = getMousePos(ev)) this.DOM.menuLinks.forEach((item, pos) => { const letters = Array.from(Object.assign.apply(Object, [item.querySelectorAll('span')])) const mouseenterFn = () => { // Hide the previous menu image if (this.current !== -1) { TweenMax.set(this.DOM.imgs[this.current], { opacity: 0 }); } // Update current this.current = pos // Now fade in the new image if we are entering the menu or just set the new image's opacity to 1 if switching between menu items if (this.fade) { TweenMax.to(this.DOM.imgs[this.current], 0.5, { ease: Quad.easeOut, opacity: 1 }) this.fade = false } else { TweenMax.set(this.DOM.imgs[this.current], { opacity: 1 }) } // Letters effect TweenMax.staggerTo(letters, 0.2, { ease: Sine.easeInOut, y: this.lastMousePos.translation.y < this.mousePos.y ? 30 : -30, startAt: {opacity: 1, y: 0}, opacity: 0, yoyo: true, yoyoEase: Back.easeOut, repeat: 1, stagger: { grid: [1,letters.length-1], from: 'center', amount: 0.12 } }) } item.addEventListener('mouseenter', mouseenterFn) }) const mousemenuenterFn = () => this.fade = true const mousemenuleaveFn = () => TweenMax.to(this.DOM.imgs[this.current], .2, { ease: Quad.easeOut, opacity: 0 }) this.DOM.menu.addEventListener('mouseenter', mousemenuenterFn) this.DOM.menu.addEventListener('mouseleave', mousemenuleaveFn) } render() { // Translate the image on mousemove this.lastMousePos.translation.x = lerp(this.lastMousePos.translation.x, this.mousePos.x, 0.2) this.lastMousePos.translation.y = lerp(this.lastMousePos.translation.y, this.mousePos.y, 0.2) this.DOM.svg.style.transform = `translateX(${(this.lastMousePos.translation.x-winsize.width/2)}px) translateY(${this.lastMousePos.translation.y-winsize.height/2}px)` // Scale goes from 0 to 50 for mouseDistance values between 0 to 140 this.lastMousePos.displacement.x = lerp(this.lastMousePos.displacement.x, this.mousePos.x, 0.1) this.lastMousePos.displacement.y = lerp(this.lastMousePos.displacement.y, this.mousePos.y, 0.1) const mouseDistance = distance(this.lastMousePos.displacement.x, this.mousePos.x, this.lastMousePos.displacement.y, this.mousePos.y) this.dmScale = Math.min(lineEq(50, 0, 140, 0, mouseDistance), 50) feDisplacementMapEl.scale.baseVal = this.dmScale requestAnimationFrame(() => this.render()) } } new Menu() } render() { return ( <Layout> <SEO title="Home" keywords={[`Artist`, `Brisbane-based`, `drawing`, `painting`, `watercolour`, `sculpture`, `installation`, `video`, `embroidery`]} /> <div style={{ paddingBottom: 100 }}> <svg className="distort" width="350" height="450" viewBox="0 0 350 450"> <filter id="distortionFilter"> <feTurbulence type="turbulence" baseFrequency="0.07 0.01" numOctaves="5" seed="2" stitchTiles="stitch" x="0%" y="0%" width="100%" height="100%" result="noise"/> <feDisplacementMap in="SourceGraphic" in2="noise" scale="0" xChannelSelector="R" yChannelSelector="B" x="0%" y="0%" width="100%" height="100%" filterUnits="userSpaceOnUse"/> </filter> <g filter="url(#distortionFilter)"> <image className="distort__img" x="50" y="50" xlinkHref={require('../images/1.jpg')} height="350" width="250"/> <image className="distort__img" x="50" y="50" xlinkHref={require('../images/2.jpg')} height="350" width="250"/> </g> </svg> <nav className="menu"> <a href="#" className="menu__link">Shanghai</a> <a href="#" className="menu__link">Taipei</a> <a href="#" className="menu__link">Bangkok</a> <a href="#" className="menu__link">Kyoto</a> </nav> </div> </Layout> ) } }
  24. I'm getting an error when trying to use TweenMax in React component. I create the component like this below. import React, {Component} from 'react'; import {connect} from 'react-redux'; import Thumbnail from './thumbnail'; import TransitionGroup from 'react-transition-group/TransitionGroup' import {fetchHomeCollection} from '../../actions/client'; import styles from '../../../styles/client/home.scss'; class Home extends Component { constructor(props){ super(props); } componentWillMount(){ this.props.fetchHomeCollection(); } firstChild(props) { const childrenArray = React.Children.toArray(props.children); return childrenArray[0] || null; } renderThumbnails(){ const {collection} = this.props; if(collection.length <= 0) return <div>Loading...</div> return collection.map((photo, index)=>{ return( <TransitionGroup component={this.firstChild} key={photo._id}> <Thumbnail {...photo} delay={0.5 * index} key={photo._id}/> </TransitionGroup> ) }) } render(){ return ( <div id="home" className="flexbox-container"> {this.renderThumbnails()} </div> ) } } function mapStateToProps({photos}){ return{ collection: photos.collection } } export default connect(mapStateToProps, {fetchHomeCollection})(Home); then in my Thumbnail component I use the componentWillAppear to call my TweenMax fromTo method. import React, {Component} from 'react'; import { Link } from 'react-router-dom'; import {TweenMax} from "gsap"; export default class Thumbnail extends Component{ componentWillAppear(callback){ const el = this.container; TweenMax.fromTo(el, 0.3, {opacity: 0}, {opacity: 1, onComplete: callback}); } } Anyone know why I might be getting this error ?
  25. https://codesandbox.io/s/sad-maxwell-2b7vv?fontsize=14 Edit: For clarification, this needs to use React hooks. I have it transforming from = to x and vice versa, however, I had to hard code the reverse animation because I couldn't seem to get it to work by using the reverse or reveresed methods like shown below. if (isMenuOpen) timeline.play() else (timeline.reversed(true).play()