react-draggable使った話
研究で色々あってreactを使う判断をしました。
研究ではAndroidのセンサログ情報やら開発者が実装した行動認識を行うクラスを可視化して想定通りに行動認識アルゴリズムが動作しているかの調査や、そもそもどういったセンサデータが用いれるかを調べられるWebベースのデバッグツールを作っていました。 本デバッグツールでは様々なセンサデータを可視化することとなるのですが、その際には、ツール利用者が自由にグラフ配置できるような仕組みが求められるかと思います。 なにぶん、昨今Androidのセンサは増えていますし、行動認識と一口に言っても様々なパラメータや計算過程の値が跋扈するわけです、大量のグラフを並べたいように並べる仕組みが必要かと思います。
そこで mzabriskie/react-draggable: React draggable component というライブラリを使いました。 名前の通りドラッグ可能にする便利コンポーネントです。
インストール方法と設定については公式READMEをご覧ください。
ドラッグ可能にする
ドラッグ可能にしたい要素を Draggable
コンポーネントで囲います。
<Draggable> <div> ドラッグできるよ </div> </Draggable>
これで div
要素はドラッグ可能になりました。簡単ですね。Reactのコンポーネントでも同様にできます。
ウインドウっぽくしたい
現状の実装だと要素内のどこをドラッグしてもドラッグされます。できればウインドウのUIっぽく上の方だけクリックしたら移動みたいな実装にしたいですね。
それには handle
属性を利用すれば良いです。 handle
で指定したclassの要素をドラッグすることで移動ができるようになります。
<Draggable handle="handle"> <div className="handle"> ここをドラッグ! </div> こっちではドラッグできないよ </Draggable>
位置を保存したい
今回のツールはブラウザベースで開発しているのですがリロードのたびに配置が変わるのは好ましくありません。 そこで位置を保存して再読込の際にはロードされるようにしましょう。
// constructorなどで実行 this.state = { componentPosition: { x: parseInt(localStorage.getItem(`position_x`), 10) || 0, y: parseInt(localStorage.getItem(`position_y`), 10) || 0 } }; function onDrag(e, position){ const {x, y} = position; this.setState({ position: {x, y} }); } function onStop(e, position){ const {x, y} = position; localStorage.setItem("position_x", x); localStorage.setItem("position_y", y) } <Draggable handle="handle" position={this.state.positon} onDrag={onDrag} onStop={onStop}> <div className="handle"> ここをドラッグ! </div> こっちではドラッグできないよ </Draggable>
こうすると、初回は position
属性によって位置が決められる。ドラッグ時には onDrag
が呼び出され、 state.position
が更新される。
ドラッグ停止時には onStop
が呼び出され localStorage
への保存が行われる。