Scroll + Drag Hybrid UI:スクロールとドラッグをつなぐインタラクション設計

Scroll+Drag Hybrid UIのアイキャッチ画像

Web UIでは、スクロールで動く表現と、ドラッグで操作する表現は別々に扱われることが多いです。

スクロール系の基本は、Scroll Trigger AnimationScroll Progress でも扱っています。

しかし実際のUIでは、

  • スクロールで進む
  • ドラッグでも動かせる
  • 操作後に少し慣性が残る

というように、複数の入力が同じ動きを操作することがあります。

今回は、Scroll + Drag Hybrid UIとして、スクロールとドラッグを同じ位置情報に接続するUIを作ってみます。

1.Scroll + Drag Hybrid UIとは

Scroll + Drag Hybrid UIは、スクロール操作とドラッグ操作を、同じUIの移動量に反映させる考え方です。

たとえば、横に並んだカードを、

  • ページスクロールで少しずつ移動させる
  • マウスやタッチ操作で直接ドラッグする
  • 離したあとに少しだけ慣性で流す

といった形です。

単なるスクロール演出ではなく、ユーザーが直接触っている感覚を加えられるのが特徴です。

2.今回作るもの

今回は、横並びカードのUIを作ります。

スクロールするとカード列が少し動き、さらにカードエリアをドラッグすると、同じカード列を直接動かせるようにします。

ポイントは、scroll用の値とdrag用の値を分けすぎないことです。

let targetX = 0;
let currentX = 0;
let velocity = 0;

このように、UIの位置を管理する値を中心にして、スクロールもドラッグもそこへ反映させます。

3.なぜ共通のstateにするのか

スクロール用の処理、ドラッグ用の処理、描画用の処理を完全に分けてしまうと、UIの状態がずれやすくなります。

たとえば、

  • スクロールでは動いている
  • ドラッグでは別の位置を見ている
  • 離した瞬間に位置が飛ぶ

という問題が起きやすくなります。

そこで今回は、すべての入力を targetX に集めます。

targetX += delta;

スクロールでも、ドラッグでも、最終的には同じ値を動かすだけにします。

4.requestAnimationFrameで描画をまとめる

入力イベントの中で直接 transform を更新し続けると、処理が散らばります。

そこで、描画は requestAnimationFrame にまとめます。

function animate() {
  currentX += (targetX - currentX) * 0.12;
  track.style.transform = `translateX(${currentX}px)`;
  requestAnimationFrame(animate);
}

入力は値を変えるだけ。
描画は毎フレームまとめて行う。

この分離をしておくと、スクロール、ドラッグ、慣性をあとから足しやすくなります。

描画ループの基本は、requestAnimationFrameの使い方 で詳しく扱っています。

5.Drag操作を追加する

ドラッグでは、前回のマウス位置との差分を使います。

const dx = e.clientX - lastX;
targetX += dx;
lastX = e.clientX;

この dx を targetX に足すだけで、カード列を直接動かせます。

また、最後の移動量を velocity に入れておくと、マウスを離したあとに慣性をつけられます。

velocity = dx;

ドラッグ操作そのものの基本は、Drag Interaction UI の記事でも整理しています。

6.慣性を追加する

ドラッグを離したあと、少しだけ動きが残るようにします。

if (!isDragging) {
  targetX += velocity;
  velocity *= 0.92;
}

velocity を少しずつ小さくすることで、自然に止まるような動きになります。

この考え方は、Inertia Scroll / Momentum UIの記事とも近いです。

7.動きすぎを防ぐ

ドラッグUIでは、どこまでも動いてしまうと見た目が崩れます。

そのため、今回は移動範囲を制限します。

targetX = Math.max(minX, Math.min(maxX, targetX));

最小値と最大値を決めて、その範囲から出ないようにします。

8.実験:Scroll vs Drag — Which Feels Better?

下のデモでは、スクロールとドラッグの両方でカード列を動かせます。

スクロールでゆっくり流れる感じと、ドラッグで直接操作する感じの違いを比べてみてください。

9.まとめ

Scroll + Drag Hybrid UIは、スクロールとドラッグを別々の機能として扱うのではなく、同じ状態に接続するUIです。

入力、状態、描画を分ける考え方は、状態管理の記事lerpの記事 ともつながります。

今回のポイントは次の3つです。

  • 入力イベントでは値だけを変える
  • 描画は requestAnimationFrame にまとめる
  • スクロールもドラッグも同じ targetX を動かす

この形にしておくと、あとから慣性や補間、スナップ処理なども追加しやすくなります。

単なるスクロール演出よりも、ユーザーが直接触っている感覚を作れるのが、Hybrid UIの面白いところです。

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA