Slide 1

Slide 1 text

Bengo4.com, Inc. Spinner の軸ズレ現象を調べたら レンダリングの深淵に飲まれた 2025.12.23 山下慧

Slide 2

Slide 2 text

Bengo4.com, Inc. 自己紹介 山下慧(Yamashita Satoshi) 弁護士ドットコム株式会社 開発本部 クラウドサインProduct Engineering部 ・趣味 ウォーキング・ランニング ・Xアカウント @kirehashi_3 2

Slide 3

Slide 3 text

Bengo4.com, Inc. LTの登壇を決めたとき ちょうど不思議現象に遭遇 … 3

Slide 4

Slide 4 text

Bengo4.com, Inc. これはよくある Spinnerの実装です 4 borderを設定し… border-radiusでborderを円形にし… animationで回転させる

Slide 5

Slide 5 text

Bengo4.com, Inc. ズーム倍率を変えて動かしてみると … ズーム倍率100% 5 ズーム倍率110% なにか違和感を感じませんか?

Slide 6

Slide 6 text

Bengo4.com, Inc. 色を同じにして枠線を付けてみる ズーム倍率100% 6 ズーム倍率110% →右側(ズーム倍率110%)の回転軸がズレて回っている!

Slide 7

Slide 7 text

Bengo4.com, Inc. ブラウザのズーム倍率が 変わるだけで回転軸が ズレてしまう … 7

Slide 8

Slide 8 text

Bengo4.com, Inc. 面白いネタになるのでは? 8

Slide 9

Slide 9 text

Bengo4.com, Inc. 結論から言うと 「これっぽい!」有力な仮説は立ちましたが 「これで間違いない!」と言い切れる 検証はできせんでした … 9

Slide 10

Slide 10 text

Bengo4.com, Inc. 今回はこの軸ズレの原因を調査した過程と それによって得た知識を紹介していきます 10

Slide 11

Slide 11 text

検証 ブラウザズームは直接の原因か? 11

Slide 12

Slide 12 text

Bengo4.com, Inc. ブラウザズームが軸ズレに直接関係するかを検証 →ブラウザズームは軸ズレに関係がない! 12 ブラウザズーム有 ブラウザズーム無 width, height 25px 27.5px ブラウザズーム 110% 100% 描画される際のサイズ 27.5px 27.5px 軸ズレ 発生 発生

Slide 13

Slide 13 text

アンチエイリアスとは 13

Slide 14

Slide 14 text

Bengo4.com, Inc. アンチエイリアスとは ベクタ情報をディスプレイ上のピクセル単位の情報に変換(ラスタライズ)する際に そのままだとカクカクした形になってしまう そうならないよう線が横切るピクセルを中間色にして滑らかに見せる機能 14 ラスタ画像 ベクタ画像 Paul Lewis「アンチエイリアス入門ガイド」( https://web.dev/articles/antialiasing-101?hl=ja) より引用・加工 / CC BY 4.0

Slide 15

Slide 15 text

ピクセルパイプラインとは 15

Slide 16

Slide 16 text

Bengo4.com, Inc. ピクセルパイプラインとは ブラウザが描画の命令を画面上のピクセルに変換して描画するまでの一連の流れ 16 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja) / CC BY 4.0

Slide 17

Slide 17 text

Bengo4.com, Inc. ピクセルパイプライン: Javascript 17 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 JavascriptによるDOM要素の追加などを計算

Slide 18

Slide 18 text

Bengo4.com, Inc. ピクセルパイプライン: Style 18 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 CSSがどのHTML要素に適用されるかを判定

Slide 19

Slide 19 text

Bengo4.com, Inc. ピクセルパイプライン: Layout 19 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 各HTML要素がスクリーンのどこを占有するかを計算する

Slide 20

Slide 20 text

Bengo4.com, Inc. ピクセルパイプライン: Paint 20 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 ピクセルを複数のレイヤ(後述)に分けて塗りつぶす

Slide 21

Slide 21 text

Bengo4.com, Inc. ピクセルパイプライン: Composite 21 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 複数のレイヤ(後述)をページ全体に合成して描画

Slide 22

Slide 22 text

Bengo4.com, Inc. レイヤとは 画面を構成する描画要素の「層」 レイヤはブラウザが個別に管理し Compositeで一つの画面に合成 →スクロールやAnimationなどによる再レンダリングを最小限に抑えて効率化 22 参考:「Key data structures in RenderingNG」(https://developer.chrome.com/docs/chromium/renderingng-data-structures)

Slide 23

Slide 23 text

Bengo4.com, Inc. レイヤの確認方法 Chromeなどの開発者ツールから開いているページのレイヤ構造は簡単に確認できる 23

Slide 24

Slide 24 text

Bengo4.com, Inc. ピクセルパイプラインのスキップ tansform, opacityのanimationなどLayout, Paintが不要な場合は、 直接Compositeにスキップする 24 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 処理を削減することでパフォーマンスの向上につながる

Slide 25

Slide 25 text

仮説 Compositeフェーズに原因がある? 25

Slide 26

Slide 26 text

Bengo4.com, Inc. なぜCompositeフェーズを疑うのか? 26 translateのAnimationでは基本的にPaintフェーズをスキップする Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 一度ラスタライズした画像を Compositeフェーズで使い回すことで軸ズレの原因になって いるのではないか?

Slide 27

Slide 27 text

検証 Layout, Paintフェーズの強制で 軸ズレが直るか 27

Slide 28

Slide 28 text

Bengo4.com, Inc. 検証:Layout, Paintフェーズの強制で軸ズレが直るか Loadingコンポーネントにbackgroundを指定し… 目視でわからない範囲で動かす Animationを追加 →毎フレームのPaint(ラスタライズ)の実行を強制 28

Slide 29

Slide 29 text

Bengo4.com, Inc. 検証:Layout, Paintフェーズの強制で軸ズレが直るか 開発者ツールで実際にPaintがスキップされなくなっていることを確認 29 通常のLoading Paintを強制したLoading Paintフェーズの実行数が 増加するようになっている

Slide 30

Slide 30 text

Bengo4.com, Inc. 検証:Layout, Paintフェーズの強制で軸ズレが直るか →軸ズレは直らなかった 原因はやはりCompositeフェーズにある! 30 通常のLoading Paintを強制したLoading

Slide 31

Slide 31 text

Compositeフェーズ における図形の変形 31

Slide 32

Slide 32 text

Bengo4.com, Inc. 【再掲】ピクセルパイプライン: Composite 32 Paul Lewis「レンダリング パフォーマンス」(https://web.dev/articles/rendering-performance?hl=ja)より引用・加工 / CC BY 4.0 複数のレイヤをページ全体に合成して描画

Slide 33

Slide 33 text

Bengo4.com, Inc. 実際に描画される画像 rotateなどの変形の指示 Paintでラスタライズされたレイヤ Compositeフェーズの変形で何が起きているか 33 参考:「Key data structures in RenderingNG」(https://developer.chrome.com/docs/chromium/renderingng-data-structures) rotate(90deg) Compositeフェーズ GPU上で変形

Slide 34

Slide 34 text

Bengo4.com, Inc. Compositeフェーズにおける変形 ● Compositeフェーズにおける回転・拡大などは GPU上で行われる ● このGPU上の変形は小数ピクセルまで考慮して計算される ● 最終的には物理ピクセルに合わせて描画する必要がある ● 変形後の図形に対して改めて 物理ピクセルに合わせて再サンプリング(ラスタライズ)が行われる 34

Slide 35

Slide 35 text

仮説 GPU内の変形と再サンプリング が原因? 35

Slide 36

Slide 36 text

Bengo4.com, Inc. Paintフェーズにおけるラスタライズ 36 ベクタ画像 x: 0px 5.25px 10.5px ラスタ画像 x: 0px 5.25px 10.5px Paintフェーズ でラスタライズ

Slide 37

Slide 37 text

Bengo4.com, Inc. GPUにおける変形 37 回転前 x: 0px 5.25px 10.5px Compositeフェーズで 5.25pxを軸に180度回転 180度回転後 x: 0px 5.25px 10.5px

Slide 38

Slide 38 text

Bengo4.com, Inc. GPUにおける変形 38 180度回転後 x: 0px 5.25px 10.5px 拡大してみると… 回転後の色の境界は物理ピクセルの境界と一致しない! →再度物理ピクセルに合わせて   再サンプリングする必要がある

Slide 39

Slide 39 text

Bengo4.com, Inc. 変形の再サンプリング 39 実際の物理ピクセルに 合うよう再サンプリング 180度回転後 x: 0px 5.25px 10.5px 再サンプリング後 x: 0px 5.25px 10.5px

Slide 40

Slide 40 text

Bengo4.com, Inc. GPUの回転前後の比較 40 Compositeフェーズで 回転・再サンプリング 180度回転前 回転・再サンプリング後 x: 0px 5.25px 10.5px x: 0px 5.25px 10.5px 回転前後で大きく形が変わっている! →これがAnimationのrotateによる軸ズレの原因ではないか?

Slide 41

Slide 41 text

Bengo4.com, Inc. この仮説の検証方法は GPU内部の挙動 であることもあり思いつきませんでした … 41

Slide 42

Slide 42 text

Bengo4.com, Inc. ですが… 仮説が正しいとすると想定される挙動がある 42

Slide 43

Slide 43 text

思考実験と検証 コンポーネントサイズの変更に よるズレの変化 43

Slide 44

Slide 44 text

Bengo4.com, Inc. 仮説が正しければ起きうる挙動は 2つ 1. 小数が0.5px付近でズレが最大になり、 0・1pxに近づくほど小さくなる 2. Retinaディスプレイでは小数が 0.5pxでは逆に軸ズレが起きなくなる 44

Slide 45

Slide 45 text

Bengo4.com, Inc. 挙動1:小数が 0.5px付近でズレが最大になる 45 180度回転前 回転・再サンプリング後 x: 0px 5.25px 10.5px x: 0px 5.25px 10.5px x: 0px 5.05px 10.1px x: 0px 5.05px 10.1px width, height 10.5px width, height 10.1px 5.05pxを 軸に回転 5.25pxを 軸に回転 変形前後のズレが小さい!

Slide 46

Slide 46 text

Bengo4.com, Inc. Retinaディスプレイは通常の2倍程度の解像度を持つディスプレイ 0.5px単位で描画できるので物理ピクセルと色の境界が一致し再サンプリング前後での変化が なくなる 挙動2:Retinaでは0.5pxでの軸ズレが消える 46 0.5px単位で 再サンプリング 180度回転後 x: 0px 5.25px 10.5px 再サンプリング後 x: 0px 5.25px 10.5px 0.5px単位の指定では再サンプリングのズレが起きなくなる

Slide 47

Slide 47 text

Bengo4.com, Inc. 2つの思考実験の検証結果 実際に0.25pxずつLoadingコンポーネントのサイズをずらして目視でずれを確認 47 width, height 通常ディスプレイ Retinaディスプレイ 24px 無 無 24.25px 中 中 24.5px 大 無 24.75px 中 中 25px 無 無 2つの起きうると考えた挙動が実際に再現された!

Slide 48

Slide 48 text

Bengo4.com, Inc. 今回の調査における仮説のまとめ ● 小数単位のコンポーネントはPaintフェーズでラスタライズ される ● rotateのAnimationによる回転はGPU上で小数ピクセルを考慮した回転 が起きる ● 回転後の画像が再度、物理ピクセルに合わせて再サンプリング される →ラスタライズと再サンプリングによる図形の誤差が大きくなることで  軸がズレて回転する 48

Slide 49

Slide 49 text

Bengo4.com, Inc. まとめ ● Loadingコンポーネントが軸ズレする事象の調査を通して ピクセルパイプラインやGPU上での変形などレンダリングの仕組みを紹介した ● 今回の調査でコードから先、実際に画面に描画されるまでもフロントエンド であると再確認できた ● あまり学ぶ機会がなかった方々もブラウザの仕組みに目を向けると 面白い学びがあるかも 49

Slide 50

Slide 50 text

ご清聴 ありがとうございました! 50

Slide 51

Slide 51 text

Bengo4.com, Inc. We are Hiring

Slide 52

Slide 52 text

Bengo4.com,Inc. VISION まだないやり方で、世界を前へ。 Drive a paradigm shift for the better world. MISSION 「プロフェッショナル・テック 」で、次の常識をつくる。 Be the Professional-Tech Company. プロフェッショナルだからできること。専門知とテクノロジーで、社会に貢献する。

Slide 53

Slide 53 text

Bengo4.com, Inc. OUR SERVICE 最新の法改正や実務について分かりやすく解説する 日本最大級の企業法務ポータルサイト 日本最大級の無料法律相談ポータルサイト 税理士に無料で相談・検索できる日本最大級の 税務相談ポータルサイト 時事問題の弁護士解説を中心としたメディア 弁護士事務所、企業法務職向け人材紹介事業 契約の締結から管理までデジタルで完結させる 契約マネジメントプラットフォーム AI基盤技術「 LegalBrain 1.0」を組み込んだ リーガル特化型 AIエージェント