プレゼンモード
再生
← / →で移動
fでフルスクリーン
escでおわる
ReactとCanvasでお絵かき機能を作った話
画像編集機能リニューアル
- React諸々の作業も落ち着いてきたので開始
- 図形の再編集・再配置を出来るように
- undoとかあると便利
v1.0の実装状態
- canvasが2つ
- 矢印は絶妙な線の曲がり具合などがハードコーディングされているので、そのライブラリはなんとかそのまま次でも使いたい。
今回の登場人物
- canvas
- ReactComponent
- DOMEvent
canvasをReactで使うときの出来事
もう少し具体的に
<Surface width={surfaceWidth} height={surfaceHeight} left={0} top={0}> <Layer /> <Image style={imageStyle} src='...' /> <Text style={textStyle}> 京都なんか </Text> <Text>...</Text> <Text>...</Text> <Image /> <Text>...</Text>
DOM Eventのハンドリングは誰が/どうやってやる?
事例紹介
React Konva
React-Canvas
- GitHub - Flipboard/react-canvas: High performance <canvas> rendering for React components
- 60fps on the mobile web — Flipboard Engineering
canvasでスクロールに応じて、ドンドン描いていくとDOMよりもrepaintが早くてヌルヌルさせる。お絵かき機能はない。
https://flipboard.com/ のスマホ版で実際に使われている雰囲気っぽい?
今回の作戦
- canvasの上に図形と同じ形のdiv OR svgを重ねてイベントをハンドリングしよう
- 上の方のComponentのstateのshapesってとこに図形情報の配列を入れてCanvasの描画状態を管理する
- ついでにその情報を使って図形の選択などをハンドリングするdivも描画する
- undo / redo的な操作もstateを更新してやる
雰囲気
- wrapper
- Layer
- 矢印
- 文字
- 矢印
- 四角
- canvas
- Layer
canvas の状態管理
React Componentのライフサイクル
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
- componentWillUnmount
Canvasのアップデートをどのタイミングで挿入するか問題
- componentをアップデートすると保持していたcanvasのcontextが死ぬ
- 図形に重ねるイベントハンドリングのdivが多いとrepaint地獄で死ぬ
- canvasでイベントハンドリングを全部やっていれば、この部分で悩まなくて済む
- 図形の領域かどうかを上手く判定しまくる必要がある
- 文字?矢印?
- 図形の領域かどうかを上手く判定しまくる必要がある
- canvasでイベントハンドリングを全部やっていれば、この部分で悩まなくて済む
- 図形に重ねるイベントハンドリングのdivが多いとrepaint地獄で死ぬ
- mousedown -> mousemove -> mouseup の間はrender走らせないようにsetStateを叩かずに一旦安静にしておいて、canvasのみを更新する
- stateに入れずにstoreとか使えば良いのではと思うけど、今はcanvasだけを更新することをstoreのUpdate時に上手くお知らせしないと同じことが起きる
- componentDidUpdateのタイミングで一斉にcanvasを全部描き直す
結果
DEMO
まとめ
- 大体スルスルくらいは動いている状態
- canvasのアップデートタイミングをReactのライフサイクルの中で上手くやっていく必要がある
- ライフサイクルの気持ちになる必要がある
- DOMは重い
心配事
- なんかもう少し良い感じにモデル化できるのではないか
- React使う必要があるのか