Webで長押し処理を実装する


Reactなどを使っているWebアプリでたまにボタンを長押しできるようにしたいことがありました。
onMouseDownでフラグを立てて、onMouseUpでフラグを折るだけかと思ったらモバイルで色々困りました。

何が困ったか

Webなので長押しした先に画像があれば画像を保存メニューを出すし、テキストがあればコピーやペーストのメニューを出してくる。
それらを停止させねば必要なイベントにたどり着けませんでした。

iOSとデスクトップはCSSで制御できるという情報はすぐに見つかったけど、Androidは見つからず。
結論としてはonContextMenuを停止させる必要がありました。

今後他の人が同じような状況に陥らないように解決手段をおいておきます。

解決

JSとCSS、両方で対応することになります。

JS

使っていたのがReactなのでJSXを使っていますが、
VueでもVanilla JSでも同じことができると思います。

  <button
    onClick={this.onClickHandler}
    onMouseDown={this.onMouseDownHandler}
    onMouseUp={this.onMouseUpHandler}
    onTouchStart={this.onMouseDownHandler}
    onTouchEnd={this.onMouseUpHandler}
    onContextMenu={e => {
      e.preventDefault();
    }}
  >
    <img src="/images/caret-right.svg" alt="" />
  </button>

CSS

色々書いてますがメニューやコピー機能を停止させてます。
AndroidもCSSで対応できたら楽だったのに…。

.long-touch-button {
  user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -ms-user-select: none;
  -webkit-touch-callout: none;
}