はじめに
こんにちは。ナオキです!
今回はJavaScriptのみを使用して画像をふわっと表示させる方法を紹介します。ぜひ参考にしてください!
- JavaScript初学者の方
- JavaScriptでスクロール処理を行いたい方
スクロール処理に使用するもの
今回はJavaScriptのIntersectionObserver
を使用してスクロール処理を実装したいと思います!
IntersectionObserver
とはターゲット要素を監視し、その要素が特定の領域内にに入ったり出たりするのを検知し、ターゲット要素と特定の領域が交差している時に関数を実行させることができます!
scroll
イベントでも簡単に実装することは出来ますが、スクロールするたびにイベントが発火してしまうのでパフォーマンス的にあまり良く有りません。それに比べてIntersectionObserver
は非同期で実行されるのでパフォーマンスにも影響しにくいです。
見本とコード説明
Webサイトでよく見るスクロール処理です。HTML
CSS
JavaScript
は以下のようになります!
<body>
<img id="image" src="image/dog.jpg" alt="dog" />
</body>
body {
padding: 100vh 0;
background-color: #d1e9ed;
}
#image {
width: 600px;
margin: 0 auto;
opacity: 0;
transition: 4s;
}
// ① ターゲット要素を取得
const image = document.getElementById("image");
// ③ オプション設定 ※デフォルトで良いなら記述しなくでも大丈夫です!
const options = {
threshold: 0.5,
};
// ④ 要素が表示されたら実行
function showImage(entries) {
if (entries[0].isIntersecting) {
image.style.opacity = 1;
}
}
// ② IntersectionObserverを呼び出す
const observer = new IntersectionObserver(showImage, options);
// ⑤ 実行
observer.observe(image);
HTML
で表示させたい画像を記述します。
CSS
では、body
でスクロール分の余白を取っています。image
で、opacity: 0
を指定し画像を透明にしておき、transition: 4s
を指定しふわっと表示されるようにします。
JavaScript
では、まず①のイベントを発火させたい要素をdocument.getElementById()
にて取得しています。
次に、②でIntersectionObserver()
を呼び出します。第1引数に実行したい関数、第2引数にはオプションの設定を書いていきます。
③でオプションを記述しています。オプションプロパティは以下の3つがあります!
- root
- 監視するベースとなる要素を指定できます。
- 初期値はブラウザの
viewport
になります。
※viewport
とは、表示領域のことです。今現在見ているページの範囲がviewport
になります!
- rootMargin
- 交差を感知するルートからの距離、こちらを利用してイベントを発生させる位置を調整できます。
- 指定の仕方は、
margin
プロパティと同じで("10px 20px 30px 0px")
のように記述します。 - 初期値は
("0px 0px 0px 0px")
になります。
※0px
の場合0
しか記述しないとエラーが出てしまうので、0px
と記述するように注意してください!
- thresholds
- ターゲット要素が見えてから、どの位置でイベントを発火させるか調整できます。
- 0 ~ 1や配列を指定できます。0はターゲットが見え初めた瞬間にイベントが発火し、1はターゲットがすべて見えてる状態でイベントが発火します。
- 初期値は0になります。
オプションは初期値で良ければ何も記述しなくて大丈夫です!
④で要素が表示されたら実行したい関数を記述しています。
関数の第1引数にはIntersectionObserver
のentry
オブジェクトを記述します。entry
オブジェクトはIntersectionObserver
と一緒に使えるもので、以下のプロパティがあります!
- boundingClientRect
- ターゲット要素が画面上にどのように表示されているかの情報を返します。具体的にいうと、その要素が画面上でどの位置にあり、どれだけの幅と高さを持っているかを返します。
- intersectionRatio
- ターゲット要素が現在どの程度見えているかを
0.0 ~ 1.0
の間の値で返します。
- ターゲット要素が現在どの程度見えているかを
- intersectionRect
- ターゲット要素が特定の領域に入っている部分の位置やサイズを返します。
- isIntersecting
- ターゲット要素が特定の領域に入ったら
true
を返し、入っていなければfalse
を返します。
- ターゲット要素が特定の領域に入ったら
- rootBounds
- ターゲット要素がどの領域に対して交差を判定しているかを返します。
- target
- ターゲット要素を返します。
- time
- ターゲット要素と特定の領域が交差状態になった時刻を返します。
今回はisIntersecting
を使用しています!
今回の場合は要素がルートに入ったら透過を無くしたいのでimage.style.opacity = 1
と記述しています。
⑤でobserver.observe(ターゲット要素)
と記述することでターゲット要素の監視が開始されます!
以上がコードの説明になります!
オプションプロパティ、entry
オブジェクトについてもっと詳しく知りたい方はこちらの公式ドキュメントを参照してください!
おまけ
少し工夫をしたら、このようなものも簡単に作れます!
<div id="box" class="box">
<p class="text">スクロールしてね!</p>
</div>
body {
padding: 100vh 0;
background-color: #d1e9ed;
}
.box {
padding: 200px 0;
margin: 0 auto;
position: relative;
}
.box::after {
position: absolute;
content: "";
top: 0;
left: 0;
background: #5df56f;
width: 100%;
height: 100%;
z-index: -1;
transform: translateX(-100%);
animation-name: none;
animation-duration: 2s;
animation-fill-mode: forwards;
transform: translateX(-100%);
}
@keyframes box_slide {
0% {
transform: translate(-100%, 0);
}
100% {
transform: translate(0, 0);
}
}
.text {
font-size: 3rem;
align-items: center;
width: fit-content;
margin: 0 auto;
}
const box = document.getElementById("box");
const sheets = document.styleSheets;
const sheet = sheets[sheets.length - 1];
const options = {
threshold: 1,
};
function showBox(entries) {
if (entries[0].isIntersecting) {
sheet.insertRule(
".box::after { animation-name: box_slide }",
sheet.cssRules.length
);
}
}
const observer = new IntersectionObserver(showBox, options);
observer.observe(box);
さいごに
今回はIntersectionObserver
を使って簡単にスクロール処理を実装する方法を紹介しました。
この他にも色々なことができるのでぜひ試してみてください!