スクロールで画像を拡大!Delighters.jsの使い方
スクロールすると特定の位置でクラスを付与して画像が拡大されるDelighters.jsの使い方を自分用にまとめてみました。
-完成DEMO-
HTML
<header id="header">
<section>
<div class="header-sp">
<h1 class="site-logo"> <a href="#"><img src="https://dl.easyuploader.cloud/20220130202634_77717844.svg" alt="#"></a> </h1>
<!-- hamburger-menu -->
<div id="navArea">
<nav>
<div class="inner">
<ul>
<li><a href="#">TEST1</a></li>
<li><a href="#">TEST2</a></li>
<li><a href="#">TEST3</a></li>
<li><a href="#">TEST4</a></li>
<li><a href="#">TEST5</a></li>
</ul>
<div class="nav-sns-erea">
<p class="txt-title">Social</p>
<ul class="sns-contents">
<li>
<p>Instagram</p>
</li>
<li>
<p>YouTube</p>
</li>
</ul>
</div>
<div class="nav-other-erea">
<p class="txt-title">Site By</p>
<ul class="other-contents">
<a href="#">
<li>Delusion Design.</li>
</a>
</ul>
</div>
<!-- toggle_btn -->
<div class="close_btn"> <span class="close">CLOSE</span> </div>
</div>
</nav>
<div class="toggle_btn"> <span class="open"></span> <span class="open"></span> <span class="open"></span> </div>
<!-- mask -->
<div id="mask"></div>
</div>
</div>
</section>
<main>
<div class="main-wrapper">
<p>content</p>
</div>
<!-- Delighters -->
<section id="Delighters">
<div class="wrapper">
<div class="img-erea"> <img class="zoom-out-img" data-delighter src="https://dl.easyuploader.cloud/20220131221337_51385349.webp" alt="サンプル画像" loading="lazy" /> </div>
<div class="img-box-wrapper">
<div class="img-box1"> <img class="zoom-out-img" data-delighter src="https://dl.easyuploader.cloud/20220207215853_69655456.webp" alt="サンプル画像2" loading="lazy" /> </div>
<div class="img-box2"> <img class="zoom-out-img" data-delighter src="https://dl.easyuploader.cloud/20220207215853_39344366.webp" alt="サンプル画像3" loading="lazy" /> </div>
</div>
</div>
</section>
<div class="main-wrapper">
<p>content2</p>
</div>
</main>
<footer id="footer">
<p>footer</p>
</footer>
CSS
/*---------------------------
0.common setting
---------------------------*/
* {
margin: 0;
padding: 0;
}
html {
font-size: 100%;
}
body {
font-family: 'Noto Sans JP', sans-serif;
font-size: 1rem;
color: #333333;
line-height: 1.5;
}
ul {
list-style: none;
}
/*---------------------------
1. header
---------------------------*/
.header-sp {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
/*paddingとborderを幅と高さに含める*/
box-sizing: border-box;
background-color: #262421;
width: 100%;
height: 60px;
z-index: 9998;
}
/*line-heightにh1タグの高さよりも小さい値「0」を指定することで、h1タグの上下の余白が消えるため、ロゴ画像の高さと揃う*/
.site-logo {
display: inline-block;
line-height: 0;
}
/* aタグのリンク範囲を親要素のサイズに広げる */
.site-logo a {
display: block;
}
.site-logo img {
width: 200px;
}
/* nav
---------------------------*/
nav {
display: block;
position: fixed;
top: 0;
/* ナビゲーションを表示させる位置を指定する */
right: -1800px;
bottom: 0;
/* メニューアイコンを押下した際のナビゲーションメニューの横幅を指定する */
width: 90%;
background: #262421;
overflow-x: hidden;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
/* ナビゲーションを表示する速度を指定する */
transition: all 0.6s;
z-index: 4;
opacity: 0;
}
.open nav {
/* ナビゲーションの表示位置を指定する */
right: 0;
/* ナビゲーションの透過率を指定する */
opacity: 1;
}
nav .inner {
padding: 4.0625rem 1.5625rem 1rem 1.5625rem;
}
nav .inner ul {
display: inlineblock;
list-style: none;
line-height: 1;
margin: 0;
}
nav .inner ul li {
position: relative;
margin: 15px 0;
}
nav .inner ul li a {
display: inlineblock;
color: #fff;
font-size: 1.5rem;
transition-duration: 0.2s;
text-decoration: none;
}
nav .nav-sns-erea, nav .nav-other-erea {
margin-top: 30px;
}
nav .nav-sns-erea li, nav .nav-other-erea li {
color: #fff;
font-size: 0.9375rem;
}
.other-contents a {
text-decoration: none;
}
nav .txt-title {
color: #919090;
font-size: 0.75rem;
font-family: 'Libre Baskerville', serif;
font-style: italic;
font-weight: 400;
line-height: 1;
}
nav .sns-contents, nav .other-contents {
margin-top: 10px;
}
nav .sns-contents p {
display: inline-block;
}
nav .other-contents p {
display: inline-block;
font-size: 1rem;
font-weight: 400;
}
/* toggle_btn
---------------------------*/
.toggle_btn {
display: block;
position: fixed;
top: 15px;
right: 15px;
width: 30px;
height: 30px;
cursor: pointer;
z-index: 3;
}
.toggle_btn .open {
display: block;
position: absolute;
left: 0;
width: 30px;
height: 1px;
background-color: #fff;
border-radius: 4px;
}
.toggle_btn .open:nth-child(1) {
top: 15px;
}
.toggle_btn .open:nth-child(2) {
top: 20px;
}
.toggle_btn .open:nth-child(3) {
top: 25px;
}
/*1つ目の要素のafter要素にMenu表示を指定する*/
.toggle_btn .open:nth-child(1)::after {
content: "Menu";
position: absolute;
top: -15px;
left: 0;
color: #fff;
font-size: 0.625rem;
line-height: 1;
text-transform: uppercase;
}
/* クリック時にハンバーガーメニューを非表示にする */
.open .toggle_btn .open {
display: none;
}
/* close_btn
---------------------------*/
/* 非表示にしたハンバーガーメニューの変わりに表示するアイコンを指定する */
.close_btn .close::before {
position: absolute;
top: 0px;
left: -20px;
font-family: 'Font Awesome 5 Free';
content: "\f057";
font-size: 1rem;
font-weight: 600;
}
.close_btn {
position: absolute;
color: #fff;
cursor: pointer;
/* 非表示にしたハンバーガーメニューの変わりにCLOSEを表示する位置を指定する */
top: calc(0% + 25px);
left: calc(100% - 80px);
z-index: 4;
}
/* mask
---------------------------*/
#mask {
display: none;
transition: all .5s;
}
/* ナビゲーションが展開された部分の外側余白を指定する */
.open #mask {
display: block;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
opacity: .8;
z-index: 2;
cursor: pointer;
}
/*---------------------------
2. main
---------------------------*/
.main-wrapper {
height: 600px;
background-color: #F8F7F5;
display: flex;
justify-content: center;
align-items: center;
}
.main-wrapper p {
font-size: 5rem;
}
/* Delighters
---------------------------*/
#Delighters {
background-color: #F8F7F5;
}
.img-erea {
margin: 0 auto;
/* 領域からはみ出た部分を表示しないように指定する */
overflow: hidden;
width: 40%;
}
.img-box-wrapper {
display:flex;
justify-content: center;
}
.img-box-wrapper .img-box1, .img-box-wrapper .img-box2 {
overflow: hidden;
width: 35%;
margin: 100px 10px 0 10px;
}
.img-erea img, .img-box1 img, .img-box2 img {
vertical-align: bottom;
width: 100%;
}
/* delighter 基本のスタイル(ズーム) */
.zoom-out-img.delighter {
transition: all 1s ease-out;
-webkit-transform: scale(1.15, 1.15);
transform: scale(1.15, 1.15);
}
/* delighter スタート時のスタイル(ズーム) */
.zoom-out-img.delighter.started {
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
/* delighter エンド時のスタイル(ズーム) */
.zoom-out-img.delighter.started.ended {
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
/*---------------------------
3. footer
---------------------------*/
#footer {
height: 600px;
background-color: #333333;
display: flex;
justify-content: center;
align-items: center;
}
#footer p {
font-size: 5rem;
color: #fff;
}
JS
// spナビ
(function ($) {
var $nav = $('#navArea');
var $btn = $('.toggle_btn');
var $mask = $('#mask');
var $close_btn = $('.close_btn');
var open = 'open'; // class
// menu open close
$btn.on('click', function () {
$nav.addClass(open);
});
$close_btn.on('click', function () {
$nav.removeClass(open);
});
// mask close
$mask.on('click', function () {
$nav.removeClass(open);
});
})(jQuery);
const setFillHeight = () => {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
}
// ここからリサイズの対応
let vw = window.innerWidth;
window.addEventListener('resize', () => {
if (vw === window.innerWidth) {
// 画面の横幅にサイズ変動がないので処理を終える
return;
}
// 画面の横幅のサイズ変動があった時のみ高さを再計算する
vw = window.innerWidth;
setFillHeight();
});
// 実行
setFillHeight();
// Delighters
/*
Delighters - Add CSS animations to delight users as they scroll down.
(c) 2018 - Q42
Written by Martin Kool
https://github.com/Q42/delighters
*/
var Delighters = new(function () {
var self = this,
dels = this.dels = [],
// default options
options = {
attribute: 'data-delighter',
classNames: ['delighter', 'started', 'ended'],
start: 0.75, // default start threshold
end: 0.75, // default end threshold
autoInit: true // initialize when DOMContentLoaded
};
document.addEventListener("DOMContentLoaded", function () {
if (options.autoInit) init();
});
function config(opts) {
for (var name in opts) options[name] = opts[name];
}
function init() {
document.addEventListener('scroll', scroll)
var els = document.querySelectorAll('[' + options.attribute + ']');
for (var i = 0; i < els.length; i++) {
var el = els[i],
def = el.getAttribute(options.attribute, 2),
pairs = def.split(';'),
del = {};
del.start = options.start;
del.end = options.end;
for (var j = 0; j < pairs.length; j++) {
var pair = pairs[j].split(':'),
name = pair[0],
val = isNaN(pair[1] * 1) ? pair[1] : pair[1] * 1;
if (name) del[name] = (val === undefined) ? true : val;
}
del.el = el;
del.id = dels.length;
dels.push(del);
el.classList.add(options.classNames[0])
if (del.debug) el.style.outline = 'solid red 4px';
}
scroll();
}
function scroll() {
var viewportHeight = window.innerHeight;
for (var i = 0; i < dels.length; i++) {
var del = dels[i],
box = del.el.getBoundingClientRect(),
factorStart = box.top / viewportHeight,
factorEnd = box.bottom / viewportHeight;
if (del.debug) {
if (factorStart >= 0 && factorStart <= 1) {
if (!del.startLine) {
del.startLine = document.createElement('div')
document.body.appendChild(del.startLine);
del.startLine.style = 'position:fixed;height:0;width:100%;border-bottom:dotted red 2px;top:' + (del.start * 100) + 'vh';
}
}
if (((factorEnd < del.end) || (factorStart > 1)) && del.startLine) {
del.startLine.parentNode.removeChild(del.startLine);
delete del.startLine;
}
}
// trueにすると繰り返し、falseにすると一回だけ
if (factorStart < del.start && !del.started) {
del.started = true;
del.el.classList.add(options.classNames[1])
} else if (factorStart > del.start && del.started) {
del.started = false;
del.el.classList.remove(options.classNames[1])
}
if (factorEnd < del.end && !del.ended) {
del.ended = true;
del.el.classList.add(options.classNames[2])
} else if (factorEnd > del.end && del.ended) {
del.ended = false;
del.el.classList.remove(options.classNames[2])
}
}
}
self.init = init;
self.config = config;
})();