🤮

SVGにクラス名をつけようとした時の話

2022/07/14に公開

花火のSVGに点滅アニメーションをつけたい

複数のpathからできているSVGにクラス名をつけようとしたときにcssでopasityで制御しようとしてこのように記述しました

hanabi.scss

@for $i from 0 through 10 {
  .hanabi#{$i} {
    animation: fire 1.4s 0.5s * $i infinite;
  }
}

@keyframes fire {
  0% {
    opacity: 0;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

scss記法でpath.hnabi1(pugの記法)となるとdelay 0.5sに1をかけるといった記述です。
それが1~10まであります

実際にクラス名を書こうとするとかなり大変.....

花火のSVGですがpathの記述が500行ちかくありました、、、しかも8種類、、、

これに気分で1~10を適当に(pugの記法)

path.hnabi1(d='hoge')
path.hnabi5(d='hoge')
path.hnabi8(d='hoge')
path.hnabi2(d='hoge')
path.hnabi4(d='hoge')
.........

と書くのはかなりの拷問とは思いませんか?

javascriptでランダムにつけたらクソ楽やん!!!!!

人間は愚かで楽して生きようとします

//読み込み時に反映したいから window.onload
window.onload = function () {
  //要素を指定
  let fire = document.querySelectorAll('.hanabi');
  //fireの数だけ繰り返す
  for (let i = 0; i < fire.length; i++) {
    let num = 1 + Math.floor(Math.random() * 10);
    fire[i].className += num;
  }
};

動きそうですよね?でも実際には以下のようなエラーがはかれます

hoge.js:10
Uncaught TypeError: Cannot set property className of #<SVGElement> which has only a getter at ./src/foge

なんかSVG内にはアクセスできないみたいですな...
しらべてみるとSVGの中は属性扱いみたいですなのでクラス名にアクセスするのではなく属性にアクセスしましよう

window.onload = function () {
  let fire = document.querySelectorAll('.hanabi');
  for (let i = 0; i < fire.length; i++) {
    let num = 1 + Math.floor(Math.random() * 10);
    fire[i].setAttribute('class', `s-blinking-hanabi__fire${num}`);
  }
};

上記のように記入することで思ったとうりの挙動になりました!!!!!

終わり

Discussion