useScroll

useScroll

リアクティブなスクロール位置と状態。

使用法

<script setup lang="ts">
import { useScroll } from '@vueuse/core'
import { useTemplateRef } from 'vue'

const el = useTemplateRef<HTMLElement>('el')
const { x, y, isScrolling, arrivedState, directions } = useScroll(el)
</script>

<template>
  <div ref="el" />
</template>

オフセットを使用する

import { useScroll } from '@vueuse/core'
// ---cut---
const { x, y, isScrolling, arrivedState, directions } = useScroll(el, {
  offset: { top: 30, bottom: 30, right: 30, left: 30 },
})

スクロール位置の設定

要素をその位置にスクロールさせるために xy の値を設定します。

<script setup lang="ts">
import { useScroll } from '@vueuse/core'
import { useTemplateRef } from 'vue'

const el = useTemplateRef<HTMLElement>('el')
const { x, y } = useScroll(el)
</script>

<template>
  <div ref="el" />
  <button @click="x += 10">
    右に10pxスクロール
  </button>
  <button @click="y += 10">
    下に10pxスクロール
  </button>
</template>

スムーズスクロール

スムーズスクロールを有効にするには behavior: smooth を設定します。behavior オプションのデフォルトは auto で、スムーズスクロールは行われません。詳細は window.scrollTo()behavior オプションを参照してください。

import { useScroll } from '@vueuse/core'
import { useTemplateRef } from 'vue'

const el = useTemplateRef<HTMLElement>('el')
const { x, y } = useScroll(el, { behavior: 'smooth' })

// または `ref` として:
const smooth = ref(false)
const behavior = computed(() => smooth.value ? 'smooth' : 'auto')
const { x, y } = useScroll(el, { behavior })

スクロール状態の再計算

measure() メソッドを呼び出すことで、スクロール位置と arrivedState を任意のタイミングで手動で更新できます。

これは、例えば動的なコンテンツの変更後や、スクロールイベント外でスクロール状態を再計算したい場合に便利です。

import { useScroll } from '@vueuse/core'
import { nextTick, onMounted, useTemplateRef, watch } from 'vue'

const el = useTemplateRef<HTMLElement>('el')
const reactiveValue = shallowRef(false)

const { measure } = useScroll(el)

// ウォッチャー内で
watch(reactiveValue, () => {
  measure()
})

// または任意の関数内で
function updateScrollState() {
  // ...何らかのロジック
  nextTick(() => {
    measure()
  })
}

[!NOTE] measure()nextTick() 内で呼び出すことを推奨します。これは、DOM が最初に更新されることを保証するためです。 スクロール状態は自動的に onMount で初期化されます。 動的な変更後に状態を再計算したい場合のみ、手動で measure() を呼び出す必要があります。

ディレクティブの使用法

<script setup lang="ts">
import type { UseScrollReturn } from '@vueuse/core'
import { vScroll } from '@vueuse/components'

const data = ref([1, 2, 3, 4, 5, 6])

function onScroll(state: UseScrollReturn) {
  console.log(state) // {x, y, isScrolling, arrivedState, directions}
}
</script>

<template>
  <div v-scroll="onScroll">
    <div v-for="item in data" :key="item">
      {{ item }}
    </div>
  </div>

  <!-- オプション付き -->
  <div v-scroll="[onScroll, { throttle: 10 }]">
    <div v-for="item in data" :key="item">
      {{ item }}
    </div>
  </div>
</template>