画像をモーダルで拡大表示する機能
準備中
imgを包むfigureに[zoomMod]classを指定。
CSSは先にmodal関数のCSSを設置してからzoomのCSSを設置
準備中
ライブラリを導入する前に
.zoomMod {
display: flex;
gap: 16px;
}
.zoomMod-wrap {
flex: 1;
display: block;
cursor: zoom-in;
position: relative;
}
.zoomMod-wrap::after {
content: '\e8ff';
font-size: 24px;
font-family: 'Material Icons';
padding: 4px 4px 3px;
line-height: 1;
border-radius: 4px;
background: rgba(0,0,0,0.7);
color: #fff;
position: absolute;
top: 8px;
right: 8px;
z-index: 1;
}
.zoomMod-img {width: 100%;}
.zoom .modalMod-sec ,
.zoomMods ,
.zoomMods-imgset-fig ,
.zoomMods-imgset ,
.zoomMods-imgset-li {height: 100%;}
.zoom .modalMod-sec {max-height: 95%;}
.zoomMods {position: relative;}
.zoomMods-imgset {
display: flex;
gap: 24px;
overflow: hidden;
}
.zoomMods-imgset-li {
min-width: 100%;
transition: 0.2s;
}
.zoomMods-imgset-img {
width: 100%;
height: 100%;
object-fit: contain;
}
.zoomMods-pager {
width: 100%;
height: 100%;
position: absolute;
top: 0;
}
.zoomMods-pager-dot {
width: fit-content;
margin: auto;
padding: 4px 16px;
border-radius: 16px;
background: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
gap: 16px;
position: absolute;
bottom: -20px;
left: 0;
right: 0;
z-index: 1;
opacity: 0;
transition: 0.2s;
}
.zoomMods-pager-dot-btn {
width: 8px;
height: 8px;
border-radius: 50% 50%;
background: rgba(255,255,255,0.5);
}
.zoomMods-pager-dot-btn:hover ,
.act .zoomMods-pager-dot-btn {background: rgba(255,255,255,1);}
.zoomMods-pager-btn {
width: 32px;
height: 32px;
margin: auto;
background: rgba(0,0,0,0.6);
color: #fff;
border-radius: 50% 50%;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
opacity: 0;
transition: 0.2s;
}
.zoomMods:hover .zoomMods-pager-dot,
.zoomMods:hover .zoomMods-pager-btn {opacity: 1;}
.zoomMods-pager-btn:hover {background: rgba(0,0,0,0.9);}
.zoomMods-pager-btn.prev {left: 8px;}
.zoomMods-pager-btn.next {right: 8px;}
.zoomMods-pager-btn.prev .ico-mui::before {content: '\e408';}
.zoomMods-pager-btn.next .ico-mui::before {content: '\e409';}
@media screen and (max-width: 768px) {
.zoomMod-wrap::after {font-size: 20px;}
.zoom .modalMod-sec,
.zoomMods,
.zoomMods-imgset-fig,
.zoomMods-imgset,
.zoomMods-imgset-li {height: auto;}
.zoomMods-imgset-li {
display: flex;
justify-content: center;
align-items: center;
}
.zoomMods-pager-dot {bottom: 0;}
.zoomMods-pager-dot , .zoomMods-pager-btn {opacity: 1;}
}
//初期設定
$('.zoomMod img').each(function(){
$(this).addClass('zoomMod-img');
if($(this).siblings('img')[0] || $(this).prev('.zoomMod-wrap')[0]){
//複数画像
var wrapOBJ = '';
} else {
//単体画像
var wrapOBJ = '';
}
if(!$(this).parents('.zoomMod-wrap')[0]){
$(this).wrap(wrapOBJ);
}
});
//ズームアクション
$bd.on('click','.zoomMod-wrap',function(){
const imgObj = $(this).find('.zoomMod-img').clone();
const imgleng = $(this).siblings().size() + 1;
const $i = $(this).index();
if($(this).hasClass('list')){
//複数画像
var obj = '
';
modalOpen(obj,'swip-zoom','zoom','','hug');
//画像・ドット作成
for(var i = 0; i < imgleng; i++) {
$('.zoomMods-imgset').append('.parent().find('.zoomMod-img').eq(i).attr('src').replace('.','_xl.') + ')
');
$('.zoomMods-pager-dot').append('');
}
$('.zoomMods-imgset-li').css('transform',translateX($i));
$('.zoomMods-pager-dot-li').eq($i).addClass('act');
} else {
//単体画像
var obj = '.find('.zoomMod-img').attr('src').replace('.','_xl.') + ')
';
modalOpen(obj,'swip','zoom','','fill');
}
});
//ページングアクション
$bd.on('click','.zoomMods-pager-btn',function(){
const $li = $('.zoomMods-imgset-li');
const $dot = $('.zoomMods-pager-dot-li');
const full = $dot.length;
const now = $('.zoomMods-pager-dot-li.act').index() + 1;
$('.zoomMods-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 {
const Num = Number(now - 2);
$dot.eq(Num).addClass('act');
$li.css('transform',translateX(Num));
}
}
});
//ドットアクション
$bd.on('click','.zoomMods-pager-dot-btn',function(){
const $papa = $(this).parent();
const $i = $papa.index();
$('.zoomMods-pager-dot-li.act').removeClass('act');
$papa.addClass('act');
$('.zoomMods-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 = $('.zoomMods-pager-dot-li.act').index();
//最初もしくは最後のアイテムの場合は動かさない
if(this.pageXm - this.pageX > 0 && act === 0 || this.pageXm - this.pageX < 0 && act + 1 == $('.zoomMods-pager-dot-li').length){
this.touchedTree = false;
return;
}
//移動量計算
if(act === 0){var X = 0;} else {var X = -(act * 100);}
var Y = this.pageXm - this.pageX;
var yc = Y + X;
if(Y > 100 || Y < -108 - (act * 8)){
return;
} else {
$('.zoomMods-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);
var act = $('.zoomMods-pager-dot-li.act').index();
if(this.top == 0 && this.left == 0){
return;
} else if(this.left > 30){
if(act == 0){var Xm = 1;} else {var Xm = act + 1;}
$('.zoomMods-imgset-li').css('transform',translateX(Xm));
$('.zoomMods-pager-dot-li.act').removeClass('act');
$('.zoomMods-pager-dot-li').eq(act + 1).addClass('act');
nowTouch = false;
} else if(this.left < -30){
if(act == 0){var Xm = 100;} else {var Xm = act - 1;}
$('.zoomMods-imgset-li').css('transform',translateX(Xm));
$('.zoomMods-pager-dot-li.act').removeClass('act');
$('.zoomMods-pager-dot-li').eq(act - 1).addClass('act');
nowTouch = false;
} else {
if(act == 0){var tX = 0;} else {var tX = '-' + act + '00%';}
$('.zoomMods-imgset-li').css({'transform':translateX(tX)});
}
$('.zoomMods-imgset-li').css({'transition':'0.2s'});
}
}, '.modalMod-sec.swip-zoom');
画像リスト
単体画像