[フロントエンド] 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をフォローして貰えたら嬉しいです ^ ^
最後までご覧頂きましてありがとうございました!