Webサイトで要素がスクロールに合わせて自然に表示される「スクロールアニメーション」は、ユーザー体験を向上させる効果があります。Vue.jsでは、Intersection Observer APIとVueのトランジション機能を組み合わせることで、軽量かつ高パフォーマンスな実装が可能です。本記事では、その具体的な方法を紹介します。
Intersection Observerで要素の表示タイミングを検知
Intersection Observer APIを使うことで、スクロールイベントを手動で監視せずに、要素がビューポートに入った瞬間を効率的に検出できます。
// composables/useIntersection.js
import { ref, onMounted, onUnmounted } from 'vue';
export function useIntersection(callback, options = {}) {
const target = ref(null);
let observer = null;
onMounted(() => {
observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
callback(entry);
}
});
}, options);
if (target.value) {
observer.observe(target.value);
}
});
onUnmounted(() => {
if (observer && target.value) {
observer.unobserve(target.value);
}
});
return target;
}
トランジションを利用したアニメーション効果
Vueの<transition>
コンポーネントを使うことで、要素が表示される際にフェードインやスライドインのアニメーションを付与できます。
<template>
<transition name="fade-up">
<div v-if="isVisible" ref="elementRef" class="box">
スクロールで表示されるコンテンツ
</div>
</transition>
</template>
<script setup>
import { ref } from 'vue';
import { useIntersection } from './composables/useIntersection';
const isVisible = ref(false);
const elementRef = useIntersection(() => {
isVisible.value = true;
});
</script>
<style>
.fade-up-enter-active {
transition: all 0.6s ease-out;
}
.fade-up-enter-from {
opacity: 0;
transform: translateY(20px);
}
.fade-up-enter-to {
opacity: 1;
transform: translateY(0);
}
.box {
background: #f2f2f2;
padding: 20px;
margin: 40px 0;
}
</style>
動作の流れ
上記のコードでは、コンポーネントがマウントされるとIntersection Observerが要素を監視します。要素が画面内に入るとコールバックが呼ばれ、isVisible
がtrue
に変わって要素が描画されます。その描画時にVueのトランジションが適用され、フェードアップのアニメーションが実行されます。
パフォーマンス面のメリット
Intersection ObserverはネイティブAPIのため、高パフォーマンスでスクロール位置を監視できます。従来のscroll
イベントのように頻繁なイベント発火を気にする必要がなく、モバイル環境でも軽快に動作します。
まとめ
Vue.jsでスクロールアニメーションを実装する際は、Intersection Observerと<transition>
を組み合わせることで、シンプルかつ高パフォーマンスな表現が可能です。画像やテキスト、カードレイアウトなど様々な要素に応用できるので、ぜひUI改善に取り入れてみてください。