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
66
LookingGlassPortraitあそんでみた
boxp
0
38
肉体を捨てた話
boxp
0
65
A story about releasing a online pairing service for avatars living in virtual worlds
boxp
1
290
VketのブースにVRoid製うちのこを召喚してみた
boxp
0
180
Hito Hub 2.0
boxp
0
1.1k
バーチャルマーケット3に ポスターを貼ってみた件
boxp
0
1.4k
趣味でGOOGLE KUBERNETES ENGINEを試したら 財布が薄くなったはなし
boxp
0
1.3k
趣味でつくる アバター×アバター マッチングアプリをリリースした話
boxp
0
110
Other Decks in Programming
See All in Programming
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
140
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
0
160
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
110
create_tableをしただけなのに〜囚われのuuid編〜
daisukeshinoku
0
260
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
190
StarlingMonkeyを触ってみた話 - 2024冬
syumai
3
270
テスト自動化失敗から再挑戦しチームにオーナーシップを委譲した話/STAC2024 macho
ma_cho29
1
1.3k
[JAWS-UG横浜 #76] イケてるアップデートを宇宙いち早く紹介するよ!
maroon1st
0
460
クリエイティブコーディングとRuby学習 / Creative Coding and Learning Ruby
chobishiba
0
3.9k
Haze - Real time background blurring
chrisbanes
1
510
103 Early Hints
sugi_0000
1
230
rails stats で紐解く ANDPAD のイマを支える技術たち
andpad
1
290
Featured
See All Featured
Become a Pro
speakerdeck
PRO
26
5k
Gamification - CAS2011
davidbonilla
80
5.1k
Designing for Performance
lara
604
68k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
26
1.9k
Designing for humans not robots
tammielis
250
25k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
Embracing the Ebb and Flow
colly
84
4.5k
Rails Girls Zürich Keynote
gr2m
94
13k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.3k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
17
2.3k
How to Ace a Technical Interview
jacobian
276
23k
Building Better People: How to give real-time feedback that sticks.
wjessup
365
19k
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!