はじめに
APNGもしくはGIF画像を画面内に複数表示する必要があり、いくつか問題にぶつかりました。
私が直面した問題と解決策を残します。
この記事の対象者
- 連続で同じAPNG/GIF画像を連続表示したい人
- 一度使用したAPNG/GIF画像を最初からアニメーションさせたい
同じAPNG/GIF画像を連続表示させる
Vueで作成していきます。最小限のtemplateを共通で利用して、scriptの部分に手を加えていきます。
共通template部分
<template>
<button @click="createImg">
画像追加
</button>
<div class="gif-list" ref="list"></div>
</template>
扱うGIFアニメーション画像
以下のカウントダウンアニメーションGIF画像を利用します。再生時間は10秒で、繰り返し再生はしません。
1. 何も手を加えずGIF画像を連続表示する
まずはシンプルにref属性list
が指定されているdivタグの下にcreateElementで生成したimgタグを追加していく処理を試してみます。
createImg() {
const newElement = document.createElement("img");
newElement.src = "画像パス";
this.$refs.list.prepend(newElement);
}
同じGIF画像を追加していくと、最初に表示したGIFアニメーションと同じアニメーションが実行されてしまいます。後から追加したGIF画像を各々最初からアニメーションさせるにはどうすれば良いでしょうか。
2. 連続表示したGIF画像を各々最初からアニメーションさせる
URLパラメータを付与して別のファイル名で呼び出すことで、追加したGIF画像がそれぞれ独立して最初からアニメーションするようになります。
createImg() {
this.count++;
const newElement = document.createElement("img");
newElement.src = "画像パス" + `&${this.count}`; // URLパラメータを適当に追加する
this.$refs.list.append(newElement);
}
追加したGIF画像が最初からアニメーションするようになりましたね。
連続表示の際に通信量を削減する
これで連続表示で最初からアニメーションさせる件は解決しましたが、パフォーマンス面の問題があります。以下が連続表示した際の通信状況です。
毎回通信発生してるじゃん…
サイズは少量ですが、高速で連打を長時間されたらサイトに負荷がかかってしまいます。なのでこちらも対策を取ります。
繰り返しで同じファイル名を利用する
createImg() {
this.count++;
const newElement = document.createElement("img");
newElement.src = "画像パス" + `&${this.count}`;
newElement.id = `gif-${this.count}`
this.$refs.list.prepend(newElement);
// 5個表示したらカウントを0にする
if (this.count === 5) {
this.count = 0;
}
}
画像を5個表示したらカウントを0に戻し、同じファイル名のGIFアニメーションを表示するようにしました。
これで画像取得の最大回数は5回になり、大量の通信発生の心配はありませんね!
しかし実際に表示される内容は以下のようになりました。
一度表示したファイル名と同じURLパラメータだと最初からアニメーションしない…
それでは最初からGIFアニメーションを最初から再生させたい場合は、通信を大量に発生させるしかないのでしょうか。
アニメーションを最初から再生させる
最終的に以下のようになりました。
createImg() {
this.count++;
// 再度表示する場合は一度srcを空にする
const removeElement = document.querySelector(`#gif-${this.count}`);
if (removeElement) {
removeElement.src = "";
removeElement.remove();
}
const newElement = document.createElement("img");
newElement.src = "画像パス" + `&${this.count}`;
newElement.id = `gif-${this.count}`
this.$refs.list.prepend(newElement);
// 5個表示したらカウントを0にする
if (this.count === 5) {
this.count = 0;
}
}
以下結果です。
追加したGIF画像が最初から再生されているのがわかりますでしょうか?通信も5回しか発生していません。
追加したのは以下の部分になります。
// 再度表示する場合は一度srcを空にする
const removeElement = document.querySelector(`#gif-${this.count}`);
if (removeElement) {
removeElement.src = "";
removeElement.remove();
}
画像を最初から再生するために重要なのは既に表示中のGIF画像のsrcを空にしている部分です。画面上に表示されているGIF画像のimg要素のsrcを空にすることで、後から同じGIF画像を挿入したら最初からアニメーションされることがわかりました。