最終更新日:2020/02/05 原本2019/08/01

JS:JavaScriptでスワイプ処理をする

JS:JavaScriptでスワイプ処理をする JavaScript

ライブラリを使わずにJavaScript単体でスマホなどのスワイプ処理を実現する方法です。

サンプルはこちら。
スワイプ処理のサンプル

なお、基本的にパソコンのブラウザ上でスワイプ処理は確認できません。開発者モードがあるブラウザ(ChromeやFirefox等)を使うと良いでしょう。
パソコンのブラウザChrome上でスマホのタッチやスワイプを確認する場合は、以下の記事を参考にしてください。

Chromeの開発者モードでスマホのタッチ・スワイプをチェックする
Chromeの開発者モードはかなりWeb開発者にとっては便利です。 パソコンのChromeブラウザ上でスマホのタッチ・スワイプをチェックする方法です。

スワイプ判定の考え方

タッチ操作を判定する3つのイベント、touchstart, touchmove, touchendを効果的に組み合わせます。

例として左から右にスワイプするイメージです。
JS:JavaScriptでスワイプ処理をする

1.touchstart
 ユーザが最初にタッチした時点のxy座標を取得できる。(サンプルプログラムではxy座標をstartX, startYとして保存)
 これを利用して、スワイプ開始時点での座標を取得するために使う。

2.touchmove
 スワイプ中(指を動かしている最中)常に発生するイベント
 タッチしたまま動かしている状態の現在xy座標を取得可能。(サンプルでは、moveX, moveYとして保存)

3.touchend
 指を離したときに発生するイベント
 このイベント発生後に左右どちらにスワイプしたかの判定を行う。
 スワイプ距離が短い場合は何もしない。

左右のスワイプであれば、x座標だけ見れば事足ります。
左から右であれば、次の条件が成り立てば、右へのスワイプとみなします。

startX + スワイプ判定のための最低距離 > moveX

上記、startXやmoveXの座標はピクセル単位です。今回スワイプ判定のための最低距離は30ピクセルとしています。
都合に応じて適当に変えてください。

HTMLタグの特定の位置をスワイプ対象とする

全体をスワイプイベント対象とするのであれば、bodyタグにイベントを設定すればOKです。
今回は、以下のHTMLタグのページを使って、divタグのidがcontentsの部分のみをスワイプイベント対象としています。

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,user-scalable=yes">
    <title>JavaScriptでスワイプ処理をする</title>
    <link rel="stylesheet" href="style.css">
    <script src="main.js" type="text/javascript"></script>
</head>
<body>
    <header>
        <h1>JavaScriptでスワイプ処理をする</h1>
    </header>
     
    <div id="contents">
        <p id="number"></p>
        <p>左右にスワイプすると数値が増減します</p>
    </div>
 
    <footer><small>&copy; 2019 dianxnao.com</small></footer>
</body>
</html>

スワイプイベント設定部分

以下のサイトをほぼそのまま参考にさせて頂きました。
JavaScriptだけでスワイプ処理追加でカルーセル(スライダー)作成

関数setSwipeの中でtouchstart, touchmove, touchendの3つのイベントをスワイプイベント対象タグに設定しています。

主な変数の目的は以下の通りです。

変数目的
startXタッチ開始 x座標
startYタッチ開始 y座標
moveXスワイプ中の x座標
moveYスワイプ中の y座標
distスワイプを感知する最低距離(ピクセル単位)

スワイプイベント設定部分のソースコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * スワイプイベント設定
 */
function setSwipe(elem) {
    let t = document.querySelector(elem);
    let startX;        // タッチ開始 x座標
    let startY;        // タッチ開始 y座標
    let moveX;    // スワイプ中の x座標
    let moveY;    // スワイプ中の y座標
    let dist = 30;    // スワイプを感知する最低距離(ピクセル単位)
     
    // タッチ開始時: xy座標を取得
    t.addEventListener("touchstart", function(e) {
        e.preventDefault();
        startX = e.touches[0].pageX;
        startY = e.touches[0].pageY;
    });
     
    // スワイプ中: xy座標を取得
    t.addEventListener("touchmove", function(e) {
        e.preventDefault();
        moveX = e.changedTouches[0].pageX;
        moveY = e.changedTouches[0].pageY;
    });
     
    // タッチ終了時: スワイプした距離から左右どちらにスワイプしたかを判定する/距離が短い場合何もしない
    t.addEventListener("touchend", function(e) {
        if (startX > moveX && startX > moveX + dist) {        // 右から左にスワイプ
            // 右から左にスワイプした時の処理
        }
        else if (startX < moveX && startX + dist < moveX) {    // 左から右にスワイプ
            // 左から右にスワイプした時の処理
        }
    });
}

プログラム全体

今回のサンプルプログラム全体を示します。

index.html, main.js(JavaScript部分), style.cssに分かれています。

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,user-scalable=yes">
<title>JavaScriptでスワイプ処理をする</title>
<link rel="stylesheet" href="style.css">
<script src="main.js" type="text/javascript"></script>
</head>
<body>
<header>
<h1>JavaScriptでスワイプ処理をする</h1>
</header>
<div id="contents">
<p id="number"></p>
<p>左右にスワイプすると数値が増減します</p>
</div>
<footer><small>&copy; 2019 dianxnao.com</small></footer>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
/* main.js */
/*
* グローバル変数
*/
var no; // 数値格納用
var number; // 数値表示部分のDOM取得用
/*
* スワイプイベント設定
*/
function setSwipe(elem) {
let t = document.querySelector(elem);
let startX; // タッチ開始 x座標
let startY; // タッチ開始 y座標
let moveX; // スワイプ中の x座標
let moveY; // スワイプ中の y座標
let dist = 30; // スワイプを感知する最低距離(ピクセル単位)
// タッチ開始時: xy座標を取得
t.addEventListener("touchstart", function(e) {
e.preventDefault();
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
});
// スワイプ中: xy座標を取得
t.addEventListener("touchmove", function(e) {
e.preventDefault();
moveX = e.changedTouches[0].pageX;
moveY = e.changedTouches[0].pageY;
});
// タッチ終了時: スワイプした距離から左右どちらにスワイプしたかを判定する/距離が短い場合何もしない
t.addEventListener("touchend", function(e) {
if (startX > moveX && startX > moveX + dist) { // 右から左にスワイプ
previous();
}
else if (startX < moveX && startX + dist < moveX) { // 左から右にスワイプ
next();
}
});
}
/*
* 次の番号を表示
*/
function next(){
no ++;
setNumber();
}
/*
* 前の番号を表示
*/
function previous(){
no --;
setNumber();
}
/*
* 数値を画面に表示する
*/
function setNumber(){
number.innerHTML = no;
}
/*
* 起動時の処理
*/
window.addEventListener("load", function(){
// 数値表示部分のDOM取得
number = document.getElementById("number");
// 数値を画面に表示
no = 0;
setNumber();
// スワイプイベント設定
setSwipe("#contents");
});
view raw main.js hosted with ❤ by GitHub
/* style.css */
@charset "utf-8";
*{
margin: 0;
padding: 0;
}
body{
-webkit-text-size-adjust: none; /* iPhoneのSafariで左上が拡大されて表示される場合の対処 */
font-family: 'メイリオ', Helvetica;
font-size: 16pt;
width: 100%;
margin: 0 auto;
}
header{
padding: 1em;
background-color: teal;
}
header h1{
font-size: 16pt;
text-align: center;
color: white;
}
#contents{
background-color: white;
text-align: center;
}
#number{
padding: 1em 0;
font-family: Impact, Helvetica;
font-weight: 900;
font-size: 64pt;
}
p{
font-size: 12pt;
}
footer{
font-size: 0.8em;
padding: 1em;
text-align: center;
}
@media screen and (min-width: 768px) and (max-width: 1024px) {
/* タブレット用のcssを記述 */
header h1{
font-size: 20pt;
}
#contents{
background-color: white;
text-align: center;
}
#number{
padding: 1em 0;
font-family: Impact, Helvetica;
font-weight: 900;
font-size: 128pt;
}
p{
font-size: 18pt;
}
}
view raw style.css hosted with ❤ by GitHub

以上、JavaScriptでスワイプ処理をするでした。