- 最終更新日
- 記事公開日
スクロールを途中で止めて(指定した要素の位置)、YES・NOの選択画面を表示する【jQuery】
スクロールの途中に「YES」or「NO」の選択画面を表示したいの。
その選択肢によって、表示する内容を変えたいんだけど、どうしたらいい?
スクロールの位置を検知して、指定した要素のところに来たら、モーダルを表示するのが良いと思います。
今回は、jQueryとCSSを使った方法を紹介します。
実装する際に注意すべきことが2つあります。
1.YES/NOの選択が終わるまで、スクロールが動かないように画面を固定する必要があります。
2.スマホ(特にiPhone)は指でスクロールした際に勢いがあると、スクロールのストップ位置を超えた場所で止まってしまいます。強制的にポジションを戻す調整が必要です。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex">
<title>DEMO</title>
<!-- jQuery -->
<script src='js/jquery.min.js'></script>
<script>
$(function() {
var flag = 0;
// 画面の高さを取得
var window_height = $(window).height();
// 最初はモーダルを隠しておく
$('#modal').hide();
// スクロールしたときに実行
$(window).on("scroll", function() {
// スクロールの座標を取得
var scroll = $(window).scrollTop();
// スクロールを止める要素の座標
var stop = $("#modal_point").offset().top;
// 画面半分くらいで検知するように微調整
var adj = window_height / 2;
// 選択画面の位置までスクロールがきたらモーダルを表示
if(scroll + window_height > stop + adj) {
// 一度選択したら、スクロールで戻ってもモーダルを表示しない
if (flag == 0) {
flag = 1;
// スクロールバーを非表示にする
$('body').css('overflow-y', 'hidden');
// ゆっくりフェードインしながらモーダルを表示
$("#modal").fadeIn("slow");
}
}
// デバッグ用(座標ステータスの表示)
var scroll_y = scroll + window_height;
var stop_y = stop + adj;
$('#status').html('スクロールのY軸/bottom座標:' + scroll_y + '<br>' + 'モーダル表示のY軸/top座標:'+ stop_y);
});
// YESをクリック
$("#yes_btn").click(function () {
// スクロールバーを表示する
$('body').css('overflow-y','auto');
// モーダルを隠す
$('#modal').hide();
// 選択後の内容を隠しておいたマスクを非表示にする
$('.mask').css('display','none');
// NOが選択された場合の内容を非表示にしておく
$('#no').css('display','none');
// 内容の表示位置まで自動スクロール
$("html").animate({scrollTop: $('#scroll_point').offset().top});
});
// NOボタンをクリック
$("#no_btn").click(function () {
// スクロールバーを表示する
$('body').css('overflow-y','auto');
// モーダルを隠す
$('#modal').hide();
// 選択後の内容を隠しておいたマスクを非表示にする
$('.mask').css('display','none');
// YESが選択された場合の内容を非表示にしておく
$('#yes').css('display','none');
// 内容の表示位置まで自動スクロール
$("html").animate({scrollTop: $('#scroll_point').offset().top});
});
});
</script>
<style>
* {
margin:0;
padding:0;
}
#container {
text-align:center;
}
.block1 {
background:#ffa595;
height:100vh;
}
.block2 {
background:#faffc7;
height:100vh;
}
.block3 {
background:#a3ffe0;
height:100vh;
}
.block4 {
background:#a8d9ff;
height:100vh;
}
#modal {
display:none;
position:fixed;
top:0;
left:0;
width:100%;
height:100%;
z-index:10;
background:rgba(0,0,0,0.8);
}
#modal_inner {
position:absolute;
top:50%;
left:50%;
transform:translateY(-50%) translateX(-50%);
background:#fff;
padding:2em;
width:60%;
}
#choice_btn {
display:flex;
text-align:center;
justify-content: space-between;
}
#choice_btn div {
flex-basis:48%;
color:#fff;
font-weight:bold;
font-size:2em;
padding:2em 0;
}
#yes_btn {
background:#da0000;
}
#no_btn {
background:#1e00d7;
}
#choice {
position:relative;
height:100%;
}
.mask {
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
background:#fff;
z-index:6;
}
#yes ,
#no {
position:absolute;
top:50%;
left:50%;
transform:translateY(-50%) translateX(-50%);
}
#yes span ,
#no span {
display:block;
font-size:5em;
font-weight:bold;
}
#yes span {
color:red;
}
#no span {
color:blue;
}
.retry {
margin:3em;
}
.retry a {
text-decoration:none;
}
#status {
position:fixed;
top:1em;
right:1em;
text-align:left;
}
</style>
</head>
<body>
<div id="container">
<div class="block1"></div>
<div class="block2"></div>
<!-- 選択肢が表示されるポイント -->
<div class="block3" id="modal_point">
<div id="modal">
<div id="modal_inner">
<div id="choice_btn">
<div id="yes_btn">YES</div>
<div id="no_btn">NO</div>
</div>
</div>
</div>
</div>
<!-- スクロールバーの移動ポイント -->
<div class="block4" id="scroll_point">
<div id="choice">
<div class="mask"></div>
<div id="yes">
<span>YES</span>が選択されました。
</div>
<div id="no">
<span>NO</span>が選択されました。
</div>
</div>
</div>
<div class="retry">
<a href="scroll_stop.html">もう一度最初から</a>
</div>
<div id="status"></div>
</div>
</body>
</html>