🖋️

MacのSafariとスマホだけSVGのpathアニメーションが逆再生されるときの原因と解決方法

2022/06/23に公開

SVG pathアニメーションの挙動はブラウザに依存している?

ある案件でSVGのパスアニメーションを実装をしたのですが、検証の際に「Safari・スマホだけ逆再生される」という謎の現象に出くわしました。

デモ

簡易版のデモを作成しました。スクロールに合わせて描画されるアニメーションです。
(実際のデザインはもっと複雑)

原因

恐らくはイラレのバージョンによるSVGデータの出力方法の違いなのかなと思います。

というのも、本記事を書くにあたり逆再生の現象を再現しようと思ったのですがなぜか自分のイラレデータではSafari・スマホ共に逆再生の現象は起きませんでした。

ちなみに自分のパソコンのイラレはCC2022です。

解決方法

自分の場合は下記の2つの方法で解決できました。

1. イラレで「パスの方向反転」をする。
2. コード上でpathを初期化する際にstroke-dashoffsetの値をマイナスにする。

1.イラレで「パスの方向反転」をする

元データをもらっている場合、イラレでパスを選択して、
[オブジェクト]→[パス]→[パスの方向反転]

これで大体のパスは修正することができました。
https://note.com/dtp_tranist/n/na9b229153d55

複雑な図形になるとpath以外にpolylinepolygonも含まれてくる可能性もあります。
その場合は下記サイトを活用してpathに変換しました。
https://www.creamu.co.jp/blog/technology/2019/12/svg_polygon_polyline_path.html

2.コード上でpathを初期化する際にstroke-dashoffsetの値をマイナスにする

1.の方法でダメだった場合はこちらもお試しください。

pathのタグに対してgetTotalLengthで全長を取得し、その長さをstroke-dashoffsetとしてスタイルに適用しているのですが、この値をマイナスにすることで始点を反転させるイメージです。
これだけで直るパスもいくつかありました。

元のデータが分かりやすいように<svg>をそのままインラインで書いています。

index.html
<svg
  class="svg svg--fromLeft"
  id=""
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 909.73 274">
  <g id="">
    <path
      pathFromLeft
      class="svg__path"
      d="M4.031,137s218-297,420.5,0,481.556,0,481.556,0"
      style="fill: none;stroke: #000;stroke-miterlimit: 10;stroke-width: 10px;"
    />
  </g>
</svg>
<svg
  class="svg svg--fromRight"
  id=""
  xmlns="http://www.w3.org/2000/svg"
  viewBox="0 0 981.213 226.287">
  <g id="">
    <path
      pathFromRight
      class="svg__path"
      d="M977.175,125.411s-192.5-263.667-451.028-10.667S3.619,90.744,3.619,90.744"
      style="fill: none;stroke: #dc1800;stroke-miterlimit: 10;stroke-width: 10px;"
    />
  </g>
</svg>
main.js
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);

// すべてのパスを取得
const svgEls = document.querySelectorAll(".svg__path");

// パスの初期化
svgEls.forEach((el) => {
  const pathLenght = el.getTotalLength();//パスの全長を取得
  el.style.strokeDashoffset = pathLenght;//☆ここを -pathLength にすることで直る場合もある
  el.style.strokeDasharray = pathLenght;
});

// アニメーション
const tl = gsap.timeline();

tl.to(".svg__path", {
  strokeDashoffset: 0,//パスの描画
  scrollTrigger: {
    trigger: ".container",
    start: "top top",
    end: "center center",
    scrub: true
  }
});

ちなみに今回の現象はググっても中々出てこなかったのですが、下記のトピックでイラレで変えられるよみたいなことを言ってる方がいて、それをきっかけに解決に辿り着けました。
https://stackoverflow.com/questions/29333444/change-direction-of-svg-animation

レアケースだとは思いますが今後同じような現象に出くわした方の助けになれば幸いです。

参考サイト

https://note.com/dtp_tranist/n/na9b229153d55
https://stackoverflow.com/questions/29333444/change-direction-of-svg-animation
https://liginc.co.jp/312143
https://jakearchibald.com/2013/animated-line-drawing-svg/

Discussion