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

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

新規登録して質問してみよう
ただいま回答率
85.47%
スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

1回答

338閲覧

タッチデバイスでのスクロール判定

kaz001

総合スコア1

スクロール

スクロールとは、ディスプレイスクリーン上において連続的にコンテンツが滑っていくことを指します。

JavaScript

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

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

1クリップ

投稿2023/10/30 10:11

編集2023/11/01 09:51

お世話になります。
はじめて質問させていただきます。
javascriptについては、WEB上のサンプルを使って組み合わせたり、検索でこちらにたどり着いて参考にさせていただいたりと、
自作まではできないレベルの者です。

実現したいこと

今更なのですが、、jqueryで動きを付けたページを作っておりまして、
タッチデバイスでのスクロールの動作を解決したくアドバイスをいただけたらと思います。
(プラグインは使っていません)


ソースコード(もしくはCode Pen)を確認いただくと、
contents3まではマウスホイール操作でコンテンツごとにスクロールするようになっています。
(わかりやすい例ですとScrollify.jsのような動作)
contents4、contents5、contents6では通常スクロールします。ページトップから下方向へ順に移動する場合は、PCでもタッチデバイスでも正常に動作しています。

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

しかし、タッチデバイスで、ページトップ(contents1)から順に下方向へ移動していき、contents4、contents5、contents6のどれかに達してから上方向へスクロールしていき、
再度ページトップ(contents1)から下方向へスクロールしようとすると、contents2へ移動せず、contents5や、contents6へ移動してしまいます。

タッチスクロールが有効になる条件と無効になる条件(が問題だと思っています)が、
それをどのように組み合わせればよいかわかりかねております。

ここからの修正が大きなものになってしまうのであれば
自分にはそこまでの対応がもう難しいと思っております。
厚かましいかとは思いますが修正案をコードをご教示いただければ大変助かります。

該当のソースコード

Code Pen
https://codepen.io/mphzyvet-the-sans/pen/vYbGLbq

<style> .section{ height:100vh; } .contents1{ background:#ff8080; } .contents2{ background:#ff80c0; } .contents3{ background:#8080ff; } .contents4{ background:#c0c0c0; height:800px; } .contents5{ background:#70df00; height:700px; } .contents6{ background:#5badff; height:600px; } </style> <div class="section contents1"> コンテンツ1 </div> <div class="section contents2"> コンテンツ2 </div> <div class="section contents3"> コンテンツ3 </div> <div class="section contents4"> コンテンツ4(通常スクロール) </div> <div class="section contents5"> コンテンツ5(通常スクロール) </div> <div class="section contents6"> コンテンツ6(通常スクロール) </div> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(document).ready(function () { var sections = $(".section"); var isAnimating = false; var numSections = sections.length; var currentSection = 0; var scrollEnabled = true; var touchScrollEnabled = true; var startY = 0; var endY = 0; var scrollThreshold = 15; // スクロールとタッチスクロールのしきい値(px); function scrollToSection(sectionIndex) { if (sectionIndex < 0) sectionIndex = 0; if (sectionIndex >= numSections) sectionIndex = numSections - 1; isAnimating = true; $("html, body").animate( { scrollTop: sections.eq(sectionIndex).offset().top, }, 2000, function () { isAnimating = false; } ); currentSection = sectionIndex; } // ホイールスクロールのイベントハンドラを定義 function handleWheelScroll(e) { if (isAnimating || !scrollEnabled) return; e.preventDefault(); if (e.originalEvent.deltaY > scrollThreshold) { if (currentSection < numSections - 1) { scrollToSection(currentSection + 1); } } else if (e.originalEvent.deltaY < -scrollThreshold) { if (currentSection > 0) { scrollToSection(currentSection - 1); } } } // ホイールスクロールのイベントを最初に有効化 $(window).on("wheel", handleWheelScroll); // タッチデバイス用にタッチイベントを処理 var touchStartY = 0; $(document).on("touchstart", function (e) { touchStartY = e.originalEvent.touches[0].clientY; }); $(document).on("touchmove", function (e) { if (isAnimating || !touchScrollEnabled) return; var deltaY = e.originalEvent.touches[0].clientY - touchStartY; if (deltaY > scrollThreshold) { if (currentSection > 0) { scrollToSection(currentSection - 1); } } else if (deltaY < -scrollThreshold) { if (currentSection < numSections - 1) { scrollToSection(currentSection + 1); } } }); // スクロールがcontents3を超えたらホイールスクロールとタッチスクロールのイベントを無効化 $(window).on("scroll", function () { var windowScrollTop = $(window).scrollTop(); var contents3Top = sections.eq(2).offset().top; if (windowScrollTop > contents3Top) { scrollEnabled = false; touchScrollEnabled = false; } else { scrollEnabled = true; touchScrollEnabled = true; } }); scrollToSection(0); }); </script>

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

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

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

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

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

Lhankor_Mhy

2023/11/01 00:45

ご提示のPenをiOSデバイスで拝見しましたが、『contents2へ移動せず、contents5や、contents6へ移動』という現象を確認することができませんでした。
kaz001

2023/11/01 02:17

ご指摘ありがとうございました。 penのhtmlソースコードにクラスの付け忘れがあり現象を確認できなくなっており修正いたしました。 よろしければ今一度確認いただければと思います。
kaz001

2023/11/01 09:58

ありがとうございます。
guest

回答1

0

ベストアンサー

currentSectionが更新されるのはscrollToSection()でだけなので、touchScrollEnabledのフラグが下りている時にセクションを通過しても更新されないのが問題のように思います。
currentSectionの管理をセクションスクロールと切り離してみてはどうでしょうか。


ご希望とは違うかもしれませんが、IntersectionObserver と scroll-snap を使って似たようなものを書いてみました。

html

1<!DOCTYPE html> 2<html lang="en"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>Document</title> 8 <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/destyle.css@3.0.0/destyle.min.css"> 9 <style> 10 .section { 11 height: 100vh; 12 } 13 14 .contents1 { 15 background: #ff8080; 16 } 17 18 .contents2 { 19 background: #ff80c0; 20 } 21 22 .contents3 { 23 background: #8080ff; 24 } 25 26 .contents4 { 27 background: #c0c0c0; 28 height: 800px; 29 } 30 31 .contents5 { 32 background: #70df00; 33 height: 700px; 34 } 35 36 .contents6 { 37 background: #5badff; 38 height: 600px; 39 } 40 41 html.scrollSnap { 42 scroll-snap-type: y mandatory; 43 } 44 45 .section { 46 scroll-snap-align: start; 47 } 48 </style> 49</head> 50 51<body> 52 <div class="section contents1"> 53 コンテンツ1 54 </div> 55 <div class="section contents2"> 56 コンテンツ2 57 </div> 58 <div class="section contents3"> 59 コンテンツ3 60 </div> 61 <div class="scrollNotSnap"> 62 <div class="section contents4"> 63 コンテンツ4(通常スクロール) 64 </div> 65 <div class="section contents5"> 66 コンテンツ5(通常スクロール) 67 </div> 68 <div class="section contents6"> 69 コンテンツ6(通常スクロール) 70 </div> 71 </div> 72 73 <script> 74 const callback = (entries, observer) => { 75 entries.forEach((entry) => { 76 if (entry.isIntersecting) { 77 document.documentElement.classList.remove('scrollSnap') 78 } else { 79 document.documentElement.classList.add('scrollSnap') 80 } 81 }); 82 }; 83 const options = { 84 root: document, 85 rootMargin: '-99% 0px -1%', 86 threshold: 0 87 } 88 89 const observer = new IntersectionObserver(callback, options); 90 document.querySelectorAll('.scrollNotSnap').forEach(el => observer.observe(el)) 91 92 </script> 93</body> 94 95</html>

投稿2023/11/01 08:21

編集2023/11/02 01:19
Lhankor_Mhy

総合スコア36134

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

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

kaz001

2023/11/01 09:58

Lhankor_Mhy様 ご回答感謝いたします。 currentSection の管理をセクションスクロールと切り離すということは、根本的にソースコードの書き換えが必要ということですね・・ 何としても動かしたいと思っております。 私にはかなり難易度が高いので先が見えないですが・・
kaz001

2023/11/02 14:40

お返事遅くなり申し訳ございません。 確認いたしました。 ありがとうございます! 基本的な動作は実現されていて感動しています。 考えつかないアイデアをいただきましてありがとうございます。 元のソースコードで実現不可能な場合は いただきました方法をもとに進めさせていただきたいと思います。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問