0
0

More than 1 year has passed since last update.

VanillaJSでイージング付きのSmoothScrollを実装する

Last updated at Posted at 2022-08-30

TL;DR

scroll-behavior便利ですね。

・・・とかいいつつ、うまくスムーススクロールが動かなかった(おそらく自分の実装が悪い気もする)ので、
バニラでスムーススクロールを実装しました。

よくあるサンプル、動きが直線的で気持ち悪いですよね。
なんでイージングつけました。

ソースコード

適当にコピペしてimportしたら使えるかと思います。

ソース説明

メインのソースはよくあるSmoothScrollと一緒です。


// clickイベント取得して、aタグのハッシュを取得する用。
export const smoothScroll = (event) => {
  event.preventDefault()
  smoothScrollWithHash(event?.target?.hash ?? "html")
}

// 直で”#id”と指定する用
export const smoothScrollWithHash = (hash) => {
  const el = document.querySelectorAll(hash)[0]

  // 目的地と開始地の座標取得
  const targetPosition = el.offsetTop
  const startPosition = document.scrollingElement.scrollTop
  let currentPosition = startPosition

  // 上スクロールか下スクロールか
  const goDown = currentPosition < targetPosition

  const interval = setInterval(function() {
    // Sin関数でイージングをつけた移動量を計算する
    const mp = movingPosition(startPosition, targetPosition, currentPosition)
    // mpの返り値が0だと無限ループになるので、最低限移動する値を加減算する
    currentPosition += goDown ? mp + 5 : - mp - 5

    if (goDown && currentPosition > targetPosition
      || !goDown && currentPosition < targetPosition) {
      clearInterval(interval);
      document.scrollingElement.scrollTop = targetPosition
    }
    document.scrollingElement.scrollTop = currentPosition
  }, 10);
}

今回イージングを実現するために、Sin関数で移動量を計算しています。

Math.sin(Math.PI)の時は移動速度が上がって下がる。
Math.sin(Math.PI/2)の時は移動速度がギュインと上がります。

const movingPosition = (start, target, current) => {
  const sin = Math.sin((current - target) / (start - target) * Math.PI)
  return sin * 50
}

(current - target) / (start - target)は開始時は1で、
currentがtargetに近づくにつれ0に近づきます。

ですので、画像x軸のπの位置から0の位置まで移動量を変化させながらスクロールされるイメージです。

22364374.png

まとめ

はとくにないよ。

0
0
2

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
0
0