Push: Ctrl+Y

 技術で遊んで ときどき進む

Web 解説してみた

React + Redux + D3.js アニメーション:ドラッグ&ドロップでキングスライムを作った

2016/08/15

はい、今回は要素のドラッグ&ドロップを中心に作ってみました。
MaterialDesignというGoogleが作った新しいデザインの形が普及してきてるように思いますが、こういうリッチなUIの作り方を知っているとWebでもUIを考えるときに幅が広がっていいなあと思います。

完成ソースはこちらに置いています。

完成図はこんな感じです。

 

前準備

React + Reduxの環境作成が必要な場合

必要な場合は以下を参照してください。

 

画像を読み込む(webpackのUrlLoader)

webpackを利用しますが、画像を読み込むためにインストールと設定が必要です。

module => loadersに追記します。

 

ドラッグ&ドロップはReactDnDで実現

ReactDndはReact用のドラッグ&ドロップモジュールです。これを使うと超簡単にドラッグ&ドロップを実現できます。公式のDocsが充実しているのも嬉しいところ。

というわけで、とりあえずインストールしておきましょう。

注意点は、ReactDnDはsvgの要素を使えないことです。react-dndというよりhtml5のほうの問題っぽいですが・・とりあえずdivなら動作したのでプログラミング上特に問題なしです!たぶん。

 

Stateの設計

React + Reduxで作るとき、Stateの設計はかなり重要なので先にやります。

react-redux-dnd-1

DragCircleはdivで、{ position: absolute; }としてtop/leftを指定します。
DropCircleは通常は { isMultiple: false }上記の状態で、ドロップすると

  • isMultiple: trueに変更される
  • childCirclesにドラッグ&ドロップされたスライムの情報が入り、svg描画される

みたいな変化をする想定です。

だいたいこれくらいの情報があれば動作可能なので、いちおうreducerに反映しておきましょう。

 

外観を作る

外観を作って動作を加えていく方向でやるので、まず外観を作ります。

円を描く

画面の真ん中に円を描き、その周りに8つのdivを配置します。
そしてもちろん、8つのbackgroundにはスライムの画像を置いていきます!

円配置

ActiondragCircledropCircleの位置を計算してStateにセット、それに従って円や画像を配置します。
componentWillMount(初期化処理するためのReactのメソッド)で初期化して画面中央に配置されるように設定するので、まずComponent達から実装してActionの処理に移りましょう。

最初はDragSlimeCircleで、大きい円の周りに8つ表示される円のひとつひとつです。

次に、真ん中のDropされるdivを作ります。

さらに、それをまとめるComponentが以下ですが、このコンポーネントは次のReactDnDを使うために必要なものになります。

そしてこれらを統括するContainerが以下です。componentWillMount()Actionから必要なデータをStateにセットしています。

 

ここで重要なのがActionsetSlimeCircles()です。でも8つなので計算は簡単。

react-redux-dnd-2

 

いきなりleftとかtopを考えるとややこしいことになるので円の中心を考えて、そこから足し引きすればOKです。

合わせてReducerを変更しておきます。

 

ここまでで実行すると、以下のような画面になるはずです。
ちなみにスライムは自分で描きました。笑顔が引きつってるw

react-redux-dnd-3

 

動作をつける

ReactDnDを使ってdrag&drop

ReactDnDを動かすためには、

  • 【DragSlimeCircle.jsx】  ドラッグするComponent
  • 【DropKingSlimeCircle.jsx】ドロップするComponent
  • 【DragDropCircles.jsx】  上の2つをまとめるComponent

の3つのコンポーネントが必要です。
それぞれ自分の仕事をできるように変更していきます。

まずはドラッグするComponentです。

次にドロップするComponent

こんな感じで、dragとdropのコンポーネント間の値の受け渡しは引数でやれます。
他にもいろんな値が取得できるので、詳しくは公式を参照するといい感じです。

最後に両者を繋ぐComponentです。

かんたんー。

あとは、dropActionContainerから渡してあげようと思います。

 

ここまでで、スライムをDropエリアにドラッグ&ドロップできるようになりました!
あとはdropActionを実行してちっちゃいスライムをDropエリアに移動させ、8個そろったらキングスライムに変更させるだけです。
・・意外とまだ長いな。。

 

ドロップ後のアクションを実装する

ドロップしたときのState変更については最初にちょろっと記載しましたが、

  • dropCircleの変更
    • { isMultiple: true } に変更
    • childCircleに情報追加
  • dragCircleの変更
    • drag済の情報を削除

になります。ここで一番問題になるのはchildCircleの配置です。

円の中に不特定多数のdivを配置していく計算とか考えると頭おかしくなりそうなので、ここは先人の叡智:d3.jsを使ってしまいます。めっちゃ便利な子。

d3.jsの計算解説

d3.jsではいろんな種類の計算ができますが、今回はバブルチャートを使います。
チャートにしたい情報をjson形式のフォーマットに入れ、計算!とやるだけです。

例えばこんな感じのデータがあるとします。(sumの値によって円の大きさを変えたいみたいな)

このとき、

こんな感じにするとpackCalculationsの中にx,y座標・半径r等がリストになってでてきます。

今回はsum的なものは関係ないので全部1として実装すれば、中心の円に収まるようにsvgのcircleの情報を返してくれます。

 

Actionの実装

これを踏まえてActionの実装です。

とりあえず、d3のモジュールをインポートしておきます。

これが、Actionだー!

Reducerでこれを反映させればOKです。

 

 

まとめというか・・

実は8匹目を入れたらキングスライムに変化させるという肝心なところの説明を忘れt・・いや、文字数多くなったからやめたわけで!GitHubに挙っているコードではちゃんと処理が入っているので見比べてみてください。

あとReactMotionについても触れようと思ったのですが、ややこしくなりそうだったので次にまわすことにします。スライムさんの顔は見飽きたが変わらず好きですよ。

>> 完成ソースはこちら(GitHubに飛びます)

 

-Web, 解説してみた
-, , , , ,

おすすめの記事

1
React + Redux入門① - Reduxの概念を理解

React+Reduxでサイトを作っているので、復習がてら「検索画面を作成する」 ...

2
React + Redux + D3.js アニメーション:ドラッグ&ドロップでキングスライムを作った

はい、今回は要素のドラッグ&ドロップを中心に作ってみました。 Mater ...