見出し画像

スクロールで画像を拡大!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;
   })();

この記事が気に入ったらサポートをしてみませんか?