📌
javascriptのスムーズscrollライブラリを作成しました。便利!!
以下のコードコピペで試せます。
js部分がライブラリ。
scrollしたい要素に、scrollable-boxを付けてください。
スクロールバーもそのまま使えます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>スムーズスクロールのモック</title>
<style>
body {
font-family: sans-serif;
margin: 0;
padding: 20px;
background-color: #f0f2f5;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.panel {
background-color: #fff;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 20px; /* Add margin for more content below */
}
h2 {
border-bottom: 2px solid #ddd;
padding-bottom: 10px;
}
.scrollable-box {
height: 200px;
overflow: auto; /* Enable scrolling here */
border: 1px solid #ccc;
padding: 10px;
margin-top: 10px;
background-color: #fafafa;
transition: box-shadow 0.3s ease; /* Add transition for a smoother effect */
}
.scrollable-box:hover {
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2); /* Highlight on hover */
}
.scroll-content {
height: 500px; /* Height for scrolling */
background-image: linear-gradient(to bottom, #a1c4fd, #c2e9fb);
padding: 10px;
}
/* Modal-related styles */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #fff;
padding: 20px;
border-radius: 8px;
max-width: 80%;
max-height: 80%;
overflow: hidden;
}
.modal-body {
height: 300px; /* Scrolling inside modal */
overflow: auto;
border: 1px solid #ddd;
padding: 10px;
margin-top: 10px;
transition: box-shadow 0.3s ease;
}
.modal-body:hover {
box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2);
}
.modal-scroll-content {
height: 800px;
background-image: linear-gradient(to bottom, #d4fc79, #96e6a1);
padding: 10px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
/* Style for the extra content to make the body scrollable */
.filler-content {
padding: 20px;
text-align: center;
color: #555;
}
</style>
</head>
<body>
<h1>スムーズスクロールのデモ</h1>
<p>以下のスクロール可能なボックスや、モーダル内のコンテンツに<strong>マウスカーソルを乗せて</strong>、マウスホイールでスクロールしてみてください。</p>
<p>※ マウスカーソルがどのボックスにも乗っていない場合は、ページ全体がスムーズにスクロールします。</p>
<div class="container">
<div class="panel" id="panel-1">
<h2>パネル 1</h2>
<p>このセクション内のスクロールボックスです。</p>
<div class="scrollable-box">
<div class="scroll-content">
<p>このボックスはスクロール可能です。</p>
<p>ホイールを回すと滑らかに動きます。</p>
<p>たくさんのコンテンツ...</p>
<p>たくさんのコンテンツ...</p>
<p>たくさんのコンテンツ...</p>
<p>たくさんのコンテンツ...</p>
<p>たくさんのコンテンツ...</p>
</div>
</div>
</div>
<div class="panel" id="panel-2">
<h2>パネル 2</h2>
<p>こちらにも別のスクロールボックスがあります。</p>
<div class="scrollable-box">
<div class="scroll-content">
<p>別のボックスです。</p>
<p>滑らかなスクロールを体験しましょう。</p>
<p>コンテンツをいっぱい入れてみました。</p>
<p>コンテンツをいっぱい入れてみました。</p>
<p>コンテンツをいっぱい入れてみました。</p>
<p>コンテンツをいっぱい入れてみました。</p>
<p>コンテンツをいっぱい入れてみました。</p>
</div>
</div>
</div>
</div>
<button id="openModalBtn">モーダルを開く</button>
<div class="modal-overlay">
<div class="modal-content">
<h2>モーダルウィンドウ</h2>
<div class="modal-body">
<div class="modal-scroll-content">
<p>これはモーダル内のスクロール可能なコンテンツです。</p>
<p>ここをクリックしてホイールを回してみてください。</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
<p>コンテンツ...</p>
</div>
</div>
<button id="closeModalBtn">閉じる</button>
</div>
</div>
<!-- Additional content to make the body scrollable -->
<div class="filler-content">
<h3>追加のコンテンツ</h3>
<p>このセクションは、ページ全体がスクロール可能であることをテストするために追加されました。</p>
<p>画面下の方までスクロールして、スムーズな動きを体験してください。</p>
<p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p>
<p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p>
<p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p>
<p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p><p>ダミーテキスト...</p>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
let targetScrollElement = document.body;
const scrollSpeed = 0.05;
const scroll_size = 3;
const animationInstances = new Map(); // マップを使用して要素ごとのアニメーションを管理
// スムーズスクロールを実行する関数
function smoothScroll(element, targetPosition) {
let currentPosition = element === document.body ? window.scrollY : element.scrollTop;
// 既にアニメーションが存在する場合はキャンセル
if (animationInstances.has(element)) {
cancelAnimationFrame(animationInstances.get(element));
}
function animate() {
currentPosition += (targetPosition - currentPosition) * scrollSpeed;
if (element === document.body) {
window.scrollTo(0, currentPosition);
} else {
element.scrollTop = currentPosition;
}
if (Math.abs(targetPosition - currentPosition) < 0.5) {
if (element === document.body) {
window.scrollTo(0, targetPosition);
} else {
element.scrollTop = targetPosition;
}
// アニメーション終了時にマップから削除
animationInstances.delete(element);
return;
}
animationInstances.set(element, requestAnimationFrame(animate));
}
// アニメーション開始
animationInstances.set(element, requestAnimationFrame(animate));
}
const scrollableElements = document.querySelectorAll('.scrollable-box, .modal-body');
scrollableElements.forEach(element => {
element.addEventListener('mouseenter', () => {
targetScrollElement = element;
console.log("Hovered on a scrollable element:", targetScrollElement);
});
element.addEventListener('mouseleave', () => {
targetScrollElement = document.body;
console.log("Mouse left scrollable element. Target reset to body.");
});
});
// Mouse wheel event listener
document.addEventListener('wheel', (event) => {
if (!targetScrollElement) return;
event.preventDefault();
// 現在のスクロール位置を正確に取得
let currentPosition = targetScrollElement === document.body
? window.scrollY
: targetScrollElement.scrollTop;
// 新しい目標地点を計算
let newTargetPosition = currentPosition + event.deltaY * scroll_size;
const maxScrollTop = targetScrollElement === document.body
? document.documentElement.scrollHeight - window.innerHeight
: targetScrollElement.scrollHeight - targetScrollElement.clientHeight;
newTargetPosition = Math.max(0, Math.min(newTargetPosition, maxScrollTop));
// スムーズスクロール関数を呼び出し、アニメーションを開始
smoothScroll(targetScrollElement, newTargetPosition);
}, { passive: false });
// スクロールを一番上にリセットする関数
function resetScrollPosition(element) {
if (!element) {
console.error("要素が指定されていません。");
return;
}
// スムーズスクロールが実行中の場合はキャンセル
if (animationInstances.has(element)) {
cancelAnimationFrame(animationInstances.get(element));
animationInstances.delete(element);
}
// スクロール位置を0に設定
if (element === document.body) {
window.scrollTo(0, 0);
} else {
element.scrollTop = 0;
}
}
// 関数をグローバルスコープに公開
window.resetScrollPosition = resetScrollPosition;
// Modal-related logic
const openModalBtn = document.getElementById('openModalBtn');
const closeModalBtn = document.getElementById('closeModalBtn');
const modalOverlay = document.querySelector('.modal-overlay');
openModalBtn.addEventListener('click', () => {
modalOverlay.style.display = 'flex';
document.body.style.overflow = 'hidden';
});
closeModalBtn.addEventListener('click', () => {
modalOverlay.style.display = 'none';
document.body.style.overflow = '';
targetScrollElement = document.body;
});
modalOverlay.addEventListener('click', (event) => {
if (event.target === modalOverlay) {
closeModalBtn.click();
}
});
});
</script>
</body>
</html>
Discussion