3
0

More than 3 years have passed since last update.

指定したHTML要素にスクロール

Last updated at Posted at 2020-07-01

JavaScript で指定した HTML 要素にスクロールさせます。自動的にフォーカスを移動させることなどを想定しています。

よくある処理だと思いますが、そのものズバリのサンプルが見当たらなかったので、実装を残しておきます。

See the Pen ensureVisible by 七誌 (@7shi) on CodePen.

このサンプルでは [Start] をクリックすると、0.5 秒ごとに選択位置を移動して、それに追随してスクロールします。

実装

.NET Framework の ListView には EnsureVisible というメソッドがあり、指定した項目が画面外にある場合はスクロールして表示することができます。

それを真似て HTML でも ensureVisible を実装しました。マージンと HTMLElement を指定します。HTMLElement は複数指定できます。

function ensureVisible(margin, ...elems) {
  let rs = elems.map((elem) => elem.getBoundingClientRect());
  let tp = Math.min(...rs.map((r) => r.top   )) - margin;
  let bt = Math.max(...rs.map((r) => r.bottom)) + margin;
  if (tp < 0) {
    let top = pageYOffset + tp;
    scroll({ top, behavior: "smooth" });
  } else if (bt > innerHeight) {
    let top = pageYOffset + bt - innerHeight;
    scroll({ top, behavior: "smooth" });
  }
}

位置の指定

getBoundingClientRect は画面上の位置(相対座標)を取得します。スクロールすると変化します。

scroll はドキュメント上の位置(絶対座標)を指定します。そのため表示の開始位置 pageYOffset を足すことで補正します。今回の実装ではスムーズスクロールを利用しています。

    scroll({ top: top, behavior: "smooth" });

スクロール量を指定する scrollBy もありますが、スムーズスクロールをサポートしていないため利用しませんでした。

サンプル

サンプルでは 0.5 秒のウェイトを Promise で処理しています。

function wait(timeout) {
  return new Promise((resolve, reject) => setTimeout(resolve, timeout));
}

start.onclick = async () => {
  for (let td of Array.from(table.getElementsByTagName("td"))) {
    ensureVisible(20, td);
    td.classList.add("selected");
    await wait(500);
    td.classList.remove("selected");
  }
  ensureVisible(20, moveToTop);
};

詳細は以下の記事を参照してください。

経緯

音声合成の読み上げ位置を追うために実装しました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0