状態管理
2019-07-16
テキストのない付箋が表示されるところまでどうにか進んだ
テキストのない付箋が表示されるようになった
テキスト部分はコメントアウトしている
パスは今コメントアウトしている
グループも今コメントアウトしている
canvasのresizeイベントもコメントアウトされて固定サイズになっている
ここら辺を順次戻して行って表示が元どおりになるようにする
それからまずは平行移動とズーム、次に付箋のドラッグでの移動を動かす
2019-08-02
テキストの表示done
base canvasとoverlay canvasがそれぞれPaperScopeを持っている
basePaperとoverlayPaperって名前にした
app.paperを削除
色々なところで使いまくっている
Toolもapp.paperにぶら下がっている
一旦コメントアウト
拡大縮小できるようになった(拡大縮小完了時に状態をセットしようとして死ぬ)
状態を更新する必要はないのではないかと考えてコメントアウト
ズームはできるようになった
平行移動を実現
manualを開いて見られるようにする
commit id: f182638
---
pRegroupに書き連ねられたものの集合体:
小手先の高速化より状態管理の仕組みの改善が優先
選択・ハイライトの状態管理
DefaultToolのhighlight/deselectはSelectionのそれと統合されるべきでは
In this section, we will create a React reconciler using react-reconciler package. We are going to implement the renderer using Fiber. Earlier, React was using a stack renderer as it was implemented on the traditional JavaScript stack. On the other hand, Fiber is influenced by algebraic effects and functional ideas. It can be thought of as a JavaScript object that contains information about a component, its input, and its output. すべての状態更新がundoリストに入っているが、それは適切ではない
---
状態管理の刷新について理解の整理
本質的にこのアプリは「HTML5のCanvasにレンダリングするアプリ」である
直接Canvasに描画するのではなくPaper.jsを使っている(当たり判定などの丸投げのため)
React的状態が更新されたらPaper#Itemを全破棄して再生成している
その実装でPCのChrome上では問題なく動く
iPadのSafari、Chrome、PCのSafariでは付箋の枚数によらず「画像の貼られた付箋」に不愉快な点滅が発生する
おそらくPCのChromeだけ、Paper.jsより下のレイヤ(=ブラウザ)で画像のキャッシュをしている
iPadで快適に動くためには、Paper#itemが破棄されないようになる必要がある
それはつまり、React的状態が更新された時に、Paper.jsのレイヤーでは既存のオブジェクトの修正や移動で対処する必要がある
これはReactがDOMに対して行なっているのとほぼ同等の処理、それを担当するのはReconciler
自分でReconcilerを実装するか、既存の実装を利用する必要がある。実装したくないのでreact-paper-bindingsを使う
加えて、現状全体のstateがUNDO対象になっているが、UNDOは必要に応じてスナップショットをpushしていく形に変える
-----
状態の代わりに関してはまずは一意なIDを持つようにしてreactがリストのレンダリングに使っているのと同じ仕組みでできないか試すべきだな、自前で差分レンダリングを作るのはなるべく避けたい だけども最終的に出力されるものがpaper.jsの要素のリストだからDOM操作のメソッドは使えないので、そこをどうするのか
react-paper-bindingがどういう実装をしているか観察
componentDidUpdateからPaperRenderer.updateContainerを呼んでいて、このPaperRendererはReconciler
オブジェクトが一意なIDを持つ必要がある、という点はReactの言葉ではKeyと言うらしい
で子要素を持つようなコンポーネントに更新があった場合には、ReconcilerがそのKeyをみて子要素を新しく作るのか破壊的に更新するのかを決める感じか
react-paper-bindingを使うので良さそう
とどちらが良いかと言うことに関しては判断がつかない
こちらの方が最終更新は新しい
react-paper-bindingの方がコントリビュータは多いなぁ
状態管理
設計の深いところに手を入れれば「画像付箋を100枚出してもちらつかない」って理想は実現できると思うが
「UNDOの機能を維持したまま」だとこれ、そう簡単ではないな。
かといってUNDOの機能を捨てるのはちょっとなぁ...
問題の整理
Reactの状態管理と辻褄の合うUNDO/REDOの仕組みを調べた時に、参考にした2つの実装が両方とも「状態が更新されたら全部再描画」になっていて当時僕は「そんなのでいいのか?性能上の問題が出るのでは?修正差分で管理する形にするべきでは?」って考えてから
若干モヤモヤするけど早すぎる最適化は諸悪の根源なので「全状態履歴を保持する実装」でまずは作る。
という判断をしたわけだ。でもって、100枚付箋を出して動かしたりしても意外と性能上の問題が出なかった。
で、ここまで来て「iPad上で画像の付箋を100枚出す」という条件でついに問題が出たわけだ。
画像が1枚でも「iPad上では画像が0.5〜1秒遅れて描画される」って振る舞いなのでこの問題を解決するには極力描画済みのオブジェクトを使い回すような実装にしなきゃいけない
Paper.jsのオブジェクトのツリーをReactの仮想DOMみたいに扱う必要があるのか
アプローチとしてはこんな感じか?
共同編集できるようにしたい
付箋の移動はやはりiPadで指でひょいひょい動かしたい
付箋の追加に関しては、キーボードが使いたいからPCでやりたい
編集モードで2箇所で開いたせいで、片方の編集で片方を上書きしてしまうミスをしたw
やっぱり、一人で使うとしても共同編集はできるべきなのです(結論)
今共同編集がOFFにされている理由は「片方の編集者がドラッグなどしている最中に、他の編集者の編集が到着してオブジェクトが再生成された場合に、ドラッグ完了時にドラッグ対象のオブジェクトを見つけられなくて死ぬ」ということなので結局やっぱりPaper#ItemがReact上の状態オブジェクト(StateItem)への参照を持っている状態がダメで全てのStateItemにuniqueなIDをつけて、ドラッグ完了のタイミングでシーンツリーからそのIDのオブジェクトを検索してそれを更新するって仕組みにするべき