SVG + React でつくる レイヤーの自由変形 / Layer Transformation with React + SVG
by
fsubal
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
SVG + React でつくる レイヤーの自由変形 Layer Transformation with React + SVG pixiv Inc. f_subal 2018/12/07
Slide 2
Slide 2 text
2 誰 ● 2016年新卒入社 ● sensei ➔ pixiv 投稿画面 ➔ pixivFACTORY ● React / Redux / SVG @f_subal
Slide 3
Slide 3 text
3
Slide 4
Slide 4 text
4
Slide 5
Slide 5 text
今日話すこと 5
Slide 6
Slide 6 text
レイヤーの自由変形をつくる 6 (っぽいもの)
Slide 7
Slide 7 text
● なぜ SVG を使うのか? ● 何が SVG の自由変形に必要か? ● 何を実装時に気をつけるか? 7 レイヤーの自由変形 (っぽいもの)
Slide 8
Slide 8 text
なぜ SVG か 8
Slide 9
Slide 9 text
任意の図形が描ける? 画像ファイルへの変換が楽? 9
Slide 10
Slide 10 text
もちろんそれもあるが 10
Slide 11
Slide 11 text
viewBox 11
Slide 12
Slide 12 text
● SVG 内のキャンバスサイズ的なものを決める属性 ○ 実際に表示する大きさとは別に決めることはできる ● 要件: グッズをつくるエディタ ○ グッズは物理的な世界にある ○ 物理的な世界にあるってことは、長さが px 単位じゃない ○ けど画面は長さが px 単位 12 viewBox と単位系
Slide 13
Slide 13 text
ブラウザに mm を描画したい 13
Slide 14
Slide 14 text
14 50x18mm の原稿が、599x215px で表 示されている 中のオブジェクトは mm で表現
Slide 15
Slide 15 text
最高 15
Slide 16
Slide 16 text
HTML を draggable にしてる 場合じゃない 16
Slide 17
Slide 17 text
で、 17
Slide 18
Slide 18 text
SVG を drag したい 18
Slide 19
Slide 19 text
19 もっというと、 移動・拡大・回転 の 3つがやりたい (厳密にはこの3つだけだと「自由変形」と呼ぶには弱いがゆるして )
Slide 20
Slide 20 text
そういえば HTML 5 Drag & Drop API ってやつが… 20
Slide 21
Slide 21 text
21 SVG Element に対応してない
Slide 22
Slide 22 text
それに依存したライブラリは無理 (react-dnd-html5-backend とか) 22
Slide 23
Slide 23 text
draggable 系ライブラリには 他にも良いのあるけど ( react-draggable とか ) 23
Slide 24
Slide 24 text
移動・拡大・回転 全部は期待できない (たいていは移動だけ、拡大だけ) 24
Slide 25
Slide 25 text
ある程度 自作するものと割り切る 25
Slide 26
Slide 26 text
全部入りではなく シンプルな drag 対応が欲しい 26
Slide 27
Slide 27 text
● SVG 要素を draggable にする ● 移動・拡大・回転にまつわる座標計算を書く ● マウスの移動量(px)を原稿の大きさ(mm)に換算する ● 以上をコンポーネントにする 27 やるべきこと
Slide 28
Slide 28 text
まず draggable にしてみよう 28
Slide 29
Slide 29 text
Snap.svg 29
Slide 30
Slide 30 text
● Adobe 製 SVG 何でもやる系ライブラリ。 ● react-* とかじゃない、Framework Agnostic ● Snap(el).drag(fn, fn, fn) で要素を draggable にできる ● これを使えば優勝…! 30 Snap.svg
Slide 31
Slide 31 text
と、思いきや 31
Slide 32
Slide 32 text
● なんと、mousemove にしか対応してない ● タッチデバイスは動かない ○ Snap.svg と同じ API の touch 用 draggable ライブラリを自作して対応 ● 現状、mouse は Snap.svg、touch は自作ライブラリ になってる ○ 両方対応ライブラリを目指す… 32 Snap#drag is mouse ONLY
Slide 33
Slide 33 text
33
Slide 34
Slide 34 text
これで基盤が整った 34
Slide 35
Slide 35 text
次は 35
Slide 36
Slide 36 text
座標を計算する 36
Slide 37
Slide 37 text
● アフィン変換 ○ 線形変換 + 平行移動 を行列式で一手に扱う数学のアレ ○ 「シアー」みたいな複雑な変換も行ける。 ● ホモグラフィ ○ ↑ に加えて「台形」とか「ゆがみ」とかもいけるやつ ○ 任意の四角形にできる 37 アフィン変換 ? ホモグラフィ ?
Slide 38
Slide 38 text
● 事実上おなじことやってるんだけど、良い感じの行列ライブラリとかないし ○ Snap.svg の matrix クラスとかあるけど…まぁ… ● 移動とか、単に座標の足し算で書いたほうが読み書きしやすいし ● 回転も、回転中心とカーソルの位置から atan2 だけで済むし ● ひとまず手早く書けて可読になるだろうと期待して愚直に 38 が、今回は使わずに実装する
Slide 39
Slide 39 text
39
Slide 40
Slide 40 text
● 水平な矩形の拡大は簡単 ○ マウスカーソルが動いた分を width と height に足すだけ ● けど 30° 右に傾いた矩形の拡大はめんどい ○ これだけは回転行列を使わないと無理 40 唯一の障壁「回転を考慮した拡大」
Slide 41
Slide 41 text
● 回転行列の公式を使って求める 41 点A を点O を中心に回転した時の座標 https://ja.wikipedia.org/wiki/回転行列 http://www.geisya.or.jp/~mwm48961/kou2/linear_image3.html
Slide 42
Slide 42 text
42
Slide 43
Slide 43 text
あとはだいたい 気合でやる 43
Slide 44
Slide 44 text
44 その他 気をつけること
Slide 45
Slide 45 text
● px ➔ mm 変換関数を作る必要がある ● 1mm が 何 px に相当するかは window の横幅に依存する ○ リサイズのたびに関数を作り変える ● viewBox のある要素を見れば現在 1mm が何 px に相当するか計算できる ○ dpi なり dpm が求められる 45 単位換算
Slide 46
Slide 46 text
46 50x18mm の原稿が、599x215px で表 示されている この情報から px ➔ mm 関数が作れる!!
Slide 47
Slide 47 text
【宣伝】詳しくは niconare のコレを見て https://niconare.nicovideo.jp/watch/kn3927 47
Slide 48
Slide 48 text
まとめ 48
Slide 49
Slide 49 text
● SVG の draggable 対応 ○ 思ったよりライブラリがないので DOM API と戦おう ● 座標計算 ○ 行列計算にひるまずに実装しましょう ○ ただ、基本的な変形は案外足し算レベルでいけたりもします ● 単位換算 ○ px と それ以外が混在する要件に気をつけよう! 49 自由変形に必要なこと (っぽいもの)
Slide 50
Slide 50 text
他にも Mobile Safari の SVG がバグりやすいとか number 型ばかりで間違うから型で守る話とか 座標計算そのものよりも原点を揃えるのが大事とか、 絶対座標と相対座標の混在とか、 タグがどんどんネストしていく話とか いっぱいあるので懇親会で聞いて下さい!!! 50
Slide 51
Slide 51 text
SVG + React でつくる レイヤーの自由変形 Layer Transformation with React + SVG pixiv Inc. f_subal 2018/12/07