11// @flow
22import * as React from 'react' ;
33
4- type Vertice = {
4+ type Vertex = {
55 x : number ,
66 y : number ,
77} ;
@@ -13,64 +13,201 @@ type Props = {|
1313 offsetX : number ,
1414 offsetY : number ,
1515 polygonOrigin : string ,
16- vertices : Array < Vertice > ,
16+ vertices : Array < Vertex > ,
1717 width : number ,
1818 height : number ,
19+ onMoveVertex : ( index : number , newX : number , newY : number ) => void ,
1920| } ;
2021
2122type State = { |
22- image : string ,
23+ draggedVertex : ?Vertex ,
24+ draggedIndex : number ,
2325| } ;
2426
2527export default class ShapePreview extends React . Component < Props , State > {
28+ constructor ( props : Props ) {
29+ super ( props ) ;
30+ this . state = { draggedVertex : null , draggedIndex : - 1 } ;
31+ }
2632
27- render ( ) {
28-
29- const { dimensionA, dimensionB, shape, offsetX, offsetY, width, height} = this . props ;
33+ _svg : any ;
34+
35+ _onVertexDown = ( vertex : Vertex , index : number ) => {
36+ if ( this . state . draggedVertex ) return ;
37+ this . setState ( { draggedVertex : vertex , draggedIndex : index } ) ;
38+ } ;
39+
40+ _onMouseUp = ( ) => {
41+ const draggingWasDone = ! ! this . state . draggedVertex ;
42+ const { draggedVertex, draggedIndex } = this . state ;
43+ this . setState (
44+ {
45+ draggedVertex : null ,
46+ } ,
47+ ( ) => {
48+ if ( draggingWasDone )
49+ this . props . onMoveVertex (
50+ draggedIndex ,
51+ Math . round ( draggedVertex ? draggedVertex . x : 0 ) ,
52+ Math . round ( draggedVertex ? draggedVertex . y : 0 )
53+ ) ;
54+ }
55+ ) ;
56+ } ;
57+
58+ _onMouseMove = ( event : any ) = > {
59+ const { offsetX, offsetY, polygonOrigin, width, height } = this . props ;
60+ const { draggedVertex } = this . state ;
61+ if ( ! draggedVertex ) return ;
62+
63+ const pointOnScreen = this . _svg . createSVGPoint ( ) ;
64+ pointOnScreen . x = event . clientX ;
65+ pointOnScreen . y = event . clientY ;
66+ const screenToSvgMatrix = this . _svg . getScreenCTM ( ) . inverse ( ) ;
67+ const pointOnSvg = pointOnScreen . matrixTransform ( screenToSvgMatrix ) ;
68+
69+ draggedVertex . x =
70+ pointOnSvg . x - offsetX - ( polygonOrigin === 'Center' ? width / 2 : 0 ) ;
71+ draggedVertex . y =
72+ pointOnSvg . y - offsetY - ( polygonOrigin === 'Center' ? height / 2 : 0 ) ;
73+
74+ this . forceUpdate ( ) ;
75+ } ;
76+
77+ renderBox ( ) {
78+ const {
79+ dimensionA,
80+ dimensionB,
81+ width,
82+ height,
83+ offsetX,
84+ offsetY,
85+ } = this . props ;
3086 const fixedWidth = dimensionA > 0 ? dimensionA : width > 0 ? width : 1 ;
3187 const fixedHeight = dimensionB > 0 ? dimensionB : height > 0 ? height : 1 ;
3288
3389 return (
34- < div >
35- { shape === 'Box' && (
36- < svg >
37- < rect
38- key = { `boxShape` }
39- fill = "rgba(255,0,0,0.75)"
40- strokeWidth = { 1 }
41- x = { offsetX + width / 2 - fixedWidth / 2 }
42- y = { offsetY + height / 2 - fixedHeight / 2 }
43- width = { fixedWidth }
44- height = { fixedHeight }
45- />
46- </ svg >
47- ) }
48- { shape === 'Circle' && (
49- < svg >
50- < circle
51- key = { `boxShape` }
52- fill = "rgba(255,0,0,0.75)"
53- strokeWidth = { 1 }
54- cx = { offsetX + width / 2 }
55- cy = { offsetY + height / 2 }
56- r = { dimensionA > 0 ? dimensionA : ( width + height ) > 0 ? ( width + height ) / 4 : 1 }
57- />
58- </ svg >
59- ) }
60- { shape === 'Edge' && (
61- < svg >
62- < line
63- key = { `boxEdge` }
64- stroke = "rgba(255,0,0,0.75)"
65- strokeWidth = { 2 }
66- x1 = { offsetX + width / 2 - fixedWidth / 2 * Math . cos ( dimensionB * Math . PI / 180 ) }
67- y1 = { offsetY + height / 2 - fixedWidth / 2 * Math . sin ( dimensionB * Math . PI / 180 ) }
68- x2 = { offsetX + width / 2 + fixedWidth / 2 * Math . cos ( dimensionB * Math . PI / 180 ) }
69- y2 = { offsetY + height / 2 + fixedWidth / 2 * Math . sin ( dimensionB * Math . PI / 180 ) }
70- />
71- </ svg >
72- ) }
73- </ div >
90+ < rect
91+ key = { 'boxShape' }
92+ fill = "rgba(255,0,0,0.75)"
93+ strokeWidth = { 1 }
94+ x = { offsetX + width / 2 - fixedWidth / 2 }
95+ y = { offsetY + height / 2 - fixedHeight / 2 }
96+ width = { fixedWidth }
97+ height = { fixedHeight }
98+ />
99+ ) ;
100+ }
101+
102+ renderCircle ( ) {
103+ const { dimensionA , width , height , offsetX , offsetY } = this . props ;
104+
105+ return (
106+ < circle
107+ key = { 'circleShape' }
108+ fill = "rgba(255,0,0,0.75)"
109+ strokeWidth = { 1 }
110+ cx = { offsetX + width / 2 }
111+ cy = { offsetY + height / 2 }
112+ r = {
113+ dimensionA > 0
114+ ? dimensionA
115+ : width + height > 0
116+ ? ( width + height ) / 4
117+ : 1
118+ }
119+ />
120+ ) ;
121+ }
122+
123+ renderEdge ( ) {
124+ const {
125+ dimensionA,
126+ dimensionB,
127+ width,
128+ height,
129+ offsetX,
130+ offsetY,
131+ } = this . props ;
132+ const halfLength =
133+ ( dimensionA > 0 ? dimensionA : width > 0 ? width : 1 ) / 2 ;
134+ const cos = Math . cos ( ( dimensionB * Math . PI ) / 180 ) ;
135+ const sin = Math . sin ( ( dimensionB * Math . PI ) / 180 ) ;
136+
137+ return (
138+ < line
139+ key = { 'edgeShape' }
140+ stroke = "rgba(255,0,0,0.75)"
141+ strokeWidth = { 2 }
142+ x1 = { offsetX + width / 2 - halfLength * cos }
143+ y1 = { offsetY + height / 2 - halfLength * sin }
144+ x2 = { offsetX + width / 2 + halfLength * cos }
145+ y2 = { offsetY + height / 2 + halfLength * sin }
146+ />
147+ ) ;
148+ }
149+
150+ renderPolygon ( ) {
151+ const {
152+ vertices,
153+ polygonOrigin,
154+ width,
155+ height,
156+ offsetX,
157+ offsetY,
158+ } = this . props ;
159+
160+ return (
161+ < React . Fragment >
162+ < polygon
163+ key = { 'polygonShape' }
164+ fill = "rgba(255,0,0,0.75)"
165+ strokeWidth = { 1 }
166+ filerule = "evenodd"
167+ points = { vertices
168+ . map (
169+ vertex =>
170+ `${ vertex . x +
171+ offsetX +
172+ ( polygonOrigin === 'Center' ? width / 2 : 0 ) } ,${ vertex . y +
173+ offsetY +
174+ ( polygonOrigin === 'Center' ? height / 2 : 0 ) } `
175+ )
176+ . join ( ' ' ) }
177+ />
178+ { vertices . map ( ( vertex , index ) => (
179+ < circle
180+ onPointerDown = { event => this . _onVertexDown ( vertex , index ) }
181+ key = { `vertex-${ index } ` }
182+ fill = "rgba(150,0,0,0.75)"
183+ strokeWidth = { 1 }
184+ cx = {
185+ vertex . x + offsetX + ( polygonOrigin === 'Center' ? width / 2 : 0 )
186+ }
187+ cy = {
188+ vertex . y + offsetY + ( polygonOrigin === 'Center' ? height / 2 : 0 )
189+ }
190+ r = { 5 }
191+ />
192+ ) ) }
193+ </ React . Fragment >
194+ ) ;
195+ }
196+
197+ render ( ) {
198+ const { shape } = this . props ;
199+
200+ return (
201+ < svg
202+ onPointerMove = { this . _onMouseMove }
203+ onPointerUp = { this . _onMouseUp }
204+ ref = { svg => ( this . _svg = svg ) }
205+ >
206+ { shape === 'Box' && this . renderBox ( ) }
207+ { shape === 'Circle' && this . renderCircle ( ) }
208+ { shape === 'Edge' && this . renderEdge ( ) }
209+ { shape === 'Polygon' && this . renderPolygon ( ) }
210+ </ svg >
74211 ) ;
75212 }
76213}
0 commit comments