SVG Arrow Animation

Viewed 964

I have implemented a growing SVG animation, and as I'm not that familiar with SVG animations, there are few issues with my implementation. The animation is simple, as I hover the SVG arrow will move forward, meaning the line will grow and the tip will move along with the line. It works well on Chrome, however, in Firefox, Safari it does not work as expected, the line and the tip of arrow will move with slight delays. I tried a few things however I does not seem to work for other browsers. Here is my code:

<div className="slider-arrow-down-btn" style={{ cursor: 'pointer' }}>
  <Link title="scroll down" to="/#homepage" onMouseEnter={this.handleOnEnter} onMouseLeave={this.handleOnLeave} className="animated-arrow-bottom">
    <svg xmlns="http://www.w3.org/2000/svg" width="30" height="61" viewBox="0 0 30 61">
      <g fill="none" fillRule="evenodd">
      <path id="arrow-path-bottom" stroke="#FFF" strokeLinejoin="bevel" strokeWidth="4" d="M2.5 39.5l12.5 20 12.5-20" />
      <path id="arrow-line-bottom" fill="#FFF" d={`M17 0v${pathHeight}h-4V0z`} />
    </g>
    </svg>
  </Link>
</div>

And the methods:

handleOnEnter = () => {
  this.setState({ pathHeight: 100 });
}

handleOnLeave = () => {
  this.setState({ pathHeight: 60 })
}

And here is the original svg:

<svg xmlns="http://www.w3.org/2000/svg" width="30" height="61" viewBox="0 0 30 61">
    <g fill="none" fill-rule="evenodd">
        <path stroke="#FFF" stroke-linejoin="bevel" stroke-width="4" d="M37 23L49.5 3 49.5 3 62 23" transform="rotate(90 14 14) matrix(0 -1 -1 0 62.5 62.5)"/>
        <path fill="#FFF" d="M0 11L60 11 60 15 0 15z" transform="rotate(90 14 14)"/>
    </g>
</svg>

So the expected result is whenever I hover the svg the line will grow (and stay fixed at beginning) and the point will move with it at the same time, without delays. Thank you!

1 Answers

I would avoid, when working with SVGs, manually altering their path data as it could quickly become messy.

The best way to ensure two elements moving separately move at the same time is to group them together and just move the group, I would structure your SVG so that you have something like the following:

<svg>
  <line {...{ /* Line Properties */ }} />
  <g {...{ /* Transform Properties */ }}>
    <line {...{ /* Line Properties (as above) */ }} />
    <path {...{ /* Arrow Head Properties */ }} />
  </g>
</svg>

Imagine both lines here are the exact same line, except because one is directly overlaying the other- when the grouped line/arrowhead moves it looks like it extends.

Then in your state for the transform group properties something like:

const groupProps = isHovered ? { transform: 'translate(0 50)' } : { transform: 'translate(0 0)' };
Related