Image Group

複数の画像をグループ化してモーダルで拡大表示する機能

詳しい導入事例は導入方法を参照してください。

画像をモーダルで拡大表示します。

  • DEMO
  • 別要素テスト1
  • 別要素テスト2
  • 単体テスト
  • Text Test

  • Text Test

  • Text Test

  • No.1

  • No.2

  • No.3

  • No.4

  • No.5

  • No.6

使い方

グループ化したい*-img-*を包む要素に+-.mod_imgGzoom-+クラスを指定してください。

モーダル表示と併用するのでModalライブラリの記述も読み込んでください。
  • CSS
  • Script
.mod_imgGzoom {
  display: flex;
  gap: 16px;
}
.mod_imgGzoom-wrap {
  flex: 1;
  height: fit-content;
  display: block;
  cursor: zoom-in;
  position: relative;
}
.mod_imgGzoom-wrap::after {
  content: '\e8ff';
  padding: 4px;
  border-radius: var(--radius-circle);
  background: var(--overlay);
  color: var(--bg-paper);
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  opacity: 0;
  transition: .2s;
}
.mod_imgGzoom-wrap:hover:after {opacity: 1;}
.mod_imgGzoom-img {width: 100%;}

.zoom #mod_modal .mod_modal-sec ,
.mod_imgGzooms ,
.mod_imgGzooms-imgset-fig ,
.mod_imgGzooms-imgset-li {height: 100%;}
.zoom #mod_modal .mod_modal-sec {max-height: 95%;}

.mod_imgGzooms {position: relative;}
.mod_imgGzooms-imgset {
  height: calc(100% - 16px);
  display: flex;
  gap: 24px;
  overflow: hidden;
}
.mod_imgGzooms-imgset-li {
  min-width: 100%;
  transition: .2s;
}
.mod_imgGzooms-imgset-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.mod_imgGzooms-pager {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
}
.mod_imgGzooms-pager-dot {
  width: fit-content;
  margin: auto;
  padding: 8px 16px;
  border-radius: var(--radius-round);
  background: var(--overlay);
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  position: absolute;
  bottom: -16px;
  left: 0;
  right: 0;
  z-index: 1;
  opacity: 0;
  transition: .2s;
}
.mod_imgGzooms-pager-dot-btn {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-circle);
  background: rgb(255 255 255 / .5);
}
.mod_imgGzooms-pager-dot-btn:hover ,
.act .mod_imgGzooms-pager-dot-btn {background: rgb(255 255 255 / 1);}
.mod_imgGzooms-pager-btn {
  width: 32px;
  height: 32px;
  margin: auto;
  background: var(--overlay);
  color: var(--bg-paper);
  border-radius: var(--radius-circle);
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 1;
  opacity: 0;
  transition: .2s;
}
.mod_imgGzooms:hover .mod_imgGzooms-pager-dot,
.mod_imgGzooms:hover .mod_imgGzooms-pager-btn {opacity: 1;}
.mod_imgGzooms-pager-btn:hover {background: rgb(0 0 0 / .9);}
.mod_imgGzooms-pager-btn.prev {left: 8px;}
.mod_imgGzooms-pager-btn.next {right: 8px;}
.mod_imgGzooms-pager-btn.prev .ico-mui::before {content: '\e408';}
.mod_imgGzooms-pager-btn.next .ico-mui::before {content: '\e409';}

@media screen and (max-width: 768px) {
  .zoom .mod_modal-sec,
  .mod_imgGzooms,
  .mod_imgGzooms-imgset-fig,
  .mod_imgGzooms-imgset,
  .mod_imgGzooms-imgset-li {height: auto;}
  .mod_imgGzooms-imgset-li {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .mod_imgGzooms-pager-dot {bottom: 0;}
  .mod_imgGzooms-pager-dot , .mod_imgGzooms-pager-btn {opacity: 1;}
}
//初期設定
$('.mod_imgGzoom img').each(function(){
  $(this).addClass('mod_imgGzoom-img');
  let wrapOBJ = '<span class="mod_imgGzoom-wrap ico-aft"></span>';
  if($(this).siblings('img')[0] || $(this).parents('.mod_imgGzoom').find('img').length > 1){
    //複数画像
    wrapOBJ = '<span class="mod_imgGzoom-wrap list ico-aft"></span>';
  }
  if(!$(this).parents('.mod_imgGzoom-wrap')[0]){
    $(this).wrap(wrapOBJ);
  }
});

//ズームアクション
$bd.on('click','.mod_imgGzoom-wrap',function(){
  let $Mod = $(this).parents('.mod_imgGzoom');
  let imgleng = $Mod.find('.mod_imgGzoom-wrap').length;
  let $i = $Mod.find('.mod_imgGzoom-wrap').index($(this));
  let $img = $(this).find('.mod_imgGzoom-img');

  let src = $img.attr('src');
  if($img.data('suffix') != ''){
    let suffix = 'zoom';
    if($img.data('suffix') != undefined){
      suffix = $img.data('suffix');
    }
    src = src.replace('.','_'+suffix +'.');
  }
  let obj = '<div class="mod_imgGzooms"><figure class="mod_imgGzooms-imgset-fig"><img class="mod_imgGzooms-imgset-img" src="' + src + '" alt=""></figure></div>';

  if($(this).hasClass('list')){
    //複数画像
    obj = '<div class="mod_imgGzooms"><ul class="mod_imgGzooms-imgset"></ul><div class="mod_imgGzooms-pager"><ul class="mod_imgGzooms-pager-dot"></ul><button class="mod_imgGzooms-pager-btn prev"><i class="ico-mui"></i></button><button class="mod_imgGzooms-pager-btn next"><i class="ico-mui"></i></button></div></div>';
    modalOpen(obj,'swip-zoom','zoom','','hug');
    
    //画像・ドット作成
    for(var i = 0; i < imgleng; i++) {
      let t = $Mod.find('.mod_imgGzoom-img').eq(i);
      let src = t.attr('src');
      if(t.data('suffix') != ''){
        let suffix = 'zoom';
        if(t.data('suffix') != undefined){
          suffix = t.data('suffix');
        }
        src = src.replace('.','_'+suffix +'.');
      }
      $('.mod_imgGzooms-imgset').append('<li class="mod_imgGzooms-imgset-li"><figure class="mod_imgGzooms-imgset-fig"><img class="mod_imgGzooms-imgset-img" src="' + src + '" alt=""></figure></li>');
      $('.mod_imgGzooms-pager-dot').append('<li class="mod_imgGzooms-pager-dot-li"><button class="mod_imgGzooms-pager-dot-btn"></button></li>');
    }

    $('.mod_imgGzooms-imgset-li').css('transform',translateX($i));
    $('.mod_imgGzooms-pager-dot-li').eq($i).addClass('act');
  } else {
    //単体画像
    modalOpen(obj,'swip','zoom','','fill');
  }
});

//ページングアクション
$bd.on('click','.mod_imgGzooms-pager-btn',function(){
  let $li = $('.mod_imgGzooms-imgset-li');
  let $dot = $('.mod_imgGzooms-pager-dot-li');
  let full = $dot.length;
  let now = $('.mod_imgGzooms-pager-dot-li.act').index() + 1;

  $('.mod_imgGzooms-pager-dot-li.act').removeClass('act');

  if($(this).hasClass('next')){
    //次へ
    if(full == now){
      //最後なら
      $dot.eq(0).addClass('act');
      $li.css('transform','translateX(0)');
    } else {
      $dot.eq(now).addClass('act');
      $li.css('transform',translateX(now));
    }
  } else if($(this).hasClass('prev')){
    //前へ
    if(now == 1){
      //最初なら
      $dot.last().addClass('act');
      $li.css('transform',translateX(full - 1));
    } else {
      let Num = Number(now - 2);
      $dot.eq(Num).addClass('act');
      $li.css('transform',translateX(Num));
    }
  }
});

//ドットアクション
$bd.on('click','.mod_imgGzooms-pager-dot-btn',function(){
  let $papa = $(this).parent();
  let $i = $papa.index();

  $('.mod_imgGzooms-pager-dot-li.act').removeClass('act');
  $papa.addClass('act');
  $('.mod_imgGzooms-imgset-li').css('transform',translateX($i));
});

//移動量計算
function translateX(num){
  return 'translateX(calc(-' + num + '00% - ' + 24 * num + 'px))';
}

//スワイプ
$bd.on({
  'touchstart': function(e){
    this.pageX = (isTouch ? event.changedTouches[0].pageX : e.pageX);
    this.pageY = (isTouch ? event.changedTouches[0].pageY : e.pageY);
    this.touchedTree = true;
    this.touched = false;
  },
  'touchmove': function(e){
    if(!this.touchedTree){return;}
    this.pageXm = (isTouch ? event.changedTouches[0].pageX : e.pageX);
    this.pageYm = (isTouch ? event.changedTouches[0].pageY : e.pageY);

    if(this.pageXm != 0){
      var act = $('.mod_imgGzooms-pager-dot-li.act').index();

      //最初もしくは最後のアイテムの場合は動かさない
      if(this.pageXm - this.pageX > 0 && act === 0 || this.pageXm - this.pageX < 0 && act + 1 == $('.mod_imgGzooms-pager-dot-li').length){
        this.touchedTree = false;
        return;
      }

      //移動量計算
      if(act === 0){var X = 0;} else {var X = -(act * 100);}
      let Y = this.pageXm - this.pageX;
      let yc = Y + X;
      if(Y > 100 || Y < -108 - (act * 8)){
        return;
      } else {
        $('.mod_imgGzooms-imgset-li').css({
          'transform':'translateX(' + yc + '%)',
          'transition':'none'
        });
      }
      nowTouch = true;
    }
  },
  'touchend': function(e){
    if(!this.touchedTree){return;}
    this.touchedTree = false;
    this.left = this.pageX - (isTouch ? event.changedTouches[0].pageX : e.pageX);
    this.top = this.pageY - (isTouch ? event.changedTouches[0].pageY : e.pageY);
    let act = $('.mod_imgGzooms-pager-dot-li.act').index();
    if(this.top == 0 && this.left == 0){
      return;
    } else if(this.left > 30){
      let Xm = act + 1;
      if(act == 0){Xm = 1;}
      $('.mod_imgGzooms-imgset-li').css('transform',translateX(Xm));
      $('.mod_imgGzooms-pager-dot-li.act').removeClass('act');
      $('.mod_imgGzooms-pager-dot-li').eq(act + 1).addClass('act');
      nowTouch = false;
    } else if(this.left < -30){
      let Xm = act - 1;
      if(act == 0){Xm = 100;}
      $('.mod_imgGzooms-imgset-li').css('transform',translateX(Xm));
      $('.mod_imgGzooms-pager-dot-li.act').removeClass('act');
      $('.mod_imgGzooms-pager-dot-li').eq(act - 1).addClass('act');
      nowTouch = false;
    } else {
      let tX = '-' + act + '00%';
      if(act == 0){tX = 0;}
      $('.mod_imgGzooms-imgset-li').css({'transform':translateX(tX)});
    }
    $('.mod_imgGzooms-imgset-li').css({'transition':'0.2s'});
  }
}, '.mod_modal-sec.swip-zoom');

サフィックス

拡大後の画像置換設定

デフォルトでは拡大後の画像は元画像のファイル名に[_zoom]のサフィックスを付けたファイル名にしています。
他のサフィックスを使用する場合は[data-suffix]属性に「_」を抜いたサフィックスの値を入れてください。
画像の置換をせずに元画像をそのまま拡大する場合は空で[data-suffix]属性を付けてください。

拡大前)hoge.jpg

デフォルト)hoge_zoom.jpg

data-suffix="xl")hoge_xl.jpg

data-suffix="")hoge.jpg

  • サフィックス指定
  • サフィックス無し