Search code examples
reactjsanimationsvgtransformintersection-observer

IntersectionObserver - transform properties targets the whole SVG animation and not class


I'm trying to get a svg animation to start when it's in the viewport. It works but when adding transform properties the whole svg and not just the targeted class is affected.

import React, { useEffect, useRef, useState } from 'react';
import { ReactComponent as Animation2Svg } from '../assets/animation3.svg';
import './animation2.css';

export const Animation2 = () => {
  const animationRef = useRef();
  const [visibleAnimation, setVisibleAnimation] = useState();
  console.log('visibleAnimation', visibleAnimation);
  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      const entry = entries[0];
      setVisibleAnimation(entry.isIntersecting);
      console.log('entry', entry);
    });
    observer.observe(animationRef.current);
    // console.log('animationRef', animationRef.current);
  }, []);

  return (
    <div
      ref={animationRef}
      className={`'animation_container' ${visibleAnimation ? 'lamp_fill' : ''}`}
    >
      <svg
        viewBox="0 0 960 960"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <g id="lamp">
          <g id="_12">
            <g id="Group">
              <path
                className="lamp_fill"
                d="M 673.8,268.9 C 670.49,212.31 666.03,147.85 624.05,105.09 605.03,88.927 595.75,88.708 576.1,80.6 534.08,69.765 491.07,82.083 449.66,89.913 382.62,105.67 316.07,123.33 250.11,143.21 201.04,156.23 143.22,156.92 106.41,196.62 76.875,241.04 84.709,297.04 84.201,347.5 86.612,407.39 83.901,468 85.176,528.14 91.427,563.78 86.363,600.74 93.601,636.8 98.899,686.58 100.94,736.75 110.7,786 111.72,829.71 125.29,878.56 165.7,901.7 198.5,924.75 239.5,926.4 278.1,929.56 334.3,923.31 391.34,926.4 447.84,924.66 496.01,923.32 545.09,928.05 592.56,918.66 626.73,907.16 644.69,870.96 647.87,836.92 653.71,790.73 638.83,744.73 638.8,698.8 639.22,658.74 633.25,618.65 640.1,578.7 645.02,533.8 655.02,489.37 657.67,444.12 668.11,386.49 675.47,327.74 673.8,268.9 Z"
              fill="black"
              />
              <!--multiple path elements-->
            </g>
          </g>
        </g>
      </svg>
    </div>
  );
};

And this I the CSS that works (and without transform properties)

.lamp_fill {
  transform-box: fill-box;
  fill: transparent;
  animation: turnOn 6s linear infinite;
}


@keyframes turnOn {

  0%,
  30% {
    fill: transparent;
  }

  40%,
  100% {
    opacity: 1;
    fill: #ffb200;
  }
}

I have tried to move the ref so ut targets the svg directly but to be honest I have no idea how to solve this.

Here is a CodeSandbox to illustrate the problem https://codesandbox.io/s/hopeful-tree-xmd32p?file=/src/App.js


Solution

  • Currently, the are two objects with the class lamp-fill, and both get animated.

    <div className={`animation_container ${visibleAnimation ? 'lamp_fill' : ''}`} >
    

    and

    <path className="lamp_fill" d="..." />
    

    If you want only the second one to be animated, set the class only there. Like this:

    <div
      ref={animationRef}
      className='animation_container'
    >
      <svg
        viewBox="0 0 960 960"
        fill="none"
        xmlns="http://www.w3.org/2000/svg"
      >
        <g id="lamp">
          <g id="_12">
            <g id="Group">
              <path
                className={visibleAnimation ? "lamp_fill" : ""}
                d="..."
              fill="black"
              />
              <!--multiple path elements-->
            </g>
          </g>
        </g>
      </svg>