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
89
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
ぬるぬる動くSwipeCard UIをClojureScriptで実装してみた
BOXP
May 30, 2019
More Decks by BOXP
See All by BOXP
Cluster Creator Kitに入門してみた
boxp
0
100
LookingGlassPortraitあそんでみた
boxp
0
79
肉体を捨てた話
boxp
0
92
A story about releasing a online pairing service for avatars living in virtual worlds
boxp
1
380
VketのブースにVRoid製うちのこを召喚してみた
boxp
0
230
Hito Hub 2.0
boxp
0
1.4k
バーチャルマーケット3に ポスターを貼ってみた件
boxp
0
1.7k
趣味でGOOGLE KUBERNETES ENGINEを試したら 財布が薄くなったはなし
boxp
0
1.5k
趣味でつくる アバター×アバター マッチングアプリをリリースした話
boxp
0
150
Other Decks in Programming
See All in Programming
「AI時代、配布するPythonコードをどう守るか: 難読化の実験と判断軸」 #PyconJP2026
pkshadeck
PRO
2
160
이 함수, 실패하면 어떻게 되나요? null부터 Rich Errors까지, Kotlin 에러 처리 15년
haeti2
0
130
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
670
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
130
20260828_品質と開発生産性を両立させる、AI時代のE2Eテストの考え方
magicpod
0
140
GKE アップグレード前に知っておきたい Blue/Green と PDB の関係
stkk
0
140
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
0
360
LL言語やWebフレームワークのPostgreSQL対応 〜DBの機能がユーザーに届くまで〜
kentaroutakeda
0
140
FDEとは、何者なのか?
masapyon1212
0
140
MIZARU@SPAJAM2026 第二回予選
1901drama
0
100
[PyCon KR 2026] More Variants, More Diversity for AI Accelerators
achimnol
0
130
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
1.7k
Featured
See All Featured
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
470
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
470
Everyday Curiosity
cassininazir
0
310
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
990
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
490
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
520
ラッコキーワード サービス紹介資料
rakko
1
4.7M
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!