Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ぬるぬる動くSwipeCard UIをClojureScriptで実装してみた
Search
BOXP
May 30, 2019
Programming
0
66
ぬるぬる動くSwipeCard UIをClojureScriptで実装してみた
BOXP
May 30, 2019
Tweet
Share
More Decks by BOXP
See All by BOXP
Cluster Creator Kitに入門してみた
boxp
0
65
LookingGlassPortraitあそんでみた
boxp
0
37
肉体を捨てた話
boxp
0
63
A story about releasing a online pairing service for avatars living in virtual worlds
boxp
1
280
VketのブースにVRoid製うちのこを召喚してみた
boxp
0
180
Hito Hub 2.0
boxp
0
1.1k
バーチャルマーケット3に ポスターを貼ってみた件
boxp
0
1.4k
趣味でGOOGLE KUBERNETES ENGINEを試したら 財布が薄くなったはなし
boxp
0
1.2k
趣味でつくる アバター×アバター マッチングアプリをリリースした話
boxp
0
110
Other Decks in Programming
See All in Programming
A Journey of Contribution and Collaboration in Open Source
ivargrimstad
0
930
『ドメイン駆動設計をはじめよう』のモデリングアプローチ
masuda220
PRO
8
540
Flutterを言い訳にしない!アプリの使い心地改善テクニック5選🔥
kno3a87
1
190
ActiveSupport::Notifications supporting instrumentation of Rails apps with OpenTelemetry
ymtdzzz
1
230
TypeScriptでライブラリとの依存を限定的にする方法
tutinoko
3
680
色々なIaCツールを実際に触って比較してみる
iriikeita
0
330
Click-free releases & the making of a CLI app
oheyadam
2
120
アジャイルを支えるテストアーキテクチャ設計/Test Architecting for Agile
goyoki
9
3.3k
Generative AI Use Cases JP (略称:GenU)奮闘記
hideg
1
290
Hotwire or React? ~アフタートーク・本編に含めなかった話~ / Hotwire or React? after talk
harunatsujita
1
120
AWS Lambdaから始まった Serverlessの「熱」とキャリアパス / It started with AWS Lambda Serverless “fever” and career path
seike460
PRO
1
260
CSC509 Lecture 13
javiergs
PRO
0
110
Featured
See All Featured
Gamification - CAS2011
davidbonilla
80
5k
Become a Pro
speakerdeck
PRO
25
5k
Optimising Largest Contentful Paint
csswizardry
33
2.9k
Done Done
chrislema
181
16k
The Cost Of JavaScript in 2023
addyosmani
45
6.8k
Rails Girls Zürich Keynote
gr2m
94
13k
How GitHub (no longer) Works
holman
310
140k
Faster Mobile Websites
deanohume
305
30k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
Six Lessons from altMBA
skipperchong
27
3.5k
The Art of Programming - Codeland 2020
erikaheidi
52
13k
Transcript
BOXP ぬるぬる動くSwipeCard UIを ClojureScriptで実装してみた
None
こんな風にぬるぬる動く SwipeCardのつくりかた をまとめます
もくじ Rendering Performance チューニングの基本 SwipeCardにおける Rendering Performance チューニング ClojureScriptによる SwipeCardの実装
Rendering Performance チューニングの 基本
引用元: RAIL モデルでパフォーマンスを計測する https://developers.google.com/web/fundamentals/performance/rail
全部0~16msで 動かないと だめ?
No!
ライフサイクルに 応じて 必要なパフォーマンスを 満たす
Webアプリ 4つのライフ サイクル (RAILモデル) • Response: ユーザーの入力に対する応答中の状態 • Animation: アニメーションの再生やSwipeCardをドラッグしている状態
• Idle: ユーザーの入力を待機している状態 • Load: コンテンツ読み込み中の状態 引用元: RAIL モデルでパフォーマンスを計測する https://developers.google.com/web/fundamentals/performance/rail
各ライフ サイクルに 求められる Performance •これよりも遅いとユーザーは操作と反応のズレを感じる 100ミリ秒以内の応答 •1000ms / 60fps -
ブラウザによるレンダリング時間 = 10ms Animation中は10ミリ秒以内に画面をレンダリングさせる •100ミリ秒以上かかる処理はアイドル時間まで後回し •ユーザー入力へのレスポンスが最優先 アイドル時間を利用したタスク分担 •1000ミリ秒より長いとユーザーの集中力が切れる •このスライドでは触れません 読み込みは1000ミリ秒以内に
まとめ どの程度の パフォーマンスが必要か ライフサイクル毎に分けて考慮する RAILモデル ユーザーの入力には100ミリ秒以内に応答する アニメーション実行中は10ミリ秒以内にレンダリング処理を完了さ せる 時間のかかる処理はアイドル時まで後回し
SwipeCardにおける Rendering Performance チューニング
SwipeCardにおけるライフサイクル 待機中 ドラッグ開始 ドラッグ スワイプ もとの位置に 戻る マッチング オーバーレイ 表示
次のカードを 最前列に Idle Response Animation
SwipeCardにおけるライフサイクル 待機中 ドラッグ開始 ドラッグ スワイプ もとの位置に 戻る マッチング オーバーレイ 表示
次のカードを 最前列に 最重要 Idle Response Animation
カードをドラッグする時 •RAILモデルに当てはめるならAnimation •目標は1frameあたり10msで処理を終えること ユーザーのドラッグ操作に合わせてカードを動かす •CSSのアニメーションだけではほぼ実現不可能 ユーザーの入力に対して変化するアニメーション
1frame/10ms 実現のために 不要な処理を削る
Webページが描 画されるまで • 5つの処理を行うパイプラインとして表現される • Paint処理が一般的に重くなりがち • Layout処理がトリガーされると必ずPaint処理もトリガーされる 引用元: ペイントの複雑さの簡略化とペイントエリアの縮小
https://developers.google.com/web/fundamentals/performance/rendering/simplify-paint-complexity-and-reduce-paint-areas
パイプライン中の 不要な処理を飛ばす Paint・Layout処理を実行させない • Paint処理はまず10msでは終わらない • JavaScript,Style処理もスワイプ処理では削る Composite処理のみで描画できる スタイルを利用する •
transformとopacityのみ 他の要素を再計算させない • Animationさせる要素を別レイヤーへ分ける • will-change: transform; によって別レイヤーが作成可能 Paintが行われていないかChromeDevToolでチェック
その他の最適化 • 不要なLayout処理(強制同期レイアウト)の回避 • スタイルの読み出しと書き込みを1frame内で行うことで発生 する • Reactを利用している場合、スタイルの書き込みは非同期に 行われるため問題にならない •
メインスレッドからUI描画以外の処理を徹底的に排除する • API呼び出しをWebWorkerから行ったり、バッチ化しておい てIdle時に実行させるなど
まとめ • RAILモデルのうち、Animationへの最適化が鍵 になる • 違和感なくアニメーションさせるためには、Paint 処理を避けた実装が必要不可欠 • transform・opacityスタイルを使った実装 •
アニメーションさせる要素を別レイヤーに配置し て余計なLayout処理を避ける • will-change: transform;
ClojureScriptによる SwipeCardの実装
SwipeCardの基本的な仕組み • 二枚の重なり合った要素を使って表現 • 待機状態・Skip・お気に入り登録・初期位置への移動中の 4つのフェーズ • ReagentのLocalStateで状態管理
SwipeCardの LocalState カードの内容 4つのフェーズ タッチポイント座標
ドラッグ そのまま離す お気に入り スキップ 次のカードを表示
ドラッグ そのまま離す お気に入り スキップ 次のカードを表示
SwipeCardのドラッグ処理の実装 • touchmoveイベントハンドラからLocalStateにタッチ ポイントの座標を保持 • 保持された座標からtransformの値を返す関数を 使ってスタイル指定 • Paint処理を避けるためtransformのみで実現
ドラッグ そのまま離す お気に入り スキップ 次のカードを表示
カードを 元の位置へ 戻す実装 • touchendイベント発生時点でのタッチポイントから、元の位置の座標へ のアニメーションを一番上のカードへ差し込む • これでアニメーション中はComposite処理のみで完結できる
ドラッグ そのまま離す お気に入り スキップ 次のカードを表示
スキップ/ お気に入り 処理の実装 • アニメーションは元の位置へ 戻す処理と同様の方法で 実現 • 移動先を元の位置では なく画面外にするだけ
• 戻す時と同様に Paint処理を省略できる
追加のカー ド取得実装 • 表示させるカードが枯渇してきたら、お気に入り/スキップ 処理実行後にWebWorkerを使って追加取得する • 状況によってはアニメーションと取得処理が重なり、fpsが 低下する可能性があるためWebWorkerに処理を追い出す
API Server WebWorker re-frame Reagent Component dispatch subscribe effect request
response dispatch
まとめ • SwipeCardの状態はre-frameではなくReagentの LocalStateで管理している • アニメーションはstyleへkeyframeを直接埋め込 んで実現している • ページング取得はWebWorkerから行った
続きはGitHubへ https://github.com/boxp/vr-match
Thanks!