サイトにマスコットキャラクターを置いて、ちょっと動かしたい。
「アニメーションGIF」だと、輪郭のギザギザにがっかりすることになります。
この記事では、なぜGIFがギザギザになるのかという原因から、最終的に『AnimeEffects』から、アニメーションWebP に変換するまでを解説します。
GIFがギザギザになる理由
GIFのアルファチャンネルは1bitしかありません。 つまり「透明」か「不透明」の2値だけ。
イラストの輪郭には、アンチエイリアスによって「半透明のグレー」が乗っています。GIFはこの中間階調を表現できないので、なめらかだった曲線が階段状に化ける。これは書き出し設定でどうにかなる話ではなくフォーマットの仕様です。
逆に言えば、8bitアルファ(256段階)を持つフォーマットに変更すれば、解決します。
| フォーマット | アルファ | 結果 |
|---|---|---|
| GIF | 1bit(2値) | ギザギザ |
| APNG | 8bit | なめらか・ファイル大 |
| アニメーションWebP | 8bit | なめらか・ファイル小 |
| WebM(VP9 alpha) | 8bit | <video> タグ用・非可逆 |
選択肢を整理する
「キャラを動かしてWebに置く」の実現手段は、それぞれ得意分野が違うので、目的から逆算して選ぶのが正解です。
1. SVG + CSS アニメーション
イラストがベクター原稿なら、これが第一候補です。
- 完全ベクターなのでRetinaでも4Kでも劣化ゼロ。ギザギザという概念がない
- 数KB〜十数KB。ランタイム不要
prefers-reduced-motion対応が1行
パーツごとに <g id="..."> で括って、transform-origin に支点を指定して回します。
#arm-r {
transform-box: view-box; /* ← これを忘れると支点が狂う */
transform-origin: 375px 142px; /* 肩の座標(viewBox基準) */
animation: wave 1.5s ease-in-out infinite;
}
@keyframes wave {
0%, 60%, 100% { transform: rotate(0); }
30% { transform: rotate(-26deg); }
45% { transform: rotate(6deg); }
}
@media (prefers-reduced-motion: reduce) { #arm-r { animation: none; } }
transform-box が最大のハマりどころです。指定しないとブラウザによって支点の解釈がズレるので、view-box(viewBox座標で指定)か fill-box(要素のバウンディングボックス基準)を明示してください。
ラスター画像でも使えます。 パーツごとに透過PNGを書き出してCSSで重ねて回せば同じことです。PNGは8bitアルファなのでギザギザも出ません。
制約は、メッシュ変形(ぐにゃっと曲げる系)が再現できないこと。回転・移動・拡縮までです。
2. Live2D
Cubism SDK自体はダウンロード無料ですが、SDKを使って作ったコンテンツをリリースする際は「SDKリリースライセンス(出版許諾契約)」の締結と契約料が必要です。個人・小規模事業者(直近の年間売上高1,000万円未満)の場合は契約も支払いも不要。
制作者が小規模事業者で「自社ブログのマスコットならタダ、客先に納品するなら先方に契約が要る」ということです。企業案件としては使いにくいです。
3. Rive
2025年10月に方針が変わって、書き出し(.riv)が有料になりました。 「Free to create. $9/month to ship.」というのが公式の言い方で、Cadet($9/月・年払い)が本番利用の最低ラインです。
4. 『AnimeEffects』 → PNG連番 → 可逆WebP
- ライセンスがクリーン(GPL)。自社でも客先でも制約なし
- メッシュ変形・ボーンが使える
- ランタイムゼロ。
<img>タグ1行で貼れる - 8bitアルファなのでギザギザなし
「ちょっと動いてかわいい」が目的なら、費用対効果はこれが良いです。
AnimeEffects
AnimeEffects は hidefuku 氏による2Dアニメーションツールです。ポリゴンメッシュの変形をベースにした各種機能で、綿密な計画なしにアニメーションを作れる、というコンセプト。
オリジナルは v1.3.4(2017年4月)で更新が止まっています。
Mac/Windowsの実行ファイルがGitHubで公開されているので、いまでも普通に動きます。
そして、有志がフォークして開発を継続しています。
現在のリードデベロッパーは p-yukusai 氏。リリース履歴はこうなっています。
| バージョン | 公開日 | 主な内容 |
|---|---|---|
| v1.3.4 | 2017-04 | hidefuku氏によるオリジナル最終版 |
| v1.5.1 | 2024-01 | |
| v1.6 | 2025-03-11 | オーディオシステム。Windows版はMSVC再頒布可能パッケージが必須に |
| v1.6.1 | 2025-05-24 | M1以降向けMacインストーラ |
| v1.7 | 2025-08-04 | カスタムイージング/ベジェエディタ、クイックエクスポート、PSD読み込み時のクラッシュ修正 |
| v1.7.1 | 2025 |
配布は itch.io(yukusai.itch.io/animeeffects)とGitHub Releasesの両方。日本語の情報が v1.4.3 あたりで止まっているので、古い版を掴んだまま「これが最新」と思い込みやすいので注意です。
macOSでの導入:Gatekeeperと権限の罠
Macで v1.7.1 の .pkg から、インストールはできた。ところが、.app をダブルクリックしてもうんともすんとも言わない。
AnimeEffectsは署名・公証されていません。作者本人が明言していて、v1.6.1でM1以降向けインストーラが用意されたのも「Appleに年100ドル払わない開発者にAppleが課してくる問題」を回避するためです。
macOS 15 Sequoia以降は「右クリック → 開く」の裏技が廃止されているので、こうします。
sudo xattr -dr com.apple.quarantine /Applications/AnimeEffects.app
sudo が要ります。.pkg でインストールするとバンドルがroot所有になるので、一般ユーザーでは属性を触れません。GUIでやるなら システム設定 → プライバシーとセキュリティ → 「このまま開く」。この項目は弾かれた直後の約1時間しか出ないので、見当たらなければもう一度ダブルクリックしてください。
バンドル内に設定を書き込む設計
xattr のエラー出力に、こんな行が混ざります。
Permission denied: '/Applications/AnimeEffects.app/Contents/MacOS/.AECache'
Permission denied: '/Applications/AnimeEffects.app/Contents/MacOS/data/locale/preference.txt'
このアプリ、自分のバンドルの中に設定とキャッシュを書きます。 root所有の /Applications に置かれると、一般ユーザーで起動したときに自分の設定ファイルが書けず、起動処理の途中で静かに死ぬ——という筋書きが成立します。
sudo chown -R "$(whoami)" /Applications/AnimeEffects.app
v1.5.1のchangelogに「Windowsインストーラのスクリプトをユーザー書き込み可能なフォルダにインストールするよう変更」という項目があるので、この設計の副作用は開発側も認識しているようです。Mac側は同じ手当てが入っていないのかもしれません。
切り分けはターミナルから
原因が分からないときは、直接叩くのが一番速いです。
/Applications/AnimeEffects.app/Contents/MacOS/AnimeEffects
Gatekeeperなら killed: 9、
アーキ違いなら Bad CPU type in executable、
Qtプラグイン欠落なら could not find or load the Qt platform plugin "cocoa"。
それぞれ違うメッセージが出るので、ここまでで原因が確定します。
なお、v1.3.4は普通に起動しました。 古い版を残しておいてよかったです。
PSDが読めない問題(未修正のバグ)
パーツ分けしたPSDを読ませると、こうなることがあります。
Failed to load the image file.
error(2) invalid signature. (layer and mask info/additional layer info/signature) '8'
PSDの形式が新しくなったからではありません。AnimeEffects側のパーサのバグです。 ソースを追うと確定できます。
src/img/PSDReader.cpp の該当箇所。
// signature
std::string signature = readString(4);
if (checkFailure()) return false;
if (signature != "8BIM" && signature != "8B64")
{
mSection += "/additional layer info/signature";
mValue = signature;
mResultCode = ResultCode_InvalidSignature;
return false;
}
4バイト読んで 8BIM か 8B64 でなければ即エラー、読めた中身をそのまま mValue に入れて表示する。つまりダイアログの '8' は「4バイト読んだらズレた位置に着地していた」証拠です。ネット上には同じエラーで '8BI' と報告している人もいて、これは1バイトズレ。
原因はその数十行下にあります。
// read as a raw data
info->data.reset(new uint8[info->dataLength]);
readBuf(info->data.get(), info->dataLength);
if (checkFailure())
return false;
// to next
length = aEndPos - tellg();
dataLength ちょうどしか読まずに次のブロックへ行っています。パディングを飛ばしていない。 PSD仕様ではこのデータ長はアラインメント調整されるので、端数のあるブロックが1個でもあると、そこから先が全部ズレて次の signature 読みで死にます。
しかも同じファイル内の別のブロック処理では、ちゃんとパディングを飛ばしているんですね。
if (block->dataLength % 2 != 0)
{
skip(1);
}
additional layer info の側だけ抜けている。
現行フォーク(AnimeEffectsDevs/master)の同じ箇所も1文字も変わっていません。 v1.7で「PSD読み込み時のクラッシュ修正」が入っていますが、こちらは別件です。つまり最新版に上げても直りません。
対処
additional layer info は、レイヤー効果・テキスト・スマートオブジェクト・調整レイヤー・リンクレイヤーなどが増えるほど膨らみます。素のラスターレイヤーだけにすれば踏む確率は下がりますが、確実ではありません。
PSDを諦めるのが早いです。 パーツごとに透過PNGで書き出して、個別に読み込ませればいい。PNGはQtの標準デコーダを通るので、この自作PSDパーサのバグとは無関係です。
実践:パーツ分けPNGを読み込む
「リソースの追加」が見つからない
v1.3.4での最初の関門です。メインメニューをいくら探しても出てきません。
ResourceDialog.cpp を見ると理由が分かります。
auto menuBar = new QMenuBar(this);
auto fileMenu = new QMenu(tr("File"), menuBar);
auto addResource = new QAction(tr("Add Resource"), fileMenu);
fileMenu->addAction(addResource);
menuBar->setNativeMenuBar(false); // ← ここ
this->setMenuBar(menuBar);
setNativeMenuBar(false) が効いていて、macOSの画面上端のメニューバーには出ません。 「リソースウィンドウ」という別ウィンドウの中に、そのウィンドウ専用の小さいメニューバーが描かれていて、そこの ファイル → リソースを追加する です。
v1.4.2で「メニューの代わりに『リソースの追加』ボタンを置いてリソース追加を簡略化」という変更が入っているので、これは既知のUX問題です。
受け付ける拡張子もソースで確認できます。
"ImageFile (*.psd *.jpg *.jpeg *.png *.gif)"
パーツはキャンバス全面サイズで書き出す
各パーツのPNGを、全部同じキャンバスサイズで書き出してください。 透過込みで位置はそのまま。こうしておくと読み込んだ時点で全パーツがぴったり重なるので、位置合わせの作業がまるごと消えます。
「中心」がピボット
ここが本記事でいちばん重要かもしれません。
AnimeEffectsの「中心」は、CSSの transform-origin そのものです。
デフォルトは画像の中心です。そのまま回転キーを打つと、キャンバスのど真ん中を軸に腕が振り回されます。肩の座標に書き換えてから回転キーを打ってください。 これだけで、ちゃんと腕を振る動きになります。
なお中心を変更すると画像がズレるので、移動キーで位置を戻すことになります。これは仕様どおりの挙動です。
書き出し設定
出力メニューには JPEG連番 / PNG連番 / GIFアニメーション / MP4 / WebM / AVI / MOV / Ogg が並んでいます。
PNG連番を選んでください。
終了フレームとフレームレート
ループアニメを作ると、最終フレームは1フレーム目と同じポーズになっているはずです。そのまま全部書き出すと同じ絵が2枚並んでループ点で一瞬停まります。
- 0〜120 → 121枚(最後が重複)
- 0〜119 → 120枚 ← これが正解
なので、 終了フレームを1つ減らします。
mIndex * プロジェクトfps / 出力fps がリサンプル処理です。プロジェクトが60fpsのときに出力フレームレートへ30を入れると mIndex * 60/30 = mIndex*2 になり、プロジェクトフレームを1個飛ばしでサンプリングします。
プロジェクト60fps・2.0秒(120フレーム)なら、
書き出し:フレームレート30 / 開始0 / 終了119 で、ループが繋がります。
可逆アニメーションWebPに変換する
libwebp の img2webp を使います。
brew install webp
cd "[PNG連番の出力先]"
ls frame_*.png | xargs img2webp -loop 0 -lossless -d 33 -o mascot.webp
ゼロ埋め連番なので、シェルのグロブ展開の順序でそのまま正しく並びます。
-lossless を必ず使ってください。 フラットな塗り+黒線のイラストは可逆WebPが異常に得意で、非可逆より小さくなることすらあります。非可逆にすると yuva420p に落ちて黒線がにじみます。
-d はディレイ(ミリ秒/1コマ)です。 ここがフレームレートと噛み合っていないと、意図した速度で動きません。
| 書き出しfps | -d |
|---|---|
| 24fps | 42 |
| 30fps | 33 |
| 60fps | 16 |
30fpsで書き出したのに -d 42 にすると、約23.8fpsで再生されるので25%ゆっくり動きます。
PNG連番は中間素材として残しておいてください。 あとからWebPを作り直すのも、APNGにするのも、スプライトシートにするのも、全部そこから分岐できます。PNG連番が原本、WebPは成果物という位置づけです。
実践:HTMLに置く
<img src="https://code-plus.jp/gp/wp-content/themes/zaratan/images/Mascot.webp" alt="" />
<img> タグ1行です。ランタイムもJSも要りません。
prefers-reduced-motion への対応
アニメーションWebPはCSSで止められません。prefers-reduced-motion に応えるなら、静止画に差し替える形になります。
<picture>
<source media="(prefers-reduced-motion: reduce)" srcset="https://code-plus.jp/gp/wp-content/themes/zaratan/images/Mascot-static.png" />
<img src="https://code-plus.jp/gp/wp-content/themes/zaratan/images/Mascot.webp" alt="" />
</picture>
まとめ
| 初期コスト | ライセンス | 客先納品 | 表現力 | |
| パーツ分け + CSS | パーツ分けのみ | なし | ◎ | 回転/移動/拡縮 |
| AnimeEffects → WebP | 小 | なし(GPL) | ◎ | ◎ 変形も可 |
| Live2D | 大 | 客先の売上で判定・要契約 | ✗ | ◎ マウス追従 |
| Rive | 中 | $9/月(書き出し時) | △ | ◎ |
要点を絞ると、こうなります。
- GIFのギザギザは1bitアルファが原因。 8bitアルファのフォーマットに変えれば設定不要で直る
- AnimeEffects → PNG連番 → 可逆WebP が、ライセンス・重さ・画質の三方よし。
<img>1行で貼れる
パーツ分けPNGとプロジェクトファイルは残しておいてください。
耳を揺らす、まばたきを足す、あたりは同じプロジェクトにノードを足すだけです。
参考リンク
- Release version1.3.4 · hidefuku/AnimeEffects — オリジナル最終版(2017年4月)
- AnimeEffectsDevs/AnimeEffects — 開発継続中のフォーク
- AnimeEffects 公式サイト
- AnimeEffects by Yukusai (itch.io) — 配布とdevlog