🐉
Vue3 特定の要素までスクロールして画面に入ると発火する
作成日:
2023/09/22
0
特定の要素までスクロールして画面に入ると発火する
今回は前回の特定の要素の取得方法を使ってスクロールして発火するやつ。
javascriptだと(*引用元すずのん)
let targets = document.querySelectorAll('.js-scroll-fall'); //アニメーションさせたい要素
//スクロールイベント
window.addEventListener('scroll', function () {
var scroll = window.scrollY; //スクロール量を取得
var windowHeight = window.innerHeight; //画面の高さを取得
for (let target of targets) { //ターゲット要素がある分、アニメーション用のクラスをつける処理を繰り返す
var targetPos = target.getBoundingClientRect().top + scroll; //ターゲット要素の位置を取得
if (scroll > targetPos - windowHeight) { //スクロール量 > ターゲット要素の位置
target.classList.add('is-animated'); //is-animatedクラスを加える
}
}
});
jQueryだと(*引用元LOOP NEVER ENDS)
$(function(){
//事前に要素のopacityを0(= 透明度100%)にしておく
$('.item').css('opacity', 0);
//要素が画面に入ったらopacityを1(= 透明度0%・不透明)にして表示する
$('.item').on('inview', function(event, isInView) {
if(isInView) {
$(this).animate({
opacity : 1.0
}, 1000);
}
});
});
上記にはWEB APIのgetBoundingClientRect
が使われているが、分からなかったら調べてほしい。(Vue記事なので)
vue3では特定の要素を取得するref
とonMounted
そして新しくintersectionObserver API
を使う
inntersectionObserverは画面に要素が入っているかをtrue or false
で判断してくれる
Vue3での実装
<p ref="hello" class="ani" :class="{blue}">アニメーション</p>
要素にref
とバインドするクラス:class
を指定する
const hello = ref();//タグにrefと同じ名前の変数をつける
const blue = ref(false);//最初はクラスを付けないのでfalse
// IntersectionObserver
const ISOServer = new IntersectionObserver(function(e){//1.eに返り値でターゲットが入る
e.forEach(function(endpoint){// endpointには`IntersectionObserverEntry`が引き渡される
console.log(endpoint.isIntersecting);//true or false
if(endpoint.isIntersecting == false){
//要素が入ってない時の処理
}else{
//要素が入った時の処理
blue.value = true; //変数をバインドしたクラスをtrueに変更
}
})
},{//2.第二引数にoptionを引き取れる
rootMargin: `0px 0px -300px 0px`//画面下から300pxのところで発火
})
onMounted(function(){
const testDom = hellow.value;
// IntersectionObserverに要素を渡す
ISOServer.observe(testDom);//渡した物が1へと渡る
});
opstionを第二に入れる方法は上記の直接書く方法と
let option:{rootMargin:string} = {
rootMargin: `0px 0px -300px 0px`
}
const options = ref(option);
// IntersectionObserver
const ISOServer = new IntersectionObserver(function(e){//1.eに返り値でターゲットが入る
e.forEach(function(endpoint){// endpointには`IntersectionObserverEntry`が引き渡される
console.log(endpoint.isIntersecting);//true or false
if(endpoint.isIntersecting == false){
//要素が入ってない時の処理
}else{
//要素が入った時の処理
blue.value = true; //変数をバインドしたクラスをtrueに変更
}
})
},options.value)//ここに第2引数として渡す
上記の方法がある。メンテのしやすさで言うとobjに設定した後者が良さそうだけど・・・。
完成系
<template>
<p ref="hello" class="ani" :class="{blue}">アニメーション</p>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
const hello = ref();
const blue = ref(false);
const ISOServer = new IntersectionObserver(function(e){
e.forEach(function(endpoint){
if(endpoint.isIntersecting == false){
//要素が入ってない時の処理
}else{
//要素が入った時の処理
blue.value = true;
}
})
},{
rootMargin: `0px 0px -300px 0px`
})
onMounted(function(){
const testDom = hellow.value;
ISOServer.observe(testDom);
});
</script>
<style lang="scss" scoped>
.blue {
animation: changeColor 5s ease-in forwards;
}
@keyframes changeColor {
from {
color: black;
}
to {
color: blue;
}
}
</style>
intersectionObserverについてもっと理解したい時はこちらで(*引用元[ふ]さん)
感想
他にも修正や編集できる所がある気がしている(やり方はいくつもありそう)
次はフェードイン・アウトをやる予定
フロントエンドエンジニアを頑張って勉強中。
最近はVueやNuxtを勉強中です。
コミュニティなどあれば参加してみたいと思ってます。
どうぞ、生暖かい目で見ていただけると幸いです。