質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1416閲覧

画像モーダルでprev, next ボタンが機能しない

erp

総合スコア46

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/01/07 23:45

編集2022/01/08 06:49

前提・実現したいこと

画像モーダルで、画像をdata-group でグループ化したいです。

発生している問題・エラーメッセージ

今のところ、開いた画像と同じ data-group に class="on" をつけるところまではできました。
onモーダルの prev, next ボタンを押すと、グループ化された on のついた画像を一つずつ移動(+1, -1)するようにしたいです。

ところが、現状では最初の一回のボタンの押下で +3, -3 されてしまう状態です。ボタンを何回も押せば本来のように +1, -1ずつ動きますが、安定して増減させたいです。

該当のソースコード

js

1document.addEventListener('DOMContentLoaded', function () { 2 class Modal { 3 constructor() { 4 //初期値(DOM) 5 this.DOM = {}; 6 this.DOM.html = document.querySelector('html'); 7 this.DOM.thumbItems = document.querySelectorAll('.modal-imgs'); 8 this.DOM.modal = document.querySelector('.modal-wrapper'); 9 this.DOM.modalOverlay = document.querySelector('.modal-overlay'); 10 this.DOM.modalItem = document.querySelector('.mid'); 11 this.DOM.modalCaption = document.querySelector('.modal-aside'); 12 this.DOM.modalClose = document.querySelector('.mp-close'); 13 this.DOM.modalPrev = document.querySelector('.mp-prev'); 14 this.DOM.modalNext = document.querySelector('.mp-next'); 15 // スワイプ座標 16 this.startX; 17 this.endX; 18 // ターゲット要素 19 this.thumbTarget; 20 // 何番めの要素か 21 this.thumbCurrent; 22 // 最初に実行する関数 23 this._init(); 24 } 25 _init() { 26 this.DOM.thumbItems.forEach((thumbItem, index, array) => { 27 thumbItem.addEventListener('click', this._appearModal.bind(this, thumbItem, index)); 28 }); 29 this._clickEvent(); 30 // this._swipeEvent(); 31 // this._mouseEvent(); 32 } 33 // クリックイベント 34 _clickEvent() { 35 this.DOM.modalClose.addEventListener('click', this._disappearModal.bind(this)); 36 this.DOM.modalOverlay.addEventListener('click', this._disappearModal.bind(this)); 37 this.DOM.modal.addEventListener('click', (e) => { 38 if (e.target.querySelector('.modal-img')) { 39 this._disappearModal.bind(this); 40 } 41 }); 42 this.DOM.modalNext.addEventListener('click', this._next.bind(this)); 43 this.DOM.modalPrev.addEventListener('click', this._prev.bind(this)); 44 } 45 // モーダル表示 46 _appearModal(thumbItem, index) { 47 this.DOM.html.classList.add('is-fixed'); 48 this.thumbCurrent = index; // 現在のindex 49 this.DOM.modal.classList.add('spinner'); 50 this.DOM.modal.classList.add('show'); 51 this.DOM.modalOverlay.classList.add('show'); 52 this.thumbTarget = thumbItem; //モーダル表示する要素 53 this._modalShow(this.thumbTarget); // モーダル表示 54 setTimeout(function () { 55 document.querySelector('.modal-wrapper').classList.remove('spinner'); 56 }, 200); 57 } 58 // モーダル非表示 59 _disappearModal() { 60 this.DOM.html.classList.remove('is-fixed'); 61 this.DOM.modal.classList.remove('show'); 62 this.DOM.modalOverlay.classList.remove('show'); 63 this.DOM.thumbItems.forEach(function (thumbItem) { 64 thumbItem.classList.remove('on'); 65 }); 66 } 67 // モーダルに表示する画像 68 _modalShow(self) { 69 const imgElm = self; 70 const targetModalItem = this.DOM.modalItem.childNodes[0]; 71 targetModalItem.src = imgElm.getAttribute('data-src'); 72 // フェードインのクラス 73 targetModalItem.classList.remove('show'); 74 setTimeout(function () { 75 targetModalItem.classList.add('show'); 76 }, 300); 77 // グループ化 78 imgElm.classList.add('on'); 79 let imageGroup = imgElm.getAttribute('data-group'); 80 this.DOM.thumbItems.forEach(function (thumbItem) { 81 if (thumbItem.getAttribute('data-group') === imageGroup) { 82 thumbItem.classList.add('on'); 83 } 84 }); 85 this._modalCaption(imgElm); 86 } 87 // モーダルに表示するキャプション 88 _modalCaption(imgElm) { 89 this.DOM.modalCaption.innerText = imgElm.dataset.caption 90 } 91 _next() { 92 this.DOM.modal.classList.add('spinner'); 93 const thumbItemsOn = document.querySelectorAll('.modal-imgs.on'); 94 this.thumbCurrent = this._changeCount(1, this.thumbCurrent, thumbItemsOn.length); 95 this.thumbTarget = thumbItemsOn[this.thumbCurrent]; 96 this._modalShow(this.thumbTarget); // モーダル表示 97 setTimeout(function () { 98 document.querySelector('.modal-wrapper').classList.remove('spinner'); 99 }, 200); 100 } 101 _prev() { 102 this.DOM.modal.classList.add('spinner'); 103 const thumbItemsOn = document.querySelectorAll('.modal-imgs.on'); 104 this.thumbCurrent = this._changeCount(-1, this.thumbCurrent, thumbItemsOn.length); 105 this.thumbTarget = thumbItemsOn[this.thumbCurrent]; 106 setTimeout(function () { 107 document.querySelector('.modal-wrapper').classList.remove('spinner'); 108 }, 200); 109 this._modalShow(this.thumbTarget); // モーダル表示 110 } 111 // 変更する番号を取得 112 _changeCount(num, index, len) { 113 return (index + num + len) % len; 114 } 115 } 116 // インスタンス化 117 const modal = new Modal(); 118});

html

1<!-- gallery --> 2<div class="img-fit-01"> 3 <div class="aspect-box spinner"> 4 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-01"> 5 </div> 6 <div class="aspect-box spinner"> 7 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-02"> 8 </div> 9 <div class="aspect-box spinner"> 10 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-03"> 11 </div> 12 <div class="aspect-box spinner"> 13 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-04"> 14 </div> 15 <div class="aspect-box spinner"> 16 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-05"> 17 </div> 18 <div class="aspect-box spinner"> 19 <img alt class="lazyload modal-imgs" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" style="width: 100%; height: 100%;" data-group="gallery-01" data-src="img/photo/04.png" data-caption="画像の詳細を書けます 01-06"> 20 </div> 21 <aside>モーダルサンプル 02 / data-group でグループ化</aside> 22</div> 23 24<!-- image modal --> 25<div class="modal-wrapper spinner"> 26 <div class="mid"><img alt src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="></div> 27 <div class="mp-prev"></div> 28 <div class="mp-next"></div> 29 <div class="mp-close"></div> 30 <aside class="modal-aside">xxx</aside> 31</div> 32<div class="modal-overlay"></div>

css

1.modal-overlay { 2 display: none; 3 position: fixed; 4 align-items: center; 5 justify-content: center; 6 flex-direction: column; 7 top: 0; 8 left: 0; 9 cursor: pointer; 10 z-index: -1; 11 opacity: 0; 12 background: rgba(255, 255, 255, 1); 13 transition: all .25s 0s ease; 14} 15 16.modal-overlay.show { 17 display: flex; 18 width: 100%; 19 height: 100%; 20 z-index: 4; 21 opacity: 1; 22} 23 24.modal-wrapper { 25 display: flex; 26 position: fixed; 27 align-items: center; 28 justify-content: center; 29 flex-direction: column; 30 transform: translate(-50%, -50%); 31 top: 50%; 32 left: 50%; 33 z-index: -1; 34 visibility: hidden; 35 opacity: 0; 36 transition: visibility .25s, opacity .25s; 37 pointer-events: none; 38} 39 40.modal-wrapper.show { 41 width: auto; 42 z-index: 10; 43 visibility: visible; 44 opacity: 1; 45 pointer-events: all; 46} 47 48.mid img { 49 display: inline-block; 50 position: relative; 51 max-width: 80vw; 52 max-height: 80vh; 53 margin: 0; 54 z-index: 5; 55 opacity: 0; 56 transition: .5s ease-out; 57 -webkit-animation: show; 58 animation: show; 59 pointer-events: all; 60} 61 62.mid img.show { 63 opacity: 1; 64 -webkit-animation: show 1.3s ease-in-out; 65 animation: show 1.3s ease-in-out; 66}

試したこと

js

1_next() { 2 this.DOM.modal.classList.add('spinner'); 3 const thumbItemsOn = document.querySelectorAll('.modal-imgs.on'); 4 this.thumbCurrent = this._changeCount(1, this.thumbCurrent, thumbItemsOn.length); 5 this.thumbTarget = thumbItemsOn[this.thumbCurrent]; 6 this._modalShow(this.thumbTarget); // モーダル表示 7 } 8 _prev() { 9 this.DOM.modal.classList.add('spinner'); 10 const thumbItemsOn = document.querySelectorAll('.modal-imgs.on'); 11 this.thumbCurrent = this._changeCount(-1, this.thumbCurrent, thumbItemsOn.length); 12 this.thumbTarget = thumbItemsOn[this.thumbCurrent]; 13 this._modalShow(this.thumbTarget); // モーダル表示 14 }

ここがうまく動いていないのだとおもいます。
試しに、

js

1 _next() { 2 this.thumbCurrent = this._changeCount(1, this.thumbCurrent, this.DOM.thumbItems.length); 3 this.thumbTarget = this.DOM.thumbItems[this.thumbCurrent]; 4 this._modalShow(this.thumbTarget); // モーダル表示 5 } 6 _prev() { 7 this.thumbCurrent = this._changeCount(-1, this.thumbCurrent, this.DOM.thumbItems.length); 8 this.thumbTarget = this.DOM.thumbItems[this.thumbCurrent]; 9 this._modalShow(this.thumbTarget); // モーダル表示 10 }

としたところ、うまく +1, -1 されました。
また、コンソールに以下のようにすると、

js

1console.log(thumbItemsOn); 2console.log(thumbItemsOn.length);

画像はきちんと取れていました。

js

1this.thumbCurrent = this._changeCount(1, this.thumbCurrent, thumbItemsOn.length);

ここがうまく +1, -1 できていないのかと思うのですが、どう変更すればいいのか全くお手上げです。

どうかご助力をお願いできませんでしょうか。なにとぞよろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Firefox 最新版

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

// グループ化 の記述を _appearModal に移し、

js

1 _num() { 2 this.DOM.thumbItemsOn = document.querySelectorAll('.modal-imgs.on'); 3 this.listItem = Array.prototype.slice.call(this.DOM.thumbItemsOn, 0); 4 this.listItem.forEach(function ($listItem, i) { 5 $listItem.dataset.num = (i); 6 }); 7 this.$listItemNum = parseInt(this.thumbTarget.getAttribute('data-num')); 8 }

これを _appearModal, _next, _prev で実行することでできました。

投稿2022/01/08 10:04

erp

総合スコア46

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問