うちのこメーカーのフロントエンド実装
今回は案件の振り返りということで、8月1日にリリースした「うちのこメーカー」のフロントエンド実装について、ご紹介しようと思います。
うちのこメーカーとは
「うちのこメーカー」は、株式会社GRITと弊社で共同開発した、パーツを選ぶだけで2億パターン以上の猫イラストと、そのイラストが入ったグッズが購入できるウェブサービスです。
サイトにアクセスして、体型や目、柄を選択していくだけで、簡単にイラストを作って画像をダウンロードすることができます。 また、GMOペパボ株式会社の様々なオリジナルグッズを作成できるサービス「SUZURI byGMOペパボ 」と API 連携することによって、作成されたうちのこイラストが入ったグッズも購入することが可能です。
グッズが1つ購入されるごとに、保護猫の約 1 日分の食事代に相当する金額が保護猫団体に寄付されます。
実装が始まるまでのフロー
自分の経験上ですが、大体の案件の場合、
企画が決まる
デザインが決まる
概要を聞く
実装が始まる
という流れで、2 ~ 3 あたりから参加する事が多かったのですが、今回は企画の段階からフロントエンドもミーティングに参加するというのが新鮮でした。
ミーティングの内容としては、プロデューサー、デザイナーの要望を聞いて検証をし、結果を元に再検討というのを繰り返し、実装が始まってからは進捗と実装の中で持ち上がった問題点について話しあって解決を目指すといった感じです。
検証
打ち合わせ段階から色々と問題提起がされていたのでその検証をやりつつ、実装開始に向けて動いていました。まず行われたのはプロジェクトの肝となるイラストの作成についての検証です。
デザイン・実装の工数を少しでも削減したいということで、イラストの共通で使える部分はどこなのかを検証していきました。
例えば、猫にはそれぞれ体型や色があるわけですが、それに関係なく柄を共通化できないかとデザイナーのデザインした猫(左)のサイズを私の方で変形(右)し、クリッピングパスを使って柄を使い回せないかやってみたり(最終的には各体型ごとに柄を調整した方が可愛くなるということで、使い回しは断念)。
また、同じ目や耳のパーツで各体型に組み合わせても破綻しないか検証したり。
さらに、全体が白く部分的に虎柄が入っているような猫については、Illustrator のソフトライトという機能を使って白い部分の柄だけ見えないようにするなどして対応することになりました。
こうした検証を行って、工数が削減できないか模索していきます。
実装開始
4月半ば頃からいよいよ実装が始まりました。
設計
まずは、全体の構成からどのようにファイル構造を作るかを考えます。下が全体の構成です。
トップ
過去のイラスト一覧
イラスト作成
商品
一覧
詳細
デザインを見るに必要なのは大きく分けて4ページ。
中でもイラスト作成ページが今回の実装では一番大変そうだったので、どうやって実装するのがいいか、デザインからSVGのレイヤー構成を先に考えてみました。
考えた結果、上から順に、
線だけをまとめたレイヤー
目・鼻・口のレイヤー
柄と色のレイヤー
体型のパスを集めたレイヤー
として、一番下のレイヤーでクリッピングマスクを作り、背景を透過させることにしました。
※完成形は試行錯誤の結果、身体部分と尻尾部分でレイヤーを分けたりと、もう少し複雑になってます。
ユーザーは、体型、柄、目、鼻・ 口(セット)、耳、尻尾の6つをイラストから選択することができ、最初は約100万通りが作成できる想定だったのですが、どんどんイラストが増えていったため最終的には2億通りを超えてしまいました。
柄は色の濃淡を、目は色をそれぞれ選べるようにしたいとのことだったので、それも加味しながらデータ構造を考えました。
要件
そうしてまとめた要件がこちらです。
SPA(React、Vue、jQuery などどれでも実現可能)
選択肢によってイラストを変更し、選択したデータを蓄積していく(jQuery で実装するなんて考えたくない、、)
商品の個別URLが必要になる可能性(React、Vueどちらでも可能)
イラスト(SVG)から画像を生成
ローカルストレージへのデータの保存と再利用
APIとの連携
コード内にSVGのパスを大量に含むので、コード分割を使いたい
React v16 で追加された Lazy 、Suspense を使えば簡単にコード分割が行えるらしいので、チャレンジとして使ってみることにしました。がその結果、分割された JS のファイル数がなんと200弱に。。
セオリー通りにいけば、今回だと4ページなので4つのファイルにまとめるのが普通だと思うのですが、大量にあるパスを細かく分けようとしたらそうなってしまいました。
技術選定
要件を考慮した結果、フレームワークは React を使用。続いて使用するライブラリを選びます。
下に一覧を書き出しましたが、今回はスマホがメインターゲットだったので react-use や react-device-detect などはそこまで使うことはなかったです。
react-use : hooks の便利関数の寄せ集め
react-device-detect : OS判定など
swr : データ取得のための hooks ライブラリ
axios : データ取得
lodash : 便利関数
ress : CSS Reset
swiper : スライダー(カルーセル)
rc-slider : スライダーバー
hex-to-rgba: 色変換(途中で chroma-js に変更)rgba-to-rgb : 色変換
chroma-js : 色操作
simplebar-react : カスタムスクロールバー
大体はよく使っているものですが、swr は初めて使いました。
「データ取得のための hooks ライブラリ」と書きましたが、next.js を開発している Vercel が開発したものだそうです。
swr は stale-while-revalidate の略で、
ということをやってくれるようです。
便利そうなだと思ったので使ってみることにしました。
使ってみた感想としては、まず React hooks との相性がすごく良いのと、通常の fetch や axios を使って実装すると、読み込み待ちなどを自分で実装しないといけないのが少し面倒なのですが、これを使えば一行書き加えるだけでその手間がなくなるのが便利でした。
今回はやりませんでしたが、データ読み込みの依存関係なども簡単に設定できるようなので、機会があればもっと使ってみようかなと思っています。
もう一つ紹介になりますが、個人的なおすすめのライブラリは lodash です。
ネイティブの関数でもできるかもしれませんが、もっと幅広くかつ強力なチェーンメソッドが lodash には用意されているので、様々な対応が可能です。配列やオブジェクトを扱う時には必須だと思います。あって困ることはありません。
目標
毎回案件に取り組む際に、目標を立てるようにしています。
今回の場合だと大きな目標は React の習熟です。
ちょうど React を使い始めて半年ぐらいで、案件的にもいくつかこなしてきたので、もっと使えるようになればいいなとその目標にしました。
中でも React hooks というのが v16.8 で追加されたのですが、 これを扱えるようになれればと。
まとめ
最後にまとめとして良かった点と困った点を。
良かった点
ネコのイラストが可愛く実装していて楽しい(モチベーション)
React は使いやすい(Typescript との相性など)
ライブラリも豊富で検索するとだいたい見つかる
Typescript との相性を考えると Vue.js よりも圧倒的に React の方が使いやすいと思ったのですが、噂によると Vue.js も 3 になってから改善されているとか。まだ試していないので実際のところはわかりませんが。
jQuery を使っていたときは極力自分でライブラリを作成するようにしていたのですが、React だといくらでもライブラリが転がっているのでそれらを使う方が対応が容易だなと思いました。
困った点
選択肢のイラスト(SVG画像)を書き出すのが大変、、
イラストで使用するためのパスの作成が大変、、
CSS Filter が効かない、、
SVG Filter を使うと生成した画像がジャギる、、
clip-path にパスが複数入っていると画像がジャギる、、
案件が進むほどに各々がネコに詳しくなっていき、こだわりが増える、、
とにかくイラストの選択肢が多いので、そのあたりの作業が非常に地道で大変でした。。。
なんと、それぞれのパスのコードは出し分けする処理の中に人力でコピペしていくという力技。
何かいい方法があれば良かったのですが思いつかず、、、
今後も随時、柄などを追加予定なので、効率化が今後の課題です。。
もう一点困ったのが Safari のバグです。
設計のところで猫の色味の濃淡について少し触れましたが、単色の猫の場合だと透明度をただ変更するだけでいいのですが、三毛猫や錆猫の場合は柄とレイヤー構造の関係で透明にならないように薄くするという処理が必要でした。
それを実現するには CSS Filter で opacity をかければ良かったのですが、なぜか Safari だけうまくいかない。。SVG Filter で実装すると画像の淵がジャギジャギに。これも Safari だけ。
結局どうしたかというと、透明度を変えるのではなくchroma-js+rgba-to-rgb を使って色合成することでなんとか解決しました。
という感じで色々と大変な部分ありましたが、無事にローンチできました。
おかげさまで大盛況の「うちのこメーカー」、全世界からたくさんのアクセスをいただいておりまして、ありがたい限りでございます!是非是非遊んでみてください。
うちのこメーカー
Instagram:https://www.instagram.com/uchinoko_maker/
Twitter:https://twitter.com/uchinokomaker