lukePeavey / SplitType

Javascript utility that splits text into lines, words, characters for animation
https://lukepeavey.github.io/SplitType/
545 stars 39 forks source link

Is it possible to delete the created SplitType instance? #39

Closed allkrain closed 1 year ago

allkrain commented 2 years ago

Is it possible to correctly remove an existing SplitType instance when, for example, unmounting a vue component? Otherwise, if I unmount using revert on the next connections for the first time, I get no text split at all, and then I get a double split. Each letter is perceived as a separate word and turns into two additional elements .word and .char

lukePeavey commented 2 years ago

Would it be possible to provide a live example of this issue on codeSandbox?

lukePeavey commented 2 years ago

Is it possible to correctly remove an existing SplitType instance when, for example, unmounting a vue component?

To answer the first part of your question, calling the revert method is the correct way to cleanup a SplitType instance before the component is unmounted. I created several simple examples using React and Vue, and was not able to reproduce the issue you described. If you could provide a live example of this issue on CodeSandbox I will definitely check it out.

Vue

Use the beforeUnmount lifecycle method to perform cleanup.

Live Example on CodeSandbox

export default {
  name: 'SplitText',
  props: {
    msg: String,
  },
  // Split text and animate into view
  mounted() {
    this.text = SplitType.create('h1')
    this.animation = gsap.timeline()
    this.animation.from(this.text.chars, {
      y: 10,
      z: -50,
      scale: 0.5,
      opacity: 0,
      rotateX: 30,
      duration: 0.6,
      ease: 'back.out(2.0)',
      stagger: { each: 0.02 },
    })
  },
  // Cleanup:  kill animation and revert split text
  beforeUnmount() {
    this.animation.kill()
    this.text.revert()
  },
}

React

Use the cleanup function of an effect hook to revert text.

Live Example on CodeSandbox

export default function Text({children}) {
  const target = useRef();
  useEffect(() => {
    if (target.current) {
      console.log("Splitting Text");

      // Split text and animate into view
      const text = SplitType.create("h1", { types: "lines,chars" });
      const animation = gsap.timeline();
      gsap.set(target.current, { visibility: "visible" });
      animation.from(text.chars, {
        y: 10,
        z: -50,
        scale: 0.5,
        rotateX: 30,
        opacity: 0,
        duration: 0.6,
        ease: "back.out(2.0)",
        stagger: { each: 0.02 }
      });
      // Cleanup:  kill animation and revert split text
      return function cleanup() {
        animation.kill();
        text.revert();
      };
    }
  }, []);

  return <h1 ref={target}>{children}</h1>;
}
lukePeavey commented 2 years ago

Possibly related to #40

allkrain commented 2 years ago

I tried to reproduce this problem for you here: https://codesandbox.io/s/dreamy-http-ihnt46 When you follow the link and back, you will see that the gradient text disappears.

lukePeavey commented 2 years ago

@allkrain thanks I'll take a look

lukePeavey commented 2 years ago

I see what you mean. You can try calling revert in the beforeUnmount hook. This seems to fix the problem.

updated example

// src/components/Home.vue

export default {
  name: "Home",
  methods: {},
  mounted() {
    this.text = new SplitType(".split-text", { types: "words, chars" });
    this.animation = gsap.timeline();
    this.animation.fromTo(
      ".split-text .char",
      {
        autoAlpha: 0,
      },
      {
        autoAlpha: 1,
        duration: 0.3,
        stagger: 0.1,
        ease: "power1.outIn",
      }
    );
  },
  beforeUnmount() {
    this.animation.kill();
    this.text.revert();
  },
};
// src/components/Inner.vue
export default {
  name: "Iner",
  methods: {},
  mounted() {
    this.text = new SplitType(".split-text", { types: "words, chars" });
    this.animation = gsap.timeline();
    this.animation.fromTo(
      ".split-text .char",
      {
        autoAlpha: 0,
      },
      {
        autoAlpha: 1,
        duration: 0.3,
        stagger: 0.1,
        ease: "power1.outIn",
      }
    );
  },
  beforeUnmount() {
    this.animation.kill();
    this.text.revert();
  },
};
lukePeavey commented 2 years ago

@allkrain let me know if that worked for you

lukePeavey commented 1 year ago

Closing this as answered