【JavaScript】QRコードを読み取って、特定のモーダルウィンドウを表示する
2024年06月17日
WEBサイト制作
- #HTML
- #css
- #JavaScript
- #tips
こんにちは!
上毛印刷WEB制作担当のソーヤです。
今回は以前の記事の続きになります。
◆過去記事はコチラ(【JavaScript】クリックしたらモーダルウィンドウで詳細情報を表示する)
ある日、QRコードを読み取って特定のモーダルウィンドウを表示することはできないか?
という要望を受けました。
というわけで実装!
お手持ちのスマートフォンで、それぞれのQRコードを読み取ってみてください!
QRコードに対応したモーダルウィンドウが表示されていると思います。
ちなみにPCの方はこちら↓↓↓
◆ネコ(別ウィンドウで開きます)
◆イヌ(別ウィンドウで開きます)
◆鰤(別ウィンドウで開きます)
◆蕎麦(別ウィンドウで開きます)
◆ビール(別ウィンドウで開きます)
◆亀の天国(別ウィンドウで開きます)
◆スバメの巣(別ウィンドウで開きます)
HTML例
<div class="modal-wrap">
<div class="modalList-item js-item" id="cat">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/IMG_1669.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/IMG_1669.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> ネコかわいいですね。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="dog">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/dog.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/dog.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> イヌかわいいですね。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="yellowtail">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/buri.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/buri.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> 鰤うまそうですね。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="soba">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/soba.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/soba.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> 蕎麦の季節になりました。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="beer">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/god.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/god.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> アルコール度数高めです。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="turtle">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/kame.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/kame.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br> 亀の楽園。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modalList-item js-item" id="swallow">
<a href="javascript:void(0);" class="js-modal">
<div class="modalButton-img">
<img src="/cp/wp/wp-content/uploads/2024/06/tsubame.jpg" alt="">
</div>
<h3>
ここをクリックしてください。<br>
</h3>
</a>
<div class="modal">
<div class="modal-container">
<div class="modal-inner">
<div class="modal-contents">
<div class="modalInner-img">
<img src="/cp/wp/wp-content/uploads/2024/06/tsubame.jpg" alt="">
</div>
<div class="modalInner-item">
<p>モーダルウィンドウが開きました。<br>ここにコンテンツを入れてください。<br>ツバメを大事にしましょう。</p>
</div>
<div class="modal-button-wrap">
<button class="modal-button" type="button">閉じる</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
CSS例
.modal-wrap{
display: flex;
flex-wrap: wrap;
}
.modalList-item {
width: 300px;
margin: 0 0 30px 0;
padding: 0 8px;
}
.modalList-item .modal-contents {
max-width: 700px;
}
.modalList-item a {
display: block;
position: relative;
width: 100%;
height: 100%;
color: #333;
background-color: #fff;
box-shadow: 9px 8px 10px rgba(0, 0, 0, 0.2), 0 0 5px 0 #ffffff, -4px 0 5px 0 #ffffff, -4px -6px 15px #ffffff;
transition: .4s ease;
}
.modalList-item a:hover {
transform: scale(1.01);
box-shadow: 15px 14px 17px rgba(0, 0, 0, 0.2), 0 0 8px 0 #ffffff, -7px 0 8px 0 #ffffff, -7px -10px 26px #ffffff;
opacity: 0.7;
}
.modalList-item a:hover::after {
transform: translateX(10px);
}
.modalList-item h3 {
padding: 20px 10px 40px;
font-size: 22px;
font-weight: bold;
line-height: 1.2;
}
.modalList-item h3 span {
font-size: 14px;
}
.modalButton-img {
position: relative;
}
.modalButton-img img {
width: 100%;
max-width: 100%;
margin: 0 0 20px;
vertical-align: top;
}
.modalInner-img {
position: relative;
margin: 0 0 20px;
}
.modalInner-img img {
width: 100%;
max-width: 100%;
margin: 0 0 20px;
vertical-align: top;
}
.modalInner-img + h3 {
display: flex;
-webkit-box-align: end;
-webkit-align-items: flex-end;
-ms-flex-align: end;
align-items: flex-end;
padding: 0 10px 20px 0;
}
.modalList-item .modal-contents {
max-width: 700px;
}
.modal {
display: none;
z-index: 9999;
position: fixed;
top: -10px;
right: 0;
bottom: -10px;
left: 0;
overflow: hidden;
overflow-y: auto;
backface-visibility: hidden;
background-color: rgba(0, 0, 0, 0.45);
}
.modal-container {
display: table;
width: 100%;
height: 100%;
padding: 10px 0;
}
.modal-inner {
display: table-cell;
padding: 2.7em 2em;
vertical-align: middle;
}
.modal-contents {
position: relative;
max-width: 1300px;
margin: 0 auto;
padding: 10px;
background-color: #fff;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
text-justify: inter-ideograph;
}
.modal-button-wrap {
position: absolute;
top: 20px;
right: 20px;
}
.modal-button {
appearance: none;
display: inline-block;
position: relative;
width: 24px;
height: 24px;
border: none;
outline: none;
background: transparent;
line-height: 1;
text-indent: -9999px;
vertical-align: middle;
cursor: pointer;
}
.modal-button::before {
position: absolute;
top: -71px;
left: 7px;
width: 30px;
height: 30px;
border: 5px solid #fff;
border-radius: 50%;
background-color: #fff;
background-image: url(/cp/wp/wp-content/uploads/2024/06/modal_close.png);
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
content: '';
cursor: pointer;
}
JavaScript例
document.addEventListener('DOMContentLoaded', function() {
var windowEl = window,
html = document.documentElement,
body = document.body,
scrollbarWidth = window.innerWidth - document.body.scrollWidth,
touchStartY;
windowEl.addEventListener('touchstart', function(event) {
touchStartY = event.changedTouches[0].screenY;
});
document.querySelectorAll('.js-modal').forEach(function(modalTrigger) {
modalTrigger.addEventListener('click', function() {
var overlay = modalTrigger.nextElementSibling;
windowEl.addEventListener('touchmove', touchMoveHandler, { passive: false });
html.style.overflow = 'hidden';
body.style.overflow = 'hidden';
if (scrollbarWidth) {
html.style.paddingRight = scrollbarWidth + 'px';
}
overlay.style.display = 'block';
overlay.style.opacity = 1;
overlay.style.transition = 'opacity 0.3s';
var touchMoveHandler = function(event) {
var currentY = event.changedTouches[0].screenY,
height = overlay.offsetHeight,
isTop = touchStartY <= currentY && overlay.scrollTop === 0, isBottom = touchStartY >= currentY && overlay.scrollHeight - overlay.scrollTop === height;
if (isTop || isBottom) {
event.preventDefault();
}
};
var closeModal = function() {
body.style.removeProperty('overflow');
html.style.removeProperty('overflow');
html.style.removeProperty('padding-right');
windowEl.removeEventListener('touchmove', touchMoveHandler);
overlay.style.transition = 'opacity 0.3s';
overlay.style.opacity = 0;
setTimeout(function() {
overlay.scrollTop = 0;
overlay.style.display = 'none';
overlay.style.removeProperty('style');
html.style.removeProperty('style');
}, 300);
};
overlay.addEventListener('click', function(event) {
if (!event.target.closest('.modal-contents')) {
closeModal();
}
});
overlay.querySelector('.modal-button').addEventListener('click', function() {
closeModal();
});
});
});
});
document.querySelectorAll('.modal').forEach(function(modalMatter) {
modalMatter.addEventListener('click', function() {
if (!event.target.closest('.modal-contents')) {
setTimeout(function() {
modalMatter.scrollTop = 0;
modalMatter.style.display = 'none';
modalMatter.style.removeProperty('style');
}, 300);
}
});
modalMatter.querySelector('.modal-button').addEventListener('click', function() {
setTimeout(function() {
modalMatter.scrollTop = 0;
modalMatter.style.display = 'none';
modalMatter.style.removeProperty('style');
}, 300);
});
});
function onPageLoad() {
var urlHash = location.hash;
if (window.name !== "any") {
location.reload();
window.name = "any";
} else {
window.name = "";
}
switch (urlHash) {
case '#cat':
document.getElementById('cat').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#dog':
document.getElementById('dog').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#yellowtail':
document.getElementById('yellowtail').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#soba':
document.getElementById('soba').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#beer':
document.getElementById('beer').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#turtle':
document.getElementById('turtle').firstElementChild.nextElementSibling.style.display = "block";
break;
case '#swallow':
document.getElementById('swallow').firstElementChild.nextElementSibling.style.display = "block";
break;
default:
break;
}
}
window.addEventListener('load', onPageLoad);
window.addEventListener('pageshow', function(event) {
if (event.persisted) {
onPageLoad();
}
});
history.replaceState(null, document.getElementsByTagName('title')[0].innerHTML, null);
window.addEventListener('popstate', function(e) {
onPageLoad();
});
Androidだと問題なく動くんですが、iPhoneだとうまくいかず結構手こずりました・・・
まとめ
今回もjQueryではなく、Vanilla.jsで実装してみました。
コピペしてガンガン使ってください!
この記事に対するご意見・ご感想・ご質問等ありましたら、
ぜひ下記フォームにてお送りください。