skip to content
私的歌詞倉庫

LottieのJsonファイルをGitHub Pages上で簡単に管理できるツールLottie Bookを作った

/ 11 min read

Updated:
Table of Contents

はじめに

最近業務でデザイナーさんとLottieのJsonファイルをやり取りする時に困ることが少しありました。

  • Jsonファイルを貰ってもそのファイルがどんなアニメーションをするか手軽に試せない
    • 外部サイトを使えば確認できるがあまり気が進まない(LottieFilesがあるが手順を間違えると全公開されるし、社外にはできるだけアップロードしたくない)
    • 確認するにはコードに組み込んで見るくらいしかない
  • すでにプロジェクト内にあるJsonファイルのアニメーションをすぐに確認できない

これらの問題を解決するために、Lottieを確認できる環境をかんたんに社内で立ち上げることができ、Jsonファイルをリポジトリに入れておくだけでstorybook的に誰でも見れるツールLottie Bookを作りました。

コンポーネント単位で表示

コンポーネント単位で表示

![Jsonファイルを再生](./img/output 1.gif)

Jsonファイルを再生

https://github.com/Tatsumi0000/lottie-book

このツールを作るために使用した技術はこちらです。

ツールバージョン
Docker29.1.3
Deno2.6.3
Vue3.5.24
Vuetify3.11.5

使い方

https://github.com/Tatsumi0000/lottie-book のリポジトリをtemplateリポジトリとして登録しているので、右上にある Use this template をクリックして管理したいorgにリポジトリを展開して下さい。

次にGitHub Pagesの設定をします。Settings → PagesにあるBuild and deploymentのSourceをGitHub Actions に設定します。

あとはsrc/assets/lightsrc/assets/dark に管理したいJsonファイルを入れれば自動でGitHub Pages上にデプロイします(要mainブランチへのcommit)。

機能や工夫した点

機能や工夫した点について紹介します。

機能についてはサンプルページを作っているので、こちらを触ってもらうほうが分かりやすいかもしれません。

Lottie Book

自動でJsonファイルをコンポーネント単位で表示

src/assets/lightsrc/assets/dark にJsonファイルを入れるだけで自動で全てのJsonファイルを読み込んで展開します。

ライトモードとダークモードに対応しており、画面右上のテーマ切り替えスイッチをクリックすることで対象のJsonファイルを自動で切り替えて読み込みます。

ライトモード

ライトモード

ダークモード

ダークモード

コンポーネントをクリックすることで拡大して表示することもできます。

コンポーネント単位で表示

コンポーネント単位で表示

メンバーとスムーズにコンポーネントのやり取りをするためにホバー表示したURLは動的に変えているので、このURLを他の人に共有するだけで誰でも簡単にシェアすることができます。例えば上記のスクショのURLは https://tatsumi0000.github.io/lottie-book/#/preview/light/rectangle_scale.json になるのでこれをシェアするだけですぐに開けます。

Jsonファイルをドラッグアンドドロップして再生

やっぱりかんたんにJsonファイルを再生できる環境が社内にも欲しかったので作りました。ヘッダーの左上にあるハンバーガーメニューから遷移できます。

![Jsonファイルを再生(再掲)](./img/output 1.gif)

Jsonファイルを再生(再掲)

docker と Makefileを使った開発環境構築

できるだけ誰でも簡単に開発できるようにdocker上で動くようにしていて、さらにイメージのビルドやライブリのインストールをmakeコマンドでできるようにしています。

良い開発環境はMakefileを見れば全てわかるみたいなことをどこかで聞いたことがあった気がするのでできるだけそちらに寄せるようにしました。

Lottie Booksはこのコマンドでブラウザの確認まで終わるようにしています。

make setup
make up

実装で苦労した点

実装で苦労した点について紹介します。

nvim上でDeno + Vueを開発

そもそもなんですが久しぶりにnvimでVueを開発しようとしたらLSP周りの設定が全然動かなくて非常に困りました。

こちらは別記事で紹介済みなのでもしよかったらこちらも御覧ください。

NeovimでDeno + Vueを開発

Jsonファイルを一括で読み込む

通常Jsonファイルなどを読み込むときはimportでパスを指定して読み込みますが、今回は自動で全て読み込んでほしかったので一括で読み込むようにしています。

こちらは標準機能としてあるimport.meta.glob を使うことで一括で読み込んでいます。

// darkディレクトリ内のJsonファイルを一括で読み込む場合
import.meta.glob<string>(`@/assets/dark/*.json`, {
eager: true,
});

Jsonファイルのバリデーション

Jsonファイルをドラッグアンドドロップする機能ではバリデーション機能も実装しました。

アップロード画面自体はVuetifyのlabにVFileUploadコンポーネントがあったのでこちらを使っています。このコンポーネントに拡張子のバリデーション機能があったので使いました。

<template>
<VFileUpload
v-model="fileDefineModel" // ここにアップロードされたファイルが入ってくる
filterByType=".json" // 拡張子をJsonしか受け付けない
@rejected="rejectedEvent" // 拡張子で引っかかった時に実行するイベント
/>
<VAlert
v-model="isShowError"
type="error"
variant="tonal"
closable
:icon="mdiAlertCircle" // エラーアイコンを変更
class="mb-6"
@click:close="onAlertClosed()"
>
{{ errorMessage }}
</VAlert>
</template>
<script setup lang="ts">
const isShowError = ref(false);
const errorMessage = ref("");
const rejectedEvent = () => {
triggerError(
"ファイルタイプが不正です。JSONファイルをアップロードして下さい。",
);
};
const triggerError = (message: string) => {
errorMessage.value = message;
isShowError.value = true;
};
</script>

TypeScriptのエラー処理

あまりTypeScriptを触らないのでエラー処理をどうやるかあまり良くわかってなかったのですが、例外をcatchしてそのエラーの型をinstanceof でチェックしていくのが主流っぽそうでした。

今回はJsonファイルのドラッグアンドドロップ機能で、そのファイルがJson構造かどうかのチェックをする時に使いました。

<script setup lang="ts">
interface FileInfo {
name: string;
animationData: object;
}
const fileInfo = ref<FileInfo>();
const fileDefineModel = defineModel<File | File[] | undefined>();
watch(fileDefineModel, async (newFile) => {
try {
if (newFile instanceof File) {
isShowError.value = false;
const text = await newFile.text();
fileInfo.value = {
name: newFile.name,
animationData: JSON.parse(text),
};
}
} catch (error) {
fileDefineModel.value = undefined;
// instanceofでチェックしていく
if (error instanceof SyntaxError) {
triggerError("JSONの構文エラーが発生しました。");
} else {
triggerError("読み込みまたは解析に失敗しました。");
}
}
});
</script>

アイコンフォントの軽量化

一通り実装して本番ビルドをしたところ、生成したファイルが2.5MB程度と結構大きかったです。

調べるとMDIがかなりの大部分を占めていたので必要なアイコンだけ読み込むことで400KB程度に軽量化することが出来ました。

公式サイトのこちらを参考にしています。

Icon Fonts — Vuetify

import { aliases, mdi } from "vuetify/iconsets/mdi-svg";
export default createVuetify({
// 色々設定があり…
icons: {
defaultSet: "mdi",
aliases,
sets: {
mdi,
},
},
});

呼び出したいときは個別にimportして使う。

import { mdiPlay } from "@mdi/js";

エディタ上でimport “vuetify/styles”;のエラーが出る

vuetify/stylesをimportする時に拡張子をつけないとエディタ上ではエラーが出るのですが、ビルドには成功していました。逆に拡張子をつけるとビルドに失敗していました。

エディタ上のエラーは無視しても良かったのですが煩わしかったので@ts-ignore をつけることで無視するようにしました。

// @ts-ignore "vuetify/styles.css"にしないとエラーにならないけど拡張子をつけるとビルドエラーになるので除外
import "vuetify/styles";

終わりに

Lottieファイルをかんたんに管理できるLottie Bookを作りました。

業務ではClaude Codeを使ってばかりなので、きちんと自分の頭でゼロから考えてコードを書きたいなと思ったのが発端だったのですがそこそこ良いツールが出来たのではないかと自画自賛しています!

Denoは興味があったのでとりあえず使ってみたのですがVueがDenoに対応しておらず、互換性モードを使うことにことになったのであまり旨みを感じることが出来ませんでした。

色々バグもあるので細かい修正をしつつ今後も気長に開発できたらなと思ってます!(多言語対応が完了したらRedditとかに投稿してみたいな)