[フロントエンド] React.jsで行のスワイプを実装する(Hammer.js利用)
こんにちは、@yoheiMuneです。
React.jsで、ネイティブのような行スワイプ処理を実装したので、ブログに残したいと思います。
React.jsにおける指ジェスチャーもHammer.jsを使うと、お手軽に実装することができます。
最後になりますが本ブログでは、フロントエンド、サーバー、Swift、PHP、Node.js、Python、Java、Linux、インフラ、Go言語、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSやTwitterをフォローして貰えたら嬉しいです ^ ^
最後までご覧頂きましてありがとうございました!
React.jsで、ネイティブのような行スワイプ処理を実装したので、ブログに残したいと思います。
目次
今回のサンプルコード
GithubのyoheiMune/react-hammer-drag-sampleに置いてあります。適宜ご参照ください。何をしたいのか
以下のテーブルビューのようなUIの場合に、指でグググと動かして行をスワイプしたい。それをReact.jsで実現したいというお話です。
Hammer.jsについて
スマホ向けのWebページで、スワイプやピンチなどの指によるジェスチャーを扱いたい場合には、Hammer.jsが便利です。Angular.jsにも採用されていて、かなりの人気なライブラリです。React.jsにおける指ジェスチャーもHammer.jsを使うと、お手軽に実装することができます。
npmインストール
React.jsでHammer.jsを扱うことができるライブラリはいくつかありますが、今回はreact-hammerjsを導入しました。採用理由としてはある程度Githubのスターも集まっているし、使い勝手も良さそうだったためです。npm installで導入します。$ npm install --save react-hammerjs
スワイプ処理を実装する
具体的な実装内容です。Cell.jsにスワイプ処理を実装し、それをApp.jsから利用する形で実装しました。App.js
まず先に、Cell.jsの利用側です。特段考慮することはなく、普通のReact的な実装を行います。
import React, { Component } from 'react'
import Cell from './Cell' // Cell.jsを読み込む
import './App.css'
class App extends Component {
render() {
return (
<div>
<h1>React.js and Hammer.js Sample.</h1>
{/* スワイプできるCellを5つ並べてみる. */}
<div className="items">
{
[1, 2, 3, 4, 5].map(num => {
return <Cell num={num} key={num}/>
})
}
</div>
</div>
)
}
}
export default App
ここではCellを5つ並べてみました。Cell.js
こちらがメインです。react-hammerjsを用いてスワイプ処理を実装します。
import React, { Component } from 'react'
import Hammer from 'react-hammerjs' // Hammer.jsを使えるように読み込みます.
import './Cell.css'
// スワイプで開いたときの距離.
const SWIPED_DISTANCE = 150
class Cell extends Component {
constructor() {
super(...arguments)
// 初期状態を定義します
this.state = {
// スワイプされた状態の場合にtrue.
opened : false,
// 指で動かしている時の移動距離.
deltaX : 0
}
}
// スワイプの開始位置を計算して返します.
// open状態であれば-150pxがスタート地点、それ以外は0px.
getFirstPosition() {
return this.state.opened ? -1 * SWIPED_DISTANCE : 0
}
// 指でのドラッグが始まった時.
onPanStart(e) {
// 最初のCellの位置を設定します.
this.setState({
deltaX : this.getFirstPosition()
})
}
// 指でドラッグしている.
onPan(e) {
// 指で動かした分だけ、移動距離を変化させます.
this.setState({
deltaX : this.getFirstPosition() + e.deltaX
})
}
// ドラッグ終了
onPanEnd(e) {
// 移動量に応じて、openedの状態を変更します.
// スワイプ前は開いていた場合
if (this.state.opened) {
// 75px(150pxの半分)の動きがあれば、閉じる.
if (e.deltaX >= SWIPED_DISTANCE / 2) {
this.setState({
opened : false,
deltaX : 0
})
// スワイプ量が少なければ、opened状態はそのまま.
} else {
this.setState({
deltaX : this.getFirstPosition()
})
}
// スワイプ前は閉じていた場合
} else {
// 75px(150pxの半分)の動きがあれば、開く.
if (e.deltaX <= -1 * SWIPED_DISTANCE / 2) {
this.setState({
opened : true,
deltaX : -1 * SWIPED_DISTANCE
})
// スワイプ量が少なければ、opened状態はそのまま.
} else {
this.setState({
deltaX : 0
})
}
}
}
render() {
// スワイプ量に合わせて、要素の位置を変更する.
let style = {
transform : `translate(${this.state.deltaX}px, 0)`
}
// <Hammer>タグでスワイプのアクションを捕捉する.
// onPanStart、onPan、onPanEnd、それぞれのイベントを扱います.
// また、「style={style}」で移動距離を設定します.
return (
<Hammer
onPanStart={this.onPanStart.bind(this)}
onPan={this.onPan.bind(this)}
onPanEnd={this.onPanEnd.bind(this)}>
<div className="cell" style={style}>cell{this.props.num}</div>
</Hammer>
)
}
}
export default Cell
少しコードが長いですが、onPanStart、onPan、onPanEndでスワイプを捉えて、その変化した量をCSSのtransform + translateで表現することで、スワイプアクションを実現しています。最後に
Hammer.jsは色々なイベントを捕捉できるので、今回紹介したもの以外にも色々と実装できて面白いです。最後になりますが本ブログでは、フロントエンド、サーバー、Swift、PHP、Node.js、Python、Java、Linux、インフラ、Go言語、機械学習、などの技術トピックを発信をしていきます。「プログラミングで困ったその時の、解決の糸口に!」そんな目標でブログを書き続けています。ぜひ、本ブログのRSSやTwitterをフォローして貰えたら嬉しいです ^ ^
最後までご覧頂きましてありがとうございました!






