React DnDでスマホでもドラッグアンドドロップ
React DnDでスマホでもドラッグアンドドロップ:
Enigmo Advent Calendar 2018の12日目の記事です。
注意: この記事のサンプルコードで使われている各ライブラリのバージョンは下記になります。
Reactでドラッグアンドドロップでの並び替えを実装する際によく使われるのがReact DnDというライブラリです。
このライブラリではHTML5のDrag and Drop APIを利用してドラッグアンドドロップを実現していますが、このAPI自体がスマートフォンなどのタッチデバイスには対応しておらず、スマホでそのままドラッグアンドドロップを実装することができません。
React DnDを使う際、ドラッグアンドドロップしたいコンポーネントを
この
前述した通りタッチデバイスの場合はこの
これだけでタッチデバイス対応ができました。
しかし、
HTML5Backendではちゃんとプレビューされている
TouchBackendではプレビューされていない!
※ ChromeのDevToolsでスマートフォンをエミュレートして録画しているためマウスカーソルが表示されています。
React DnD にはDragLayerという、ドラッグ時のプレビュー表示をカスタマイズできるAPIがあります。
これを使うことでタッチデバイスでもいい感じのプレビューを表示することができます。
利用側のサンプルコードは以下です。
また、
同一画面の他のコンポーネントでもドラッグアンドドロップするために、
プレビューがタッチした部分に追従するように
スマホでもプレビューができた!
※ ChromeのDevToolsでスマートフォンをエミュレートして録画しているためマウスカーソルが表示されています。
スマートフォンなどのタッチデバイスでHTML5のようなドラッグアンドドロップを実現する方法を解説しました。
実際に実装する際は、TouchBackendのリポジトリ に完全に動作するサンプルがあるのでそちらも参考にしてみてください。
http://react-dnd.github.io/react-dnd/about
https://github.com/yahoo/react-dnd-touch-backend
Enigmo Advent Calendar 2018の12日目の記事です。
注意: この記事のサンプルコードで使われている各ライブラリのバージョンは下記になります。
react 16.4.0 react-dnd 4.0.2 react-dnd-html5-backend 4.0.2 react-dnd-touch-backend 0.5.1
React DnD
Reactでドラッグアンドドロップでの並び替えを実装する際によく使われるのがReact DnDというライブラリです。このライブラリではHTML5のDrag and Drop APIを利用してドラッグアンドドロップを実現していますが、このAPI自体がスマートフォンなどのタッチデバイスには対応しておらず、スマホでそのままドラッグアンドドロップを実装することができません。
TouchBackend
React DnDを使う際、ドラッグアンドドロップしたいコンポーネントを DragDropContext という HOC(Higer Order Component) に渡します。この
DragDropContext の最初の引数に渡すのは通常、 HTML5Backend というバックエンドモジュールです。import HTML5Backend from 'react-dnd-html5-backend'
import { DragDropContext } from 'react-dnd'
class YourApp {
/* ... */
}
export default DragDropContext(HTML5Backend)(YourApp)
HTML5Backend は使えません。 しかしタッチデバイス対応した TouchBackendというものがあるのでそちらを使います。import HTML5Backend from 'react-dnd-html5-backend'
import TouchBackend from 'react-dnd-touch-backend';
import { DragDropContext } from 'react-dnd'
const isTouchDevice = () => {
/* タッチデバイス判定 */
}
class YourApp {
/* ... */
}
export default DragDropContext(isTouchDevice() ? TouchBackend : HTML5Backend)(YourApp)
しかし、
HTML5Backend のようにいい感じにプレビューされません。HTML5Backendではちゃんとプレビューされている
TouchBackendではプレビューされていない!
※ ChromeのDevToolsでスマートフォンをエミュレートして録画しているためマウスカーソルが表示されています。
DragLayer
React DnD にはDragLayerという、ドラッグ時のプレビュー表示をカスタマイズできるAPIがあります。これを使うことでタッチデバイスでもいい感じのプレビューを表示することができます。
利用側のサンプルコードは以下です。
import React from 'react'
import DragLayer from 'react-dnd/lib/DragLayer'
import TouchBackend from 'react-dnd-touch-backend';
import { DragDropContext } from 'react-dnd'
function collect(monitor) {
const item = monitor.getItem()
return {
currentOffset: monitor.getSourceClientOffset(),
previewProps: item && item.previewProps,
isDragging:
monitor.isDragging() && monitor.getItemType() === 'IMAGE'
}
}
function getItemStyles(currentOffset) {
if (!currentOffset) {
return {
display: 'none'
}
}
const x = currentOffset.x
const y = currentOffset.y
const transform = `translate(${x}px, ${y}px) scale(1.05)`
return {
WebkitTransform: transform,
transform: transform,
}
}
class PreviewComponent extends React.Component {
render() {
const { isDragging, previewProps, currentOffset } = this.props
if (!isDragging) {
return null
}
return (
<div style={getItemStyles(currentOffset)}>
{/*...*/}
</div>
)
}
}
const DragPreview = DragLayer(collect)(PreviewComponent)
class YourApp {
render() {
return (
<div>
{/* ... */}
<DragPreview />
</div>
)
}
}
export default DragDropContext(TouchBackend)(YourApp)
かんたんに解説
DragLayer の引数 collect 関数ではDragLayerMonitorのオブジェクトが渡されます。monitor.getItem() で DragSource にアクセスすることができ、 任意で渡した props(今回の場合は previewProps という名前で渡していますが、どんな名前でも渡すことができます) にアクセスできます。また、
monitor.isDragging で実際にドラッグされているか判定することができます。同一画面の他のコンポーネントでもドラッグアンドドロップするために、
DragDropContext が複数ある場合は monitor.getItemType() でどのコンテキストなのかを判定するとよいでしょう。プレビューがタッチした部分に追従するように
monitor.getSourceClientOffset() を使ってオフセット座標を返しておきます。collect 関数の返り値のオブジェクトはそのままプレビュー用のコンポーネントで props として受け取ることができます。getItemStyles 関数では受け取った props.currentOffset を使ってCSSを調整しています。DragDropContext に渡したコンポーネントで DragLayer を描画することで、ドラッグ時にプレビューを表示することができます。スマホでもプレビューができた!
※ ChromeのDevToolsでスマートフォンをエミュレートして録画しているためマウスカーソルが表示されています。
最後に
スマートフォンなどのタッチデバイスでHTML5のようなドラッグアンドドロップを実現する方法を解説しました。実際に実装する際は、TouchBackendのリポジトリ に完全に動作するサンプルがあるのでそちらも参考にしてみてください。
参考リンク
http://react-dnd.github.io/react-dnd/abouthttps://github.com/yahoo/react-dnd-touch-backend
コメント
コメントを投稿