👻
[JavaScript]素のJSで作る追従バナーサンプル
はじめに
本記事は、筆者による理解の復習・確認やアウトプットの練習のために書いております。
間違った解釈等ございましたら、ご連絡いただけますと幸いです。
イメージ
動画 →GIF 変換のせいか、気持ち速くなってます
確認動作環境
Chrome
コード置き場
コード全体
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>追従バナーサンプル</title>
</head>
<body>
<div id="banner-wrapper"></div>
<style>
* {
margin: 0;
padding: 0;
}
body {
height: 2000px;
position: relative;
}
#banner-wrapper {
width: 150px;
height: 150px;
background: red;
position: absolute;
right: 0;
background: url(./banner.png);
background-size: contain;
}
</style>
<script>
const banner = document.getElementById('banner-wrapper')
const bannerHeight = banner.offsetHeight
const windowHeight = window.innerHeight
const displayHeight = windowHeight - (bannerHeight + 30)
banner.style.top = `${displayHeight}px`
banner.style.bottom = 'initial';
window.addEventListener('scroll', () => {
const scrollY = document.documentElement.scrollTop
banner.style.top = `${displayHeight + scrollY}px`
banner.animate([
{ top: `${displayHeight + scrollY}px` }
], {
duration: 2000,
easing: 'ease-in-out'
})
})
</script>
</body>
</html>
それぞれ説明
const banner = document.getElementById('banner-wrapper') // 要素の取得
const bannerHeight = banner.offsetHeight // 要素の高さを取得(150px)
const windowHeight = window.innerHeight // 表示されている画面の高さを取得
const displayHeight = windowHeight - (bannerHeight + 30) // バナーの定位置を初期値として設定
banner.style.top = `${displayHeight}px` // バナーの定位置をスタイルに反映
ちなみに、↑ を設定しなくても追従するんですが、たまに挙動がおかしくなってバナーがどこか行ってしまうので、スクロールのたびに top 値を設定してます。
// スクロールした時に発火
window.addEventListener('scroll', () => {
const scrollY = document.documentElement.scrollTop // スクロールしたピクセル数を返す
banner.style.top = `${displayHeight + scrollY}px` // バナー定位置 + スクロール分をtopの値に設定
// ぬるっと動かすアニメーションの設定
banner.animate([
{ top: `${displayHeight + scrollY}px` }
], {
duration: 2000, // 2000ミリ秒(2秒)遅らせてアニメーションさせる
easing: 'ease-in-out' // 最初と最後だけゆっくり、中間は加速する動きをつける
})
})
最後に
スクロールするたびに top 値を設定するの、処理が重くなってそうで嫌だなと思いながらも
他に実装手法を思い浮かばないので、もっと良い実装方法ございましたら教えてください!
参考
Discussion