スマートフォンからデスクトップ画面に至るまで、タッチスクリーンはますます多くのデバイスで利用できます。アプリは、直感的かつ美しい方法でタップに反応する必要があります。
タッチスクリーンは、スマートフォンから あります。ユーザーが UI を操作することを選択すると、アプリは 直感的な方法でタップに反応します
要素の状態に対応する
ウェブページ上の要素をタップまたはクリックしたことで、 サイトが実際にそれを検知したのか?
ユーザーによるパーツのタップや操作に応じて要素の色が変わる ウェブサイトが機能していることが基本的な安心感を与えてくれます。Google は、 ストレスが軽減され、テンポよくレスポンシブな印象になります。
DOM 要素は、デフォルト、フォーカス、ホバーの状態を継承できます。
定義できます。これらの状態ごとに UI を変更するには、スタイルを適用する必要があります。
以下に示すように、疑似クラス :hover
、:focus
、:active
に追加します。
.btn {
background-color: #4285f4;
}
.btn:hover {
background-color: #296cdb;
}
.btn:focus {
background-color: #0f52c1;
/* The outline parameter suppresses the border
color / outline when focused */
outline: 0;
}
.btn:active {
background-color: #0039a8;
}
![ボタンのさまざまな色を示す画像
州](https://web.dev/static/articles/add-touch-to-your-site/image/image-illustrating-differ-b45250d7caf18.png?hl=ja)
ほとんどのモバイル ブラウザでは、要素にマウスオーバーやフォーカスの状態が適用されます。 メッセージを表示できます。
設定するスタイルとそのスタイルがユーザーにどのように見えるかを慎重に検討する 顧客満足度の向上につながります
デフォルトのブラウザ スタイルを抑制する
さまざまな状態用のスタイルを追加すると、ほとんどのブラウザでは
ユーザーのタップ操作に応じて独自のスタイルを実装します。これは主に
モバイルデバイスが発売された当初は
:active
状態のスタイル設定が必要です。その結果、多くのブラウザが
ユーザーにフィードバックを提供します。
ほとんどのブラウザでは、outline
CSS プロパティを使用して、
要素にフォーカスが移ったときに通知を受け取れます。これを非表示にするには、次のコマンドを使用します。
.btn:focus {
outline: 0;
/* Add replacement focus styling here (i.e. border) */
}
Safari と Chrome でタップのハイライト表示の色が追加されている
-webkit-tap-highlight-color
CSS プロパティ:
/* Webkit / Chrome Specific CSS to remove tap
highlight color */
.btn {
-webkit-tap-highlight-color: transparent;
}
Windows Phone の Internet Explorer でも、動作は似ていますが、動作は抑制されています。 メタタグを使用:
<meta name="msapplication-tap-highlight" content="no">
Firefox では 2 つの副作用を処理する必要があります。
-moz-focus-inner
疑似クラス。アウトラインを追加する
タップ可能な要素がある場合は、border: 0
を設定することで削除できます。
Firefox で <button>
要素を使用している場合、グラデーションが表示されます。
適用されています。これは、background-image: none
を設定することで削除できます。
/* Firefox Specific CSS to remove button
differences and focus ring */
.btn {
background-image: none;
}
.btn::-moz-focus-inner {
border: 0;
}
ユーザー選択を無効にする
UI を作成する際は、ユーザー エクスペリエンスの 操作できるものの、デフォルトの動作を抑制したい場合は、 UI 上でマウスをドラッグして 長押ししてテキストを選択するか
これは user-select
CSS プロパティで行うことができますが、
コンテンツでこれを行うことは非常に不快感を与える可能性があります。
要素の中のテキストを選択する場合に、自動的に選択されるようになります。
そのため、慎重に慎重に使用してください。
/* Example: Disable selecting text on a paragraph element: */
p.disable-text-selection {
user-select: none;
}
カスタム ジェスチャーを実装する
サイトで使用するカスタムのインタラクションやジェスチャーについて 次の 2 つのトピックに留意してください
- すべてのブラウザをサポートする方法。
- フレームレートを高く保つ方法
この記事では、これらのトピックについて取り上げ、必要な API に関する すべてのブラウザへのヒットをサポートし これらのイベントの使い方を説明します 支援します
ジェスチャーで行う動作に応じて、 ユーザーに一度に 1 つの要素の操作を許可するか、または 複数の要素を同時に操作できます
この記事では、2 つの例を紹介します。いずれも、 高フレームレートを維持する方法を紹介します
![ドキュメントのタッチ操作の GIF の例](https://web.dev/static/articles/add-touch-to-your-site/image/example-gif-touch-docum-45703b8fb77df.gif?hl=ja)
最初の例では、ユーザーが 1 つの要素を操作できるようにします。この 1 つの要素にすべてのタッチイベントを渡すようにすることもできます。ただし、 要素自体で最初に開始された操作として認識されます。たとえば、 スワイプ可能な要素から指を離しても、要素をコントロールできます。
ユーザーに高い柔軟性をもたらすため便利ですが、 ユーザーが UI を操作する方法を制限します。
![要素のタップの GIF の例](https://web.dev/static/articles/add-touch-to-your-site/image/example-gif-touch-eleme-f47c2ec84c1a6.gif?hl=ja)
ただし、ユーザーが複数の要素を同時に操作することが予想される場合は、 時間(マルチタッチを使用)では、タップを特定の 要素です。
これはユーザーにとってはより柔軟性がありますが、情報を操作するロジックが複雑になります。 ユーザーエラーに対する耐障害性が低下します
イベント リスナーを追加する
Chrome(バージョン 55 以降)、Internet Explorer、Edge、
カスタム ジェスチャーの実装に推奨されるアプローチは、PointerEvents
です。
他のブラウザでは、TouchEvents
と MouseEvents
が適切な方法です。
PointerEvents
の優れた点は、複数のタイプの入力を結合できることです。
マウス、タッチ、ペンの各イベントをまとめて 1 つの
使用します。リッスンするイベントは、pointerdown
、pointermove
、
pointerup
と pointercancel
。
他のブラウザでの同等の機能は、touchstart
、touchmove
、
タッチイベント用の touchend
と touchcancel
。
マウス入力に対して、mousedown
を実装する必要があるのと同じ操作です。
mousemove
、mouseup
。
使用するイベントについてご不明な点がある場合は、 タップイベント、マウスイベント、ポインタ イベント。
これらのイベントを使用するには、DOM で addEventListener()
メソッドを呼び出す必要があります。
要素、イベントの名前、コールバック関数、ブール値です。
このブール値は、イベントをその前後にキャッチすべきかどうかを決定します
他の要素によって、他の要素を捕捉して解釈する機会が
できます。(true
は、他の要素よりもイベントを優先することを意味します)。
次に、インタラクションの開始をリッスンする例を示します。
// Check if pointer events are supported.
if (window.PointerEvent) {
// Add Pointer Event Listener
swipeFrontElement.addEventListener('pointerdown', this.handleGestureStart, true);
swipeFrontElement.addEventListener('pointermove', this.handleGestureMove, true);
swipeFrontElement.addEventListener('pointerup', this.handleGestureEnd, true);
swipeFrontElement.addEventListener('pointercancel', this.handleGestureEnd, true);
} else {
// Add Touch Listener
swipeFrontElement.addEventListener('touchstart', this.handleGestureStart, true);
swipeFrontElement.addEventListener('touchmove', this.handleGestureMove, true);
swipeFrontElement.addEventListener('touchend', this.handleGestureEnd, true);
swipeFrontElement.addEventListener('touchcancel', this.handleGestureEnd, true);
// Add Mouse Listener
swipeFrontElement.addEventListener('mousedown', this.handleGestureStart, true);
}
単一要素のインタラクションを処理する
上記の短いコード スニペットでは、開始イベント リスナーのみを追加しています。 使用できます。これは、マウスイベントによって イベント リスナーが追加されている要素の上にカーソルが移動したとき。
TouchEvents
は、場所にかかわらず、開始後に操作をトラッキングします
タップが発生し、PointerEvents
が接触位置に関係なくイベントをトラッキングします。
DOM 要素で setPointerCapture
が呼び出された後に行われます。
マウスの移動イベントと終了イベントについては、 リスナーをドキュメントに追加すると、 完了するまでカーソルをトラックし続けます。
実装の手順は以下のとおりです。
- すべての TouchEvent リスナーと PointerEvent リスナーを追加。MouseEvent はのみを追加します トリガーされます。
- 開始操作コールバック内で、マウスの移動イベントと終了イベントを
表示されます。この方法では、可否に関係なくすべてのマウスイベントが
元の要素でイベントが発生するかどうか。PointerEvent については、
元の要素で
setPointerCapture()
を呼び出す必要があります。 すべてのイベントを記録します。次に、操作の開始を処理します。 - 移動イベントを処理します。
- 終了イベントで、マウス移動リスナーと終了リスナーをドキュメントから削除する 操作を終了します。
以下は、移動を追加する handleGestureStart()
メソッドのスニペットです。
end イベントをドキュメントに追加します。
// Handle the start of gestures
this.handleGestureStart = function(evt) {
evt.preventDefault();
if(evt.touches && evt.touches.length > 1) {
return;
}
// Add the move and end listeners
if (window.PointerEvent) {
evt.target.setPointerCapture(evt.pointerId);
} else {
// Add Mouse Listeners
document.addEventListener('mousemove', this.handleGestureMove, true);
document.addEventListener('mouseup', this.handleGestureEnd, true);
}
initialTouchPos = getGesturePointFromEvent(evt);
swipeFrontElement.style.transition = 'initial';
}.bind(this);
追加する終了コールバックは handleGestureEnd()
で、これにより移動が削除されます。
end イベント リスナーをドキュメントから送り、ポインタのキャプチャを解放して、
呼び出すことができます。
// Handle end gestures
this.handleGestureEnd = function(evt) {
evt.preventDefault();
if (evt.touches && evt.touches.length > 0) {
return;
}
rafPending = false;
// Remove Event Listeners
if (window.PointerEvent) {
evt.target.releasePointerCapture(evt.pointerId);
} else {
// Remove Mouse Listeners
document.removeEventListener('mousemove', this.handleGestureMove, true);
document.removeEventListener('mouseup', this.handleGestureEnd, true);
}
updateSwipeRestPosition();
initialTouchPos = null;
}.bind(this);
このパターンに従ってドキュメントに移動イベントを追加すると、 ユーザーが要素の操作を開始し、そのジェスチャーを要素の外側に 要素がある場合、場所を問わずにマウスの動きを継続的に受け取ります。 イベントはドキュメントから受信されているため、ページ上にあります。
この図は、 移動や終了のイベントをドキュメントに移動できます。
![タッチイベントをドキュメントにバインドする
`touchstart`](https://web.dev/static/articles/add-touch-to-your-site/image/illustrating-binding-touc-3fd5e6cb19faa.gif?hl=ja)
タップに効率的に応答する
開始イベントと終了イベントの処理が完了したので、 応答します。
開始イベントと移動イベントのいずれについても、x
と y
を簡単に抽出できます。
便利です。
次の例では、イベントが TouchEvent
からのものかどうかを確認します。
targetTouches
が存在するかどうかを確認しています。存在する場合は
最初の接触から clientX
と clientY
。
イベントが PointerEvent
または MouseEvent
の場合は、clientX
を抽出し、
イベント自体から直接 clientY
を取得します。
function getGesturePointFromEvent(evt) {
var point = {};
if (evt.targetTouches) {
// Prefer Touch Events
point.x = evt.targetTouches[0].clientX;
point.y = evt.targetTouches[0].clientY;
} else {
// Either Mouse event or Pointer Event
point.x = evt.clientX;
point.y = evt.clientY;
}
return point;
}
TouchEvent
には、タッチデータを含む 3 つのリストがあります。
touches
: 画面上で現在行われているすべてのタップのリスト(指定の有無は問わない) 対象の DOM 要素。targetTouches
: イベントによって現在発生している DOM 要素上のタップのリスト あります。changedTouches
: イベントにつながった変更のタップのリスト 発生します。
ほとんどの場合、targetTouches
には必要なものがすべて揃っています。(
これらのリストについて詳しくは、タップリストをご覧ください)。
requestAnimationFrame を使用する
イベント コールバックはメインスレッドで呼び出されるため、次のように実行します。 イベントのコールバックにコードをできるだけ少なくして、 ジャンクを防止できます
requestAnimationFrame()
を使用すると、UI を更新することができます。
ブラウザがフレームを描画する前に表示されるようになり、
イベントコールバックで処理します
requestAnimationFrame()
をまだよくご存じない場合は、
こちらで詳細をご覧ください。
一般的な実装では、x
座標と y
座標を
開始イベントと移動イベント、移動イベント内のアニメーション フレームのリクエスト
呼び出すことができます。
このデモでは、最初の接触位置を handleGestureStart()
に保存します(initialTouchPos
を探してください)。
// Handle the start of gestures
this.handleGestureStart = function(evt) {
evt.preventDefault();
if (evt.touches && evt.touches.length > 1) {
return;
}
// Add the move and end listeners
if (window.PointerEvent) {
evt.target.setPointerCapture(evt.pointerId);
} else {
// Add Mouse Listeners
document.addEventListener('mousemove', this.handleGestureMove, true);
document.addEventListener('mouseup', this.handleGestureEnd, true);
}
initialTouchPos = getGesturePointFromEvent(evt);
swipeFrontElement.style.transition = 'initial';
}.bind(this);
handleGestureMove()
メソッドはイベントの位置を保存します。
リクエストの前に、必要に応じてアニメーション フレームを
onAnimFrame()
関数をコールバックとして使用します。
this.handleGestureMove = function (evt) {
evt.preventDefault();
if (!initialTouchPos) {
return;
}
lastTouchPos = getGesturePointFromEvent(evt);
if (rafPending) {
return;
}
rafPending = true;
window.requestAnimFrame(onAnimFrame);
}.bind(this);
onAnimFrame
値は、呼び出されると UI を変更する関数です。
移動しますこの関数を requestAnimationFrame()
に渡すと、
ページを更新する直前にこの関数を呼び出すようブラウザに指示します
(ページの変更内容を描画するなど)。
handleGestureMove()
コールバックでは、最初に rafPending
が false かどうかを確認します。
onAnimFrame()
が requestAnimationFrame()
によって呼び出されたかどうかを示します。
直近の移動イベント以降ですつまり、requestAnimationFrame()
は 1 つだけです。
常に待機している状態です
onAnimFrame()
コールバックが実行されると、任意のイベントに変換が設定されます。
rafPending
を false
に更新する前に移動する要素を指定して、
新しいアニメーション フレームがリクエストされます。
function onAnimFrame() {
if (!rafPending) {
return;
}
var differenceInX = initialTouchPos.x - lastTouchPos.x;
var newXTransform = (currentXPosition - differenceInX)+'px';
var transformStyle = 'translateX('+newXTransform+')';
swipeFrontElement.style.webkitTransform = transformStyle;
swipeFrontElement.style.MozTransform = transformStyle;
swipeFrontElement.style.msTransform = transformStyle;
swipeFrontElement.style.transform = transformStyle;
rafPending = false;
}
タップ操作でジェスチャーを制御する
CSS プロパティ touch-action
を使用すると、デフォルトのタップを制御できます。
制御できます。この例では、touch-action: none
を使用して以下を行います。
ブラウザがユーザーの操作を一切行えないようにし、タップすることで、
すべてのタッチイベントをインターセプトします
/* Pass all touches to javascript: */
button.custom-touch-logic {
touch-action: none;
}
touch-action: none
を使用すると、すべての脅威を防ぐことができるため、核となるオプションである
変更できます。多くの場合、いずれかの方法は
以下の方法が適しています。
touch-action
を使用すると、ブラウザで実装された操作を無効にできます。
たとえば、IE10 以降ではダブルタップによるズーム操作がサポートされています。ルールの
manipulation
件中 touch-action
件、デフォルトのダブルタップを無効にしています
確認します。
これにより、ダブルタップ ジェスチャーを自分で実装できます。
よく使用される touch-action
値は次のとおりです。
古いバージョンの IE のサポート
IE10 をサポートする場合、
PointerEvents
。
PointerEvents
がサポートされているかどうかを確認するには、通常
window.PointerEvent
ですが、IE10 では、
window.navigator.msPointerEnabled
。
ベンダー プレフィックス付きのイベント名は、'MSPointerDown'
、'MSPointerUp'
、および
'MSPointerMove'
。
下の例は、サポートの有無を確認して切り替える方法を示しています イベント名を定義します。
var pointerDownName = 'pointerdown';
var pointerUpName = 'pointerup';
var pointerMoveName = 'pointermove';
if (window.navigator.msPointerEnabled) {
pointerDownName = 'MSPointerDown';
pointerUpName = 'MSPointerUp';
pointerMoveName = 'MSPointerMove';
}
// Simple way to check if some form of pointerevents is enabled or not
window.PointerEventsSupport = false;
if (window.PointerEvent || window.navigator.msPointerEnabled) {
window.PointerEventsSupport = true;
}
詳しくは、 Microsoft。
リファレンス
タッチ状態の疑似クラス
確定的なタッチイベント リファレンスはこちらをご覧ください。 W3C タッチイベント。
タッチイベント、マウスイベント、ポインタ イベント
これらのイベントは、新しい操作を アプリケーション:
タッチリスト
各タッチイベントには、次の 3 つのリスト属性が含まれます。
iOS でアクティブ状態のサポートを有効にする
残念ながら、iOS の Safari はデフォルトでは「アクティブ」状態を適用せず、
動作させるには、touchstart
イベント リスナーをドキュメントに追加する必要があります。
body または各要素に対して指定できます。
これは、iOS デバイスでのみ実行されるように、ユーザー エージェント テストの背後で行う必要があります。
ボディにタッチ開始を追加すると、すべての要素に適用できるというメリットがあります。 ただし、ページをスクロールするときにパフォーマンスの問題が発生する可能性があります。
window.onload = function() {
if (/iP(hone|ad)/.test(window.navigator.userAgent)) {
document.body.addEventListener('touchstart', function() {}, false);
}
};
または、タップ開始リスナーをすべての操作可能な パフォーマンス上の懸念が軽減されます。
window.onload = function() {
if (/iP(hone|ad)/.test(window.navigator.userAgent)) {
var elements = document.querySelectorAll('button');
var emptyFunction = function() {};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('touchstart', emptyFunction, false);
}
}
};