@@ -351,11 +351,18 @@ function updateShape(gd, index, opt, value) {
351
351
}
352
352
353
353
function setupDragElement ( gd , shapePath , shapeOptions , index ) {
354
+ var MINWIDTH = 10 ,
355
+ MINHEIGHT = 10 ;
356
+
354
357
var update ;
355
358
var x0 , y0 , x1 , y1 , astrX0 , astrY0 , astrX1 , astrY1 ;
359
+ var n0 , s0 , w0 , e0 , astrN , astrS , astrW , astrE , optN , optS , optW , optE ;
356
360
var pathIn , astrPath ;
361
+
357
362
var xa , ya , x2p , y2p , p2x , p2y ;
358
363
364
+ var dragBBox , dragMode ;
365
+
359
366
var dragOptions = {
360
367
element : shapePath . node ( ) ,
361
368
prepFn : startDrag ,
@@ -364,9 +371,8 @@ function setupDragElement(gd, shapePath, shapeOptions, index) {
364
371
365
372
dragElement . init ( dragOptions ) ;
366
373
367
- function startDrag ( ) {
368
- setCursor ( shapePath , 'move' ) ;
369
-
374
+ function startDrag ( evt , startX , startY ) {
375
+ // setup conversion functions
370
376
xa = Axes . getFromId ( gd , shapeOptions . xref ) ;
371
377
ya = Axes . getFromId ( gd , shapeOptions . yref ) ;
372
378
@@ -375,6 +381,7 @@ function setupDragElement(gd, shapePath, shapeOptions, index) {
375
381
p2x = getPixelToData ( gd , xa ) ;
376
382
p2y = getPixelToData ( gd , ya , true ) ;
377
383
384
+ // setup update strings and initial values
378
385
var astr = 'shapes[' + index + ']' ;
379
386
if ( shapeOptions . type === 'path' ) {
380
387
pathIn = shapeOptions . path ;
@@ -392,9 +399,43 @@ function setupDragElement(gd, shapePath, shapeOptions, index) {
392
399
astrY1 = astr + '.y1' ;
393
400
}
394
401
402
+ if ( x0 < x1 ) {
403
+ w0 = x0 ; astrW = astr + '.x0' ; optW = 'x0' ;
404
+ e0 = x1 ; astrE = astr + '.x1' ; optE = 'x1' ;
405
+ }
406
+ else {
407
+ w0 = x1 ; astrW = astr + '.x1' ; optW = 'x1' ;
408
+ e0 = x0 ; astrE = astr + '.x0' ; optE = 'x0' ;
409
+ }
410
+ if ( y0 < y1 ) {
411
+ n0 = y0 ; astrN = astr + '.y0' ; optN = 'y0' ;
412
+ s0 = y1 ; astrS = astr + '.y1' ; optS = 'y1' ;
413
+ }
414
+ else {
415
+ n0 = y1 ; astrN = astr + '.y1' ; optN = 'y1' ;
416
+ s0 = y0 ; astrS = astr + '.y0' ; optS = 'y0' ;
417
+ }
418
+
395
419
update = { } ;
396
420
397
- dragOptions . moveFn = moveShape ;
421
+ // choose 'move' or 'resize'
422
+ // based on initial position of cursor within the drag element
423
+ dragBBox = dragOptions . element . getBoundingClientRect ( ) ;
424
+
425
+ var w = dragBBox . right - dragBBox . left ,
426
+ h = dragBBox . bottom - dragBBox . top ,
427
+ x = startX - dragBBox . left ,
428
+ y = startY - dragBBox . top ,
429
+ cursor = ( w > MINWIDTH && h > MINHEIGHT ) ?
430
+ dragElement . getCursor ( x / w , 1 - y / h ) :
431
+ 'move' ;
432
+
433
+ setCursor ( shapePath , cursor ) ;
434
+
435
+ // possible values 'move', 'sw', 'w', 'se', 'e', 'ne', 'n', 'nw' and 'w'
436
+ dragMode = cursor . split ( '-' ) [ 0 ] ;
437
+
438
+ dragOptions . moveFn = ( dragMode === 'move' ) ? moveShape : resizeShape ;
398
439
}
399
440
400
441
function endDrag ( dragged ) {
@@ -424,6 +465,38 @@ function setupDragElement(gd, shapePath, shapeOptions, index) {
424
465
425
466
shapePath . attr ( 'd' , getPathString ( gd , shapeOptions ) ) ;
426
467
}
468
+
469
+ function resizeShape ( dx , dy ) {
470
+ if ( shapeOptions . type === 'path' ) {
471
+ // TODO: implement path resize
472
+ var moveX = function moveX ( x ) { return p2x ( x2p ( x ) + dx ) ; } ;
473
+ if ( xa && xa . type === 'date' ) moveX = encodeDate ( moveX ) ;
474
+
475
+ var moveY = function moveY ( y ) { return p2y ( y2p ( y ) + dy ) ; } ;
476
+ if ( ya && ya . type === 'date' ) moveY = encodeDate ( moveY ) ;
477
+
478
+ shapeOptions . path = movePath ( pathIn , moveX , moveY ) ;
479
+ update [ astrPath ] = shapeOptions . path ;
480
+ }
481
+ else {
482
+ var newN = ( ~ dragMode . indexOf ( 'n' ) ) ? n0 + dy : n0 ,
483
+ newS = ( ~ dragMode . indexOf ( 's' ) ) ? s0 + dy : s0 ,
484
+ newW = ( ~ dragMode . indexOf ( 'w' ) ) ? w0 + dx : w0 ,
485
+ newE = ( ~ dragMode . indexOf ( 'e' ) ) ? e0 + dx : e0 ;
486
+
487
+ if ( newS - newN > MINHEIGHT ) {
488
+ update [ astrN ] = shapeOptions [ optN ] = p2y ( newN ) ;
489
+ update [ astrS ] = shapeOptions [ optS ] = p2y ( newS ) ;
490
+ }
491
+
492
+ if ( newE - newW > MINWIDTH ) {
493
+ update [ astrW ] = shapeOptions [ optW ] = p2x ( newW ) ;
494
+ update [ astrE ] = shapeOptions [ optE ] = p2x ( newE ) ;
495
+ }
496
+ }
497
+
498
+ shapePath . attr ( 'd' , getPathString ( gd , shapeOptions ) ) ;
499
+ }
427
500
}
428
501
429
502
function getShapeLayer ( gd , index ) {
0 commit comments