Jump to content
Search Community

Getting MorphSVG to work with React Hooks

danboyle8637 test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I'll upload a pen, but I feel like this might be something obvious I'm missing. 

 

I am building a react project using all hooks. In the past, when I used a class component, I would do something like this...

 

import MorphSVGPlugin from '../src/greensock/MorphSVGPlugin'

constructor(props) {
 super(props)
  
 this.morphSVG = MorphSVGPlugin
}

 

Then I would use the morphSVG: property in my Tween vars object and it was all good.

 

But with hooks, there is no constructor function. And just assigning the morphsvg plugin to an used variable doesn't help.

 

I'm using useEffect (only run on component mounting) to setup my morphing tween.

 

Any ideas?

Link to comment
Share on other sites

3 hours ago, danboyle8637 said:

I would use the morphSVG: property in my Tween vars object


I don't quite follow this - can you provide some sample code? A codepen would be SUPER helpful too. It almost sounds like you're trying to pass the actual plugin reference itself into a tween (which would be incorrect). For example: 

//BAD!
TweenMax.to(target, 1, {morphSVG:MorphSVGPlugin});

//GOOD
TweenMax.to(target, 1, {morphSVG:"#endShapeSelector"});

 

I'm sure we'll figure it out once we see your reduced test case. 

 

Happy tweening!

Link to comment
Share on other sites

import React, { useEffect, useRef } from "react"
import { TimelineMax, TweenMax } from "gsap"
import MorphSVGPlugin from "../greensock/MorphSVGPlugin"

import { useMenuOpenStore } from "../context/MenuOpenContext"

const MenuIcon = ({ width, height, className }) => {
  // My state so I know when the menu is open and closed
  const [{ menuOpen }, dispatch] = useMenuOpenStore()
  
  // Initiallized timelinemax
  const tl = new TimelineMax({ paused: true })
  
  // Setup refs to access the paths
  const topMenuBarRef = useRef(null)
  const middleMenuBarRef = useRef(null)
  const bottomMenuBarRef = useRef(null)
  const rightCloseRef = useRef(null)
  const leftCloseRef = useRef(null)

  useEffect(() => {
    tl.to(middleMenuBarRef.current, 0.3, {
      x: -60,
      autoAlpha: 0,
    })
      .to(topMenuBarRef.current, 0.3, {
        morphSVG: leftCloseRef.current,
      })
      .to(bottomMenuBarRef.current, 0.3, {
        morphSVG: rightCloseRef.current,
      })
  }, [])

  useEffect(() => {
    if (menuOpen) {
      console.log("play")
      tl.play()
    } else {
      console.log("reverse")
      tl.reverse()
    }
  })

  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      className={className}
      width={width}
      height={height}
      viewBox="0 0 194.27 162.68"
    >
      <g
        id="close-menu-icon"
        fill="#fff"
        stroke="#ebebeb"
        strokeLinecap="round"
        strokeMiterlimit="10"
        strokeWidth="24"
      >
        <path
          ref={rightCloseRef}
          id="right-cross"
          d="M28 150.68l59.83-59.83L166.68 12"
        />
        <path
          ref={leftCloseRef}
          id="left-cross"
          d="M166.68 150.68l-59.83-59.83L28 12"
        />
      </g>
      <g
        id="menu-icon"
        fill="#ebebeb"
        stroke="#ebebeb"
        strokeLinecap="round"
        strokeMiterlimit="10"
        strokeWidth="24"
      >
        <path ref={topMenuBarRef} id="top-menu-bar" d="M12 31.57h169.93" />
        <path
          ref={middleMenuBarRef}
          id="middle-menu-bar"
          d="M71.95 81.28h110.32"
        />
        <path
          ref={bottomMenuBarRef}
          id="bottom-menu-bar"
          d="M38.38 131h143.89"
        />
      </g>
    </svg>
  )
}

export default MenuIcon

 

This is my component. It's a standalone SVG that changes based on my menu being open or closed.

 

I don't use morphSVG in setting up the timeline. 

 

I import morphSVG based on the files location in my project. 

 

But I don't know how to get my app to know about it because it's not being used. Not sure if I need to do something with webpack.

Link to comment
Share on other sites

Oh, there's nothing special about wrapping it in an array - I just did that in case you have other plugins you need to reference as well. So you could simply add them to the array. 

 

Yeah, if you're still having trouble, please shoot us a codesandbox or something and we can take a peek. 

Link to comment
Share on other sites

  • 9 months later...

Having a similar issue where morphSVG seems to be ignored, but other gsap animations work fine.  React project.

 

I've installed gsap via the members npm package and imported.

 

import TweenMax from 'gsap'
import Sine from 'gsap'
import MorphSVGPlugin from 'gsap/MorphSVGPlugin'

Here's what the usage looks like (the items with ".current" are the references to the svg elements).

TweenMax.to(lineAnimate.current, 1.2, {
  morphSVG: lineRef.current,
  repeat: -1,
  yoyo: true,
  ease: Sine.easeInOut,
  delay: 0,
});

 

Link to comment
Share on other sites

@conspireagency Did you register the plugin? 

// you only need to do this once
gsap.registerPlugin(MorphSVGPlugin);

I bet React is dropping it when tree shaking because you don't actually reference the plugin anywhere in your code. Registering it protects it from tree shaking. 

 

If you're still having trouble, please provide a reduced test case that we can peek at to see the issue in context. We'd love to help, but sometimes it's tough to troubleshoot blind :)

 

Happy tweening and thanks for being a club member!

  • Like 1
Link to comment
Share on other sites

Yeahhh just figured that out right now looking at the console haha!  Thanks for the quick reply though, honestly amazed.

 

Just in case this helps anyone...

 

import gsap, {TweenMax, Sine} from 'gsap'
import MorphSVGPlugin from 'gsap/MorphSVGPlugin'

 

Then usage something like this

 

  gsap.registerPlugin(MorphSVGPlugin);

  const lineAnimate = useRef(null);
  const lineRef = useRef(null);


  useEffect(() => {
    TweenMax.to(lineAnimate.current, 1.2, {
      morphSVG : lineRef.current,
      repeat: -1,
      yoyo: true,
      ease: Sine.easeInOut,
      delay: 0,
    });
  });

 

  • Like 1
Link to comment
Share on other sites

6 minutes ago, GreenSock said:

Did you register the plugin? 

 

Ain't gonna happen using this syntax.

 

16 minutes ago, conspireagency said:

 


import TweenMax from 'gsap'
import Sine from 'gsap'
import MorphSVGPlugin from 'gsap/MorphSVGPlugin'

 

TweenMax and Sine are the gsap object.

 

Please read the install page and watch this video.

https://greensock.com/docs/v3/Installation

 

 

 

 

 

 

  • Like 2
Link to comment
Share on other sites

1 minute ago, OSUblake said:

TweenMax and Sine are the gsap object.

 

That's why we recommend using brackets. That way you won't import the wrong object, and the correct objects will show up in auto-complete.

 

import { gsap, Sine} from 'gsap'
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin'

gsap.registerPlugin(MorphSVGPlugin);

const lineAnimate = useRef(null);
const lineRef = useRef(null);

useEffect(() => {
    gsap.to(lineAnimate.current, 1.2, {
      morphSVG : lineRef.current,
      repeat: -1,
      yoyo: true,
      ease: Sine.easeInOut,
      delay: 0,
    });
  });

 

Or use string format for eases.

 

import { gsap } from 'gsap'
import { MorphSVGPlugin } from 'gsap/MorphSVGPlugin'

gsap.registerPlugin(MorphSVGPlugin);

const lineAnimate = useRef(null);
const lineRef = useRef(null);

useEffect(() => {
    gsap.to(lineAnimate.current, 1.2, {
      morphSVG : lineRef.current,
      repeat: -1,
      yoyo: true,
      ease: "sine.inOut",
      delay: 0,
    });
  });

 

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