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
70
ぬるぬる動くSwipeCard UIをClojureScriptで実装してみた
BOXP
May 30, 2019
Tweet
Share
More Decks by BOXP
See All by BOXP
Cluster Creator Kitに入門してみた
boxp
0
80
LookingGlassPortraitあそんでみた
boxp
0
54
肉体を捨てた話
boxp
0
77
A story about releasing a online pairing service for avatars living in virtual worlds
boxp
1
330
VketのブースにVRoid製うちのこを召喚してみた
boxp
0
200
Hito Hub 2.0
boxp
0
1.3k
バーチャルマーケット3に ポスターを貼ってみた件
boxp
0
1.5k
趣味でGOOGLE KUBERNETES ENGINEを試したら 財布が薄くなったはなし
boxp
0
1.4k
趣味でつくる アバター×アバター マッチングアプリをリリースした話
boxp
0
120
Other Decks in Programming
See All in Programming
Django Ninja による API 開発効率化とリプレースの実践
kashewnuts
0
930
クラシルを支える技術と組織
rakutek
0
190
monorepo の Go テストをはやくした〜い!~最小の依存解決への道のり~ / faster-testing-of-monorepos
convto
2
390
CSC509 Lecture 01
javiergs
PRO
1
430
2分台で1500examples完走!爆速CIを支える環境構築術 - Kaigi on Rails 2025
falcon8823
3
3.1k
いま中途半端なSwift 6対応をするより、Default ActorやApproachable Concurrencyを有効にしてからでいいんじゃない?
yimajo
2
340
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
490
AIで開発生産性を上げる個人とチームの取り組み
taniigo
0
130
iOS 17で追加されたSubscriptionStoreView を利用して5分でサブスク実装チャレンジ
natmark
0
590
Web技術を最大限活用してRAW画像を現像する / Developing RAW Images on the Web
ssssota
2
1.2k
Web フロントエンドエンジニアに開かれる AI Agent プロダクト開発 - Vercel AI SDK を観察して AI Agent と仲良くなろう! #FEC余熱NIGHT
izumin5210
3
400
Catch Up: Go Style Guide Update
andpad
0
170
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
29
2.6k
Raft: Consensus for Rubyists
vanstee
139
7.1k
Gamification - CAS2011
davidbonilla
81
5.5k
RailsConf 2023
tenderlove
30
1.2k
Fireside Chat
paigeccino
40
3.7k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Done Done
chrislema
185
16k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
20k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
4 Signs Your Business is Dying
shpigford
185
22k
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!