<div class="viewer"><img src="https://picsum.photos/id/1/800/400"></div>
<ul class="viewer__list">
    <li><a href="https://picsum.photos/id/1/800/400" class="viewer__item is-current"><img src="https://picsum.photos/id/1/300/150" alt=""></a></li>
    <li><a href="https://picsum.photos/id/10/800/400" class="viewer__item"><img src="https://picsum.photos/id/10/300/150" alt=""></a></li>
    <li><a href="https://picsum.photos/id/348/800/400" class="viewer__item"><img src="https://picsum.photos/id/348/300/150" alt=""></a></li>
</ul>
  • Content:
    .viewer {
      position: relative;
      width: 100%;
      max-width: 600px;
      margin: 0 auto 16px;
    }
    
    .viewer > img {
      opacity: 1;
      width: 100%;
    }
    
    .viewer.is-change-active > img {
      position: absolute;
      top: 0;
      left: 0;
      transition: opacity 1s;
    }
    
    .viewer.is-change-active > img:first-child {
      z-index: 1;
    }
    
    .viewer__list {
      display: flex;
      width: 100%;
      max-width: 600px;
      margin: 0 auto 16px;
      justify-content: space-between;
    }
    
    .viewer__list > li {
      width: calc((100% - 24px) / 3);
    }
    
    .viewer__item {
      display: block;
      filter: grayscale(100%);
      transition: filter 1s;
    }
    
    .viewer__item.is-current {
      filter: grayscale(0%);
    }
    
    .viewer__item > img {
      width: 100%;
    }
    
  • URL: /components/raw/viewer/viewer.css
  • Filesystem Path: src\components\03-viewer\viewer.css
  • Size: 677 Bytes
  • Content:
    .viewer {
      position: relative;
      width: 100%;
      max-width: 600px;
      margin: 0 auto $space_lg;
      & > img {
        opacity: 1;
        width: 100%;
      }
      &.is-change-active > img {
        position: absolute;
        top: 0;
        left: 0;
        transition: opacity $speed_slow;
      }
      &.is-change-active > img:first-child {
        z-index: 1;
      }
      &__list {
        display: flex;
        width: 100%;
        max-width: 600px;
        margin: 0 auto $space_lg;
        justify-content: space-between;
        & > li {
          width: calc((100% - #{$space_md * 2}) / 3);
        }
      }
      &__item {
        display: block;
        filter: grayscale(100%);
        transition: filter $speed_slow;
        &.is-current {
          filter: grayscale(0%);
        }
        & > img {
          width: 100%;
        }
      }
    }
    
  • URL: /components/raw/viewer/viewer.scss
  • Filesystem Path: src\components\03-viewer\viewer.scss
  • Size: 729 Bytes
  • Content:
    (function() {
      const viewerEl = document.querySelector('.viewer');
      if(!viewerEl) {return;}
      const viewerItems = document.querySelectorAll('.viewer__item');
      let changeFlag = false;
    
      viewerItems.forEach(item => {
        item.addEventListener('click', (e) => {
          e.preventDefault();
          // 画像切り替え時にクリックした場合、もしくは現在表示されている画像をクリックした場合は処理しない
          if(changeFlag || item.classList.contains('is-current')) {return;}
          changeFlag = true;
          viewerChange(item);
          itemCurrentChange(item);
        });
      });
    
      // viewer画像の切り替え
      function viewerChange(item) {
        let viewerCurrentImg = viewerEl.querySelector('img');
        let viewerNextImg = document.createElement('img');
        let viewerWidth = viewerEl.clientWidth;
        let viewerHeight = viewerEl.clientHeight;
    
        // position:absolute時にレイアウトが崩れないよう、画像切り替え時のみwidth・heightを固定
        // viewerの外枠
        viewerEl.style.width = `${viewerWidth}px`;
        viewerEl.style.height = `${viewerHeight}px`;
        // 次の画像
        viewerNextImg.setAttribute('src', item.getAttribute('href'));
        viewerNextImg.style.width = `${viewerWidth}px`;
        viewerNextImg.style.height = `${viewerHeight}px`;
        // 現在の画像
        viewerCurrentImg.style.width = `${viewerWidth}px`;
        viewerCurrentImg.style.height = `${viewerHeight}px`;
    
        // 現在の画像のopacityが0になったら要素自体を削除。また、一時的に付与していたwidth・heightの固定を解除
        viewerCurrentImg.addEventListener('transitionend', () => {
          viewerCurrentImg.remove();
          viewerEl.classList.remove('is-change-active');
          viewerEl.style.width = '';
          viewerEl.style.height = '';
          viewerNextImg.style.width = '';
          viewerNextImg.style.height = '';
          changeFlag = false;
        });
    
        viewerEl.classList.add('is-change-active');
        viewerEl.appendChild(viewerNextImg);
        viewerCurrentImg.style.opacity = 0;
      }
    
      // サムネイル画像へのis-currentクラス付け替え
      function itemCurrentChange(item) {
        viewerItems.forEach(el => {
          el.classList.remove('is-current');
        });
        item.classList.add('is-current');
      }
    }());
    
  • URL: /components/raw/viewer/viewer.js
  • Filesystem Path: src\components\03-viewer\viewer.js
  • Size: 2.3 KB