@@ -9,10 +9,15 @@ import {
9
9
OnPointerDownHandler ,
10
10
OnDragHandler ,
11
11
} from "../canvas-event-target" ;
12
- import { get_hovering_target , centerOf } from "../math" ;
12
+ import {
13
+ target_of_point ,
14
+ centerOf ,
15
+ edge_scrolling ,
16
+ target_of_area ,
17
+ } from "../math" ;
13
18
import { utils } from "@design-sdk/core" ;
14
19
import { LazyFrame } from "@code-editor/canvas/lazy-frame" ;
15
- import { HudCustomRenderers , HudSurface } from "./hud-surface " ;
20
+ import { HudCustomRenderers , HudSurface } from ".. /hud" ;
16
21
import type { Box , XY , CanvasTransform , XYWH } from "../types" ;
17
22
import type { FrameOptimizationFactors } from "../frame" ;
18
23
const designq = utils . query ;
@@ -89,7 +94,7 @@ export function Canvas({
89
94
...props
90
95
} : {
91
96
viewbound : Box ;
92
- onSelectNode ?: ( node ? : ReflectSceneNode ) => void ;
97
+ onSelectNode ?: ( ... node : ReflectSceneNode [ ] ) => void ;
93
98
onClearSelection ?: ( ) => void ;
94
99
} & CanvasCustomRenderers &
95
100
CanvasState & {
@@ -131,6 +136,7 @@ export function Canvas({
131
136
? [ offset [ 0 ] / zoom , offset [ 1 ] / zoom ]
132
137
: [ 0 , 0 ] ;
133
138
const [ isPanning , setIsPanning ] = useState ( false ) ;
139
+ const [ isDraggomg , setIsDragging ] = useState ( false ) ;
134
140
const [ marquee , setMarquee ] = useState < XYWH > ( null ) ;
135
141
136
142
const cvtransform : CanvasTransform = {
@@ -151,17 +157,46 @@ export function Canvas({
151
157
setHoveringLayer ( wshighlight ) ;
152
158
} , [ highlightedLayer ] ) ;
153
159
160
+ // area selection hook
161
+ useEffect ( ( ) => {
162
+ if ( marquee ) {
163
+ const area : XYWH = [
164
+ marquee [ 0 ] / zoom ,
165
+ marquee [ 1 ] / zoom ,
166
+ marquee [ 2 ] / zoom ,
167
+ marquee [ 3 ] / zoom ,
168
+ ] ;
169
+
170
+ const selections = target_of_area ( {
171
+ area,
172
+ tree : nodes ,
173
+ contain : false ,
174
+ } ) ;
175
+
176
+ // https://stackoverflow.com/a/19746771
177
+ const same =
178
+ selectedNodes . length === selections ?. length &&
179
+ selectedNodes . every ( ( value , index ) => value === selections [ index ] . id ) ;
180
+
181
+ if ( ! same ) {
182
+ onSelectNode ( ...selections ) ;
183
+ }
184
+ }
185
+ //
186
+ } , [ marquee ] ) ;
187
+
154
188
const onPointerMove : OnPointerMoveHandler = ( state ) => {
155
- if ( isPanning || isZooming ) {
189
+ if ( isPanning || isZooming || isDraggomg ) {
156
190
// don't perform hover calculation while transforming.
157
191
return ;
158
192
}
159
- const hovering = get_hovering_target ( {
193
+ const hovering = target_of_point ( {
160
194
point : state . xy ,
161
195
tree : nodes ,
162
196
zoom : zoom ,
163
197
offset : nonscaled_offset ,
164
198
margin : LAYER_HOVER_HIT_MARGIN ,
199
+ reverse : true ,
165
200
} ) ;
166
201
167
202
if ( ! hovering ) {
@@ -223,27 +258,48 @@ export function Canvas({
223
258
setOffset ( [ newx , newy ] ) ;
224
259
} ;
225
260
261
+ const onDragStart : OnDragHandler = ( s ) => {
262
+ onClearSelection ( ) ;
263
+ setIsDragging ( true ) ;
264
+ setHoveringLayer ( null ) ;
265
+
266
+ // set the marquee start point
267
+ const [ x , y ] = s . initial ;
268
+ const [ ox , oy ] = offset ;
269
+ const [ x1 , y1 ] = [ x - ox , y - oy ] ;
270
+ setMarquee ( [ x1 , y1 , 0 , 0 ] ) ;
271
+ } ;
272
+
226
273
const onDrag : OnDragHandler = ( s ) => {
227
- const [ x1 , y1 ] = s . initial ;
228
- const [ x2 , y2 ] = [
274
+ const [ ox , oy ] = offset ;
275
+ const [ x , y ] = [
229
276
// @ts -ignore
230
277
s . event . clientX ,
231
278
// @ts -ignore
232
279
s . event . clientY ,
233
280
] ;
234
281
235
- const [ ox , oy ] = offset ;
236
- const [ x , y , w , h ] = [
237
- x1 - ox ,
238
- y1 - oy ,
239
- x2 - x1 , // w
240
- y2 - y1 , // h
241
- ] ;
242
- setMarquee ( [ x , y , w , h ] ) ;
282
+ const [ x1 , y1 ] = [ x - ox , y - oy ] ;
283
+
284
+ if ( marquee ) {
285
+ const [ w , h ] = [
286
+ x1 - marquee [ 0 ] , // w
287
+ y1 - marquee [ 1 ] , // h
288
+ ] ;
289
+ setMarquee ( [ marquee [ 0 ] , marquee [ 1 ] , w , h ] ) ;
290
+ }
291
+
292
+ // edge scrolling
293
+ const [ cx , cy ] = [ x , y ] ;
294
+ const [ dx , dy ] = edge_scrolling ( cx , cy , viewbound ) ;
295
+ if ( dx || dy ) {
296
+ setOffset ( [ ox + dx , oy + dy ] ) ;
297
+ }
243
298
} ;
244
299
245
300
const onDragEnd : OnDragHandler = ( s ) => {
246
301
setMarquee ( null ) ;
302
+ setIsDragging ( false ) ;
247
303
} ;
248
304
249
305
const is_canvas_transforming = isPanning || isZooming ;
@@ -299,8 +355,8 @@ export function Canvas({
299
355
onPointerMoveStart = { ( ) => { } }
300
356
onPointerMoveEnd = { ( ) => { } }
301
357
onPointerDown = { onPointerDown }
358
+ onDragStart = { onDragStart }
302
359
onDrag = { onDrag }
303
- onDragStart = { ( ) => { } } // TODO:
304
360
onDragEnd = { onDragEnd }
305
361
>
306
362
< HudSurface
@@ -363,7 +419,7 @@ function CanvasTransformRoot({
363
419
width : 0 ,
364
420
height : 0 ,
365
421
willChange : "transform" ,
366
- transform : `scale(${ scale } ) translateX (${ xy [ 0 ] } px) translateY( ${ xy [ 1 ] } px)` ,
422
+ transform : `scale(${ scale } ) translate3d (${ xy [ 0 ] } px, ${ xy [ 1 ] } px, 0 )` ,
367
423
isolation : "isolate" ,
368
424
} }
369
425
>
0 commit comments