デザイナーの使うツールとエンジニアの実装は往々にして距離は遠く、イニシャルの開発の時はある程度足並み揃えられるものの、開発が進み実装とデザインデータが乖離していくなんてことはよくある話です。
その乖離をなるべく解消できないかと思っていたところにFramerXという良いツールが出てきたので、今回はデザイナーとエンジニアの開発フローとも照らし合わせながらそのツールの使い方についてまとめてみようと思います。
この記事のサンプルはこちら
https://github.com/tyshgc/framerx-mobx-hooks-example
FramerX はFramer社が開発しているデザインツールです。
SkecthやFigma、Adobe XDのようなツールの様な基本はデザイナーが使うGUIツールです。
オフィシャルサイトには以下のように書かれています。
Bring your creative ideas to life with Framer X, the best tool for interactive design. Create responsive layouts, design realistic prototypes, and bring everything closer to production—all in one place.
説明ではインタラクティブに最適なデザイン制作のためのツールといったところで、グラフィックだけのDesign ComponentやReactコンポーネントで書けるCode Componentでデザインを構成していかかとが出来るツールです。
詳しいツールの使い方やpros/consは色々なところで言及されているので端折りますが、このFramerXを使うと実際に開発で使われるコードやAPIなどのデータを活用することが容易くなります。
今回は大きく以下の内容で、実際に開発で利用する場合の一例を軽くまとめてみようと思います。
FramerXはまずプロジェクトを作るところから始まります。
普通にプロジェクトを作成すると{プロジェクト名}.framerx
というバイナリーファイルが生成されます。
この詳細な中身は以下のようにライブラリフォルダ下にあるキャッシュフォルダに置かれます。
中身を見ると package.json
や tsconfig.json
などパッケージやTypeScriptのコンフィグが用意されています。
また /code
フォルダには自作したCode Componentが置かれ、/design
には document.json
が置かれ、デザインデータをjsonファイルで管理していることがわかります。
つまりこれらは全てgitで管理可能ですので開発のリポジトリにデザインデータを載せることが可能になります。
そのままプロジェクトを作成してもライブラリフォルダ下に自動で配置されてしまうため保存先を変更しなくてはなりません。
この説明があまりツールの目立ったところにないのはちょっと如何かと思うんですが… FrameXのサイトを見ていくと以下の様に書いてありました。
To create a folder-backed project, create a new Framer X project or open an existing project. With your project open:
You can open a .framerfx folder in Finder by right-clicking and selecting "Show Package Contents".
既存プロジェクトでも新規プロジェクトでも、optionキーを押したままファイル をクリックするとメニューにSave As
が表示されます。
さらにoptionキーを押したままSave Asを選択する と以下のように File Formart
が選択できるようになり Framer X(Folder)
を選択すると {プロジェクト名}.framerfx
というフォルダプロジェクトに変更できます。
このフォルダを開発中のリポジトリフォルダ以下に置けばgitで差分管理することが可能になります。
例として、FramerX側で画面やButtonをDesign Componentとして作ると…
差分として以下のファイルたちが変更されました。
初回のコミットなので諸々全部含まれていますが、document.json
でプロジェクトファイルの状態を保存しこれを基本的に自動でアップデートしてきます。
さきほどの差分に canvas.tsx
というものがありました。このファイルはDesign Componentをexportできるように自動で定義してくれるものです。
例としてButtonコンポーネントにフラグを渡して角丸の有無をコントロールできるようにしてみましょう。
Design ComponentのButton
コンポーネント をCodeButton
コンポーネントに差し替えてみるとこうなります。
Design Componentではテキストと画像くらいしかpropsとして渡せませんが、Code Componentの場合は addPropertyControls()
で色々なものを渡すことが可能になります。
このようにReact.jsをある程度理解し、TypeScriptを書くことができることが前提ではありますが… それさえできれば如何様にでもできるのがFramerXの素晴らしいところです。
FramerXはReactで開発する際に実装できることはほとんどできるといって過言ではないです。
これまではいくらデザインシステムを頑張って粒度の分解を行ってもデザインデータと実装されたものは真に混ざることはありませんでした。
開発はより多くの共通言語を持つ事でスピードも品質も高まります。その可能性を秘めているものの一つがFramerXだと思います。
デザイナーとエンジニアの協業でFramerXを良さそうということはわかってきました。しかし問題はFramerXでコード扱う場合に 「デザイナーがコードをかけない」 ことがネックになります。
FramerXはちょっと複雑なことをやろうとするとCode Componentを書かなければなりませんし、Code Componentをエンジニアが書くというのはそれはそれで無駄です(開発には必要ないものですから)。
そこで自分が考える方法としては2つ。
1番は今がんばれるくらいなら前からがんばってたのでは?という話になりそうなので置いておいて…。
2番もCode Componentをエンジニアが書くんでしょ?って思うかもしれませんが、Code ComponentはFramerXのためのContainerコンポーネントとして考えて、詳細なコンポーネントはFramerXを見ながら実装してしまえば良いと思います。
ちなみにVueやFlutter、Nativeアプリの開発の場合はそもそもFramerXの利点が生かせないので他のツールでいいんじゃないでしょうか。
Framer社が頑張るか早めにOSS化すればワンチャン他のフレームワークや言語で同じことができるようになるかもしれませんが今の所予定はなさそうです。
というわけで、エンジニアとしてさきほどのCodeButtonコンポーネントを開発用に実装してみます。
実装といってもCodeComponentでほぼ出来上がっていますが、細かいスタイルなどはDesign Componentを活用していたので残りの部分を実装して調整する感じです。
StyleとDOM要素の名付けをしやすいように @emotion/styled
を使っていますが、基本的にはCodeButton.tsxから実装しています。
次に、CodeButton.tsxにButton.tsxをimportします。
尚、Design ComponentのStyle情報はFramerXの右のコンパネにある Layout | Handoff
のタブで Handoff を選ぶとCSSをコピーできます。
※Styleは多少調整が必要な場合もあります🙇
以下は先ほどのButton.tsxを開発中のReactに加えたコードです。
FramerXとReact Appをそれぞれプレビューしてみるとこんな感じになります。
表示や演出によりユーザに適切な情報をフィードバックするところもUIデザインの重要な要素です。マイクロインタラクションとしてのアニメーションをデザインができる方が良いのですが、FramerXはこちらもページ遷移以外はコードで表現するか、FramerXのパッケージを追加してなんとかするしかありません。
ただ、幸いにもFramerMotionというReactアニメーションライブラリがあります(FramerXにも内包されている)。これで実装していくとアニメーションもデザインデータと本実装との共有ができて良いと思います。
https://www.framer.com/motion/
ちなみにライブラリは利用できるので、Lottie や react-spring など他のアニメーションライブラリを活用しても問題ありません。
アイコンなどのアニメーションはLottie + Haiku の方が圧倒的に良いです。
では、FramerMotionでタップ時のアニメーションをいれてみます。
簡単すぎる。。
motion
のAPIなど詳しくはこちら https://www.framer.com/api/motion/
次のコードは実際に実装してみたButtonコンポーネント。
プレビューするとこんな感じです。
左がReactとしてローカルサーバ立ち上げて実行した様子。右がFramerXのプレビューモードです。同じですね。
ここまでに説明したようにDesign Componentを作成し画面を模したFrameに配置するところまでがデザイナー担当。
その差分をpullしてきて、そのままDesign Componentのpropsやstyleを参照し、React Componentを実装しCode Componentとしてラップする。
最後はFramerXのDesign ComponentのインスタンスをCode Componentに差し替える流れです。これならデザイナーがコードをかけなくてもエンジニアもそれほど負荷にならずに進められると思います。
ところで、アプリケーションを開発するとGUIなどの状態(State)を扱わなければなりません。
またプロトタイピングで状態を扱えるようになるとわざわざエラー有無の画面を作ったりなどの手間も減ります、それらを作ることをうっかり忘れるなんてことも減ります。
この状態のデータを扱い安くするためにも集約するStoreが欲しくなります。
FramerXで状態をStoreを持たせるには Framerが用意している Data()
にオブジェクトを渡すことで可能になります。
DataはOverride定義したイベントをCode ComponentやDesign ComponentにFramerXの右コンパネのOverrideから渡すことでpropsを上書きして渡すことができます。
本記事では本実装のコードを共用できることを生かし、State Manager(状態管理)もFramerX上で利用できるようにします。これでいちいちFramerX用にStoreを実装しなくても良くなります。
サンプルではMobX + React Hooksを採用してContext ProviderなしでStoreの参照とActionを渡しています。
MobXを採用した理由は、当初Typelessで試みましたがContext Provider周りでうまくいかず、かといってReduxは本記事にしては冗長的になるのでUnstatedと悩んでMobXにしました。あと個人的にMobX好きなのも理由(FlutterやReactNativeでの採用実績も海外では多いため)。
まずはMobXの準備をします。MobXはStateインスタンスを用意すればどこからでもimportで参照できます。これは良い点・悪い点がありますがその辺は長くなるので端折ります。
1づつカウントアップしていくだけの単純なやつ。
このあとContext周りをHooksにまとめます。
参考: MobX と hooks でプレーンな書き味の React コンポーネントを書く
諸々インスタンス化します。
このindex.tsをimportすればインスタンス化されたCounterStoreの持つ @action countUp()
を叩けるようになりますが、Storeを直接叩きにいくと後々複数のStoreを一つのイベントで扱う際に重複されるコードがでてくるのでActions Classを作ってそこにまとめます。
ここまできたら後はHoFなContainer Componentを作ってStoreのStateを渡せるようにします。
ここまでがReact App側の実装です。このStoreやActionをFramerX側でも使えるようにします。
さきほどまでFramerX上ではButtonしかつくっていませんのでカウンターの数字を表示するコンポーネント NumberView
をつくります。
このままではStoreのデータをもってこれないのでCode Componentを作成します。ついでにNumberViewとButtonを一緒したCode Componentにします。
const countString =
${count};
で文字列にしています。SNumberView
でstyleに position: relative;
をいれているのはDesign Componentはそのままだと absolute
になっているため明示的に変更しています(absoluteだとレイアウトがくずれる)。あとは CodeDomainCounter
コンポーネントを画面のFrameに配置して完了です。
ただカウントアップしているだけなのでそもそもState Managerなんて必要性ないですが…。
Hooksでロジックや状態を切り分けておいて、必要なプレゼンテーションに組み込むことでReact上でもFramerX上でも同じロジックや状態を使うことができます。
FramerXをうまく使うことによってデザインデータはイニシャル開発でもリリース後でも最終アウトプットである実装されたコードに寄り添うことができます。
またほぼ実際と同じインタラクションをプロトタイピングとして活用できるので ユーザによるレビューもこれまでのプロトタイピングツールのそれより遥かに精度の高いものに できます。
少なくともReact.js / React Nativeでの開発の場合はFramerXを使わない手はないと思います。