@leafer-in/editor 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/editor.cjs CHANGED
@@ -83,6 +83,7 @@ const PathScaler = {
83
83
  const { scalePoints } = PathScaler;
84
84
 
85
85
  const matrix$1 = draw.MatrixHelper.get();
86
+ const { topLeft: topLeft$1, top: top$1, topRight: topRight$1, right: right$2, bottom: bottom$1, left: left$2 } = draw.Direction9;
86
87
  function scaleResize(leaf, scaleX, scaleY) {
87
88
  if (leaf.pathInputed) {
88
89
  scaleResizePath(leaf, scaleX, scaleY);
@@ -95,14 +96,35 @@ function scaleResize(leaf, scaleX, scaleY) {
95
96
  }
96
97
  }
97
98
  function scaleResizeFontSize(leaf, scaleX, scaleY) {
98
- const { width, height } = leaf.__localBoxBounds;
99
- if (scaleX !== 1) {
100
- leaf.fontSize *= scaleX;
101
- leaf.y -= height * (scaleX - scaleY) / 2;
99
+ const { app } = leaf;
100
+ const editor = app && app.editor;
101
+ if (editor.editing) {
102
+ const layout = leaf.__layout;
103
+ let { width, height } = layout.boxBounds;
104
+ width *= (scaleY - scaleX) * (leaf.scaleX < 0 ? -1 : 1);
105
+ height *= (scaleX - scaleY) * (leaf.scaleY < 0 ? -1 : 1);
106
+ switch (editor.resizeDirection) {
107
+ case top$1:
108
+ case bottom$1:
109
+ leaf.fontSize *= scaleY;
110
+ layout.affectScaleOrRotation ? leaf.moveInner(-width / 2, 0) : leaf.x -= width / 2;
111
+ break;
112
+ case left$2:
113
+ case right$2:
114
+ leaf.fontSize *= scaleX;
115
+ layout.affectScaleOrRotation ? leaf.moveInner(0, -height / 2) : leaf.y -= height / 2;
116
+ break;
117
+ case topLeft$1:
118
+ case topRight$1:
119
+ leaf.fontSize *= scaleX;
120
+ layout.affectScaleOrRotation ? leaf.moveInner(0, -height) : leaf.y -= height;
121
+ break;
122
+ default:
123
+ leaf.fontSize *= scaleX;
124
+ }
102
125
  }
103
- else if (scaleY !== 1) {
104
- leaf.fontSize *= scaleY;
105
- leaf.x -= width * (scaleY - scaleX) / 2;
126
+ else {
127
+ leaf.fontSize *= scaleX;
106
128
  }
107
129
  }
108
130
  function scaleResizePath(leaf, scaleX, scaleY) {
@@ -435,7 +457,7 @@ class EditSelect extends draw.Group {
435
457
  }
436
458
  onPointerMove(e) {
437
459
  const { app, editor } = this;
438
- if (this.running && !this.isMoveMode && app.config.pointer.hover && !app.interaction.dragging) {
460
+ if (this.running && !this.isMoveMode && app.interaction.canHover && !app.interaction.dragging) {
439
461
  const find = this.findUI(e);
440
462
  editor.hoverTarget = editor.hasItem(find) ? null : find;
441
463
  }
@@ -444,15 +466,27 @@ class EditSelect extends draw.Group {
444
466
  }
445
467
  }
446
468
  onBeforeDown(e) {
469
+ if (e.multiTouch)
470
+ return;
447
471
  const { select } = this.editor.mergeConfig;
448
- if (select === 'press')
449
- this.checkAndSelect(e);
472
+ if (select === 'press') {
473
+ if (this.app.config.mobile) {
474
+ this.waitSelect = () => this.checkAndSelect(e);
475
+ }
476
+ else {
477
+ this.checkAndSelect(e);
478
+ }
479
+ }
450
480
  }
451
481
  onTap(e) {
482
+ if (e.multiTouch)
483
+ return;
452
484
  const { editor } = this;
453
485
  const { select } = editor.mergeConfig;
454
486
  if (select === 'tap')
455
487
  this.checkAndSelect(e);
488
+ else if (this.waitSelect)
489
+ this.waitSelect();
456
490
  if (this.needRemoveItem) {
457
491
  editor.removeItem(this.needRemoveItem);
458
492
  }
@@ -483,6 +517,10 @@ class EditSelect extends draw.Group {
483
517
  }
484
518
  }
485
519
  onDragStart(e) {
520
+ if (e.multiTouch)
521
+ return;
522
+ if (this.waitSelect)
523
+ this.waitSelect();
486
524
  if (this.allowDrag(e)) {
487
525
  const { editor } = this;
488
526
  const { stroke, area } = editor.mergeConfig;
@@ -494,10 +532,10 @@ class EditSelect extends draw.Group {
494
532
  }
495
533
  }
496
534
  onDrag(e) {
497
- if (this.editor.dragging) {
498
- this.onDragEnd();
535
+ if (e.multiTouch)
499
536
  return;
500
- }
537
+ if (this.editor.dragging)
538
+ return this.onDragEnd(e);
501
539
  if (this.dragging) {
502
540
  const { editor } = this;
503
541
  const total = e.getInnerTotal(this);
@@ -521,7 +559,9 @@ class EditSelect extends draw.Group {
521
559
  }
522
560
  }
523
561
  }
524
- onDragEnd() {
562
+ onDragEnd(e) {
563
+ if (e.multiTouch)
564
+ return;
525
565
  if (this.dragging)
526
566
  this.originList = null, this.selectArea.visible = false;
527
567
  }
@@ -567,7 +607,7 @@ class EditSelect extends draw.Group {
567
607
  app.on_(core.PointerEvent.MOVE, this.onPointerMove, this),
568
608
  app.on_(core.PointerEvent.BEFORE_DOWN, this.onBeforeDown, this),
569
609
  app.on_(core.PointerEvent.TAP, this.onTap, this),
570
- app.on_(core.DragEvent.START, this.onDragStart, this),
610
+ app.on_(core.DragEvent.START, this.onDragStart, this, true),
571
611
  app.on_(core.DragEvent.DRAG, this.onDrag, this),
572
612
  app.on_(core.DragEvent.END, this.onDragEnd, this),
573
613
  app.on_(core.MoveEvent.MOVE, this.onAutoMove, this),
@@ -590,22 +630,32 @@ class EditSelect extends draw.Group {
590
630
 
591
631
  const { topLeft, top, topRight, right: right$1, bottomRight, bottom, bottomLeft, left: left$1 } = draw.Direction9;
592
632
  const { toPoint } = draw.AroundHelper;
633
+ const { within } = draw.MathHelper;
593
634
  const EditDataHelper = {
594
- getScaleData(bounds, direction, pointMove, lockRatio, around) {
635
+ getScaleData(element, startBounds, direction, totalMove, lockRatio, around, flipable, scaleMode) {
595
636
  let align, origin = {}, scaleX = 1, scaleY = 1;
596
- const { width, height } = bounds;
637
+ const { boxBounds, widthRange, heightRange } = element;
638
+ const { width, height } = startBounds;
597
639
  if (around) {
598
- pointMove.x *= 2;
599
- pointMove.y *= 2;
600
- }
601
- if (Math.abs(pointMove.x) === width)
602
- pointMove.x += 0.1;
603
- if (Math.abs(pointMove.y) === height)
604
- pointMove.y += 0.1;
605
- const topScale = (-pointMove.y + height) / height;
606
- const rightScale = (pointMove.x + width) / width;
607
- const bottomScale = (pointMove.y + height) / height;
608
- const leftScale = (-pointMove.x + width) / width;
640
+ totalMove.x *= 2;
641
+ totalMove.y *= 2;
642
+ }
643
+ const originChangedScaleX = element.scaleX / startBounds.scaleX;
644
+ const originChangedScaleY = element.scaleY / startBounds.scaleY;
645
+ const signX = originChangedScaleX < 0 ? -1 : 1;
646
+ const signY = originChangedScaleY < 0 ? -1 : 1;
647
+ const changedScaleX = scaleMode ? originChangedScaleX : signX * boxBounds.width / width;
648
+ const changedScaleY = scaleMode ? originChangedScaleY : signY * boxBounds.height / height;
649
+ totalMove.x *= scaleMode ? originChangedScaleX : signX;
650
+ totalMove.y *= scaleMode ? originChangedScaleY : signY;
651
+ if (Math.abs(totalMove.x) === width)
652
+ totalMove.x += 0.1;
653
+ if (Math.abs(totalMove.y) === height)
654
+ totalMove.y += 0.1;
655
+ const topScale = (-totalMove.y + height) / height;
656
+ const rightScale = (totalMove.x + width) / width;
657
+ const bottomScale = (totalMove.y + height) / height;
658
+ const leftScale = (-totalMove.x + width) / width;
609
659
  switch (direction) {
610
660
  case top:
611
661
  scaleY = topScale;
@@ -646,12 +696,41 @@ const EditDataHelper = {
646
696
  if (lockRatio) {
647
697
  const unlockSide = lockRatio === 'corner' && direction % 2;
648
698
  if (!unlockSide) {
649
- const scale = Math.sqrt(Math.abs(scaleX * scaleY));
699
+ let scale;
700
+ switch (direction) {
701
+ case top:
702
+ case bottom:
703
+ scale = scaleY;
704
+ break;
705
+ case left$1:
706
+ case right$1:
707
+ scale = scaleX;
708
+ break;
709
+ default:
710
+ scale = Math.sqrt(Math.abs(scaleX * scaleY));
711
+ }
650
712
  scaleX = scaleX < 0 ? -scale : scale;
651
713
  scaleY = scaleY < 0 ? -scale : scale;
652
714
  }
653
715
  }
654
- toPoint(around || align, bounds, origin);
716
+ scaleX /= changedScaleX;
717
+ scaleY /= changedScaleY;
718
+ if (!flipable) {
719
+ const { worldTransform } = element;
720
+ if (scaleX < 0)
721
+ scaleX = 1 / boxBounds.width / worldTransform.scaleX;
722
+ if (scaleY < 0)
723
+ scaleY = 1 / boxBounds.height / worldTransform.scaleY;
724
+ }
725
+ if (widthRange) {
726
+ const nowWidth = boxBounds.width * element.scaleX;
727
+ scaleX = within(nowWidth * scaleX, widthRange) / nowWidth;
728
+ }
729
+ if (heightRange) {
730
+ const nowHeight = boxBounds.height * element.scaleY;
731
+ scaleY = within(nowHeight * scaleY, heightRange) / nowHeight;
732
+ }
733
+ toPoint(around || align, boxBounds, origin);
655
734
  return { origin, scaleX, scaleY, direction, lockRatio, around };
656
735
  },
657
736
  getRotateData(bounds, direction, current, last, around) {
@@ -772,6 +851,11 @@ function updateCursor(editor, e) {
772
851
  return;
773
852
  if (point.name === 'circle')
774
853
  return;
854
+ if (point.pointType === 'button') {
855
+ if (!point.cursor)
856
+ point.cursor = 'pointer';
857
+ return;
858
+ }
775
859
  let { rotation } = editBox;
776
860
  const { resizeCursor, rotateCursor, skewCursor, resizeable, rotateable, skewable } = editor.mergeConfig;
777
861
  const { pointType } = point, { flippedX, flippedY } = editBox;
@@ -840,9 +924,8 @@ class EditBox extends draw.Group {
840
924
  resizePoints.push(resizePoint);
841
925
  this.listenPointEvents(resizePoint, 'resize', i);
842
926
  }
843
- buttons.add(circle);
844
927
  this.listenPointEvents(circle, 'rotate', 2);
845
- view.addMany(...rotatePoints, rect, buttons, ...resizeLines, ...resizePoints);
928
+ view.addMany(...rotatePoints, rect, circle, buttons, ...resizeLines, ...resizePoints);
846
929
  this.add(view);
847
930
  }
848
931
  load() {
@@ -858,9 +941,9 @@ class EditBox extends draw.Group {
858
941
  if (!(i % 2))
859
942
  resizeP.rotation = (i / 2) * 90;
860
943
  }
861
- circle.set(this.getPointStyle(mergeConfig.rotatePoint || pointsStyle[0]));
944
+ circle.set(this.getPointStyle(mergeConfig.circle || mergeConfig.rotatePoint || pointsStyle[0]));
862
945
  rect.set(Object.assign({ stroke, strokeWidth }, (mergeConfig.rect || {})));
863
- rect.hittable = !single && moveable;
946
+ rect.hittable = !single && !!moveable;
864
947
  element.syncEventer = (single && moveable) ? rect : null;
865
948
  this.app.interaction.bottomList = (single && moveable) ? [{ target: rect, proxy: element }] : null;
866
949
  }
@@ -869,7 +952,7 @@ class EditBox extends draw.Group {
869
952
  if (this.view.worldOpacity) {
870
953
  const { mergeConfig } = this.editor;
871
954
  const { width, height } = bounds;
872
- const { rect, circle, resizePoints, rotatePoints, resizeLines } = this;
955
+ const { rect, circle, buttons, resizePoints, rotatePoints, resizeLines } = this;
873
956
  const { middlePoint, resizeable, rotateable, hideOnSmall } = mergeConfig;
874
957
  const smallSize = typeof hideOnSmall === 'number' ? hideOnSmall : 10;
875
958
  const showPoints = !(hideOnSmall && width < smallSize && height < smallSize);
@@ -899,19 +982,25 @@ class EditBox extends draw.Group {
899
982
  }
900
983
  }
901
984
  }
902
- circle.visible = showPoints && rotateable && !!mergeConfig.rotatePoint;
985
+ circle.visible = showPoints && rotateable && !!(mergeConfig.circle || mergeConfig.rotatePoint);
986
+ if (circle.visible)
987
+ this.layoutCircle(mergeConfig);
903
988
  if (rect.path)
904
989
  rect.path = null;
905
990
  rect.set(Object.assign(Object.assign({}, bounds), { visible: true }));
906
- const buttonVisible = showPoints && (circle.visible || this.buttons.children.length > 1);
907
- this.buttons.visible = buttonVisible;
908
- if (buttonVisible)
909
- this.layoutButtons();
991
+ buttons.visible = showPoints && buttons.children.length > 0;
992
+ if (buttons.visible)
993
+ this.layoutButtons(mergeConfig);
910
994
  }
911
995
  }
912
- layoutButtons() {
913
- const { buttons, resizePoints } = this;
914
- const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = this.editor.mergeConfig;
996
+ layoutCircle(config) {
997
+ const { circleDirection, circleMargin, buttonsMargin, buttonsDirection, middlePoint } = config;
998
+ const direction = fourDirection.indexOf(circleDirection || ((this.buttons.children.length && buttonsDirection === 'bottom') ? 'top' : 'bottom'));
999
+ this.setButtonPosition(this.circle, direction, circleMargin || buttonsMargin, !!middlePoint);
1000
+ }
1001
+ layoutButtons(config) {
1002
+ const { buttons } = this;
1003
+ const { buttonsDirection, buttonsFixed, buttonsMargin, middlePoint } = config;
915
1004
  const { flippedX, flippedY } = this;
916
1005
  let index = fourDirection.indexOf(buttonsDirection);
917
1006
  if ((index % 2 && flippedX) || ((index + 1) % 2 && flippedY)) {
@@ -919,11 +1008,18 @@ class EditBox extends draw.Group {
919
1008
  index = (index + 2) % 4;
920
1009
  }
921
1010
  const direction = buttonsFixed ? EditDataHelper.getRotateDirection(index, this.flippedOne ? this.rotation : -this.rotation, 4) : index;
922
- const point = resizePoints[direction * 2 + 1];
1011
+ this.setButtonPosition(buttons, direction, buttonsMargin, !!middlePoint);
1012
+ if (buttonsFixed)
1013
+ buttons.rotation = (direction - index) * 90;
1014
+ buttons.scaleX = flippedX ? -1 : 1;
1015
+ buttons.scaleY = flippedY ? -1 : 1;
1016
+ }
1017
+ setButtonPosition(buttons, direction, buttonsMargin, useMiddlePoint) {
1018
+ const point = this.resizePoints[direction * 2 + 1];
923
1019
  const useX = direction % 2;
924
1020
  const sign = (!direction || direction === 3) ? -1 : 1;
925
- const useWidth = index % 2;
926
- const margin = (buttonsMargin + (useWidth ? ((middlePoint ? point.width : 0) + buttons.boxBounds.width) : ((middlePoint ? point.height : 0) + buttons.boxBounds.height)) / 2) * sign;
1021
+ const useWidth = direction % 2;
1022
+ const margin = (buttonsMargin + (useWidth ? ((useMiddlePoint ? point.width : 0) + buttons.boxBounds.width) : ((useMiddlePoint ? point.height : 0) + buttons.boxBounds.height)) / 2) * sign;
927
1023
  if (useX) {
928
1024
  buttons.x = point.x + margin;
929
1025
  buttons.y = point.y;
@@ -932,11 +1028,6 @@ class EditBox extends draw.Group {
932
1028
  buttons.x = point.x;
933
1029
  buttons.y = point.y + margin;
934
1030
  }
935
- if (buttonsFixed) {
936
- buttons.rotation = (direction - index) * 90;
937
- buttons.scaleX = flippedX ? -1 : 1;
938
- buttons.scaleY = flippedY ? -1 : 1;
939
- }
940
1031
  }
941
1032
  unload() {
942
1033
  this.visible = false;
@@ -963,18 +1054,23 @@ class EditBox extends draw.Group {
963
1054
  }
964
1055
  onDragStart(e) {
965
1056
  this.dragging = true;
1057
+ const { editor } = this;
966
1058
  if (e.current.name === 'rect') {
967
- const { editor } = this;
968
1059
  this.moving = true;
969
1060
  editor.dragStartPoint = { x: editor.element.x, y: editor.element.y };
970
1061
  editor.opacity = editor.mergeConfig.hideOnMove ? 0 : 1;
971
1062
  }
1063
+ else if (e.current.pointType === 'resize') {
1064
+ editor.dragStartBounds = Object.assign({}, editor.element.getLayoutBounds('box', 'local'));
1065
+ editor.resizeDirection = e.current.direction;
1066
+ }
972
1067
  }
973
1068
  onDragEnd(e) {
974
1069
  this.dragging = false;
975
1070
  this.moving = false;
976
1071
  if (e.current.name === 'rect')
977
1072
  this.editor.opacity = 1;
1073
+ this.editor.resizeDirection = undefined;
978
1074
  }
979
1075
  onDrag(e) {
980
1076
  const { editor } = this;
@@ -983,7 +1079,7 @@ class EditBox extends draw.Group {
983
1079
  if (editor.mergeConfig.rotateable)
984
1080
  editor.onRotate(e);
985
1081
  }
986
- else {
1082
+ else if (point.pointType === 'resize') {
987
1083
  editor.onScale(e);
988
1084
  }
989
1085
  updateCursor(editor, e);
@@ -1047,8 +1143,6 @@ class EditBox extends draw.Group {
1047
1143
  rect.on_(core.DragEvent.START, this.onDragStart, this),
1048
1144
  rect.on_(core.DragEvent.DRAG, editor.onMove, editor),
1049
1145
  rect.on_(core.DragEvent.END, this.onDragEnd, this),
1050
- rect.on_(core.ZoomEvent.BEFORE_ZOOM, editor.onScale, editor, true),
1051
- rect.on_(core.RotateEvent.BEFORE_ROTATE, editor.onRotate, editor, true),
1052
1146
  rect.on_(core.PointerEvent.ENTER, () => updateMoveCursor(editor)),
1053
1147
  rect.on_(core.PointerEvent.DOUBLE_TAP, this.onDoubleTap, this),
1054
1148
  rect.on_(core.PointerEvent.LONG_PRESS, this.onLongPress, this)
@@ -1078,7 +1172,7 @@ class EditMask extends draw.UI {
1078
1172
  const { rect } = editor.editBox;
1079
1173
  const { width, height } = rect.__;
1080
1174
  canvas.resetTransform();
1081
- canvas.fillWorld(canvas.bounds, mask);
1175
+ canvas.fillWorld(canvas.bounds, mask === true ? 'rgba(0,0,0,0.8)' : mask);
1082
1176
  canvas.setWorld(rect.__world, options.matrix);
1083
1177
  canvas.clearRect(0, 0, width, height);
1084
1178
  }
@@ -1163,6 +1257,7 @@ const config = {
1163
1257
  boxSelect: true,
1164
1258
  moveable: true,
1165
1259
  resizeable: true,
1260
+ flipable: true,
1166
1261
  rotateable: true,
1167
1262
  skewable: true
1168
1263
  };
@@ -1320,7 +1415,7 @@ class Editor extends draw.Group {
1320
1415
  get buttons() { return this.editBox.buttons; }
1321
1416
  constructor(userConfig, data) {
1322
1417
  super(data);
1323
- this.config = config;
1418
+ this.config = draw.DataHelper.clone(config);
1324
1419
  this.leafList = new draw.LeafList();
1325
1420
  this.openedGroupList = new draw.LeafList();
1326
1421
  this.simulateTarget = new draw.Rect({ visible: false });
@@ -1384,29 +1479,39 @@ class Editor extends draw.Group {
1384
1479
  return this.mergeConfig.editSize;
1385
1480
  }
1386
1481
  onMove(e) {
1387
- const total = { x: e.totalX, y: e.totalY };
1388
- if (e.shiftKey) {
1389
- if (Math.abs(total.x) > Math.abs(total.y))
1390
- total.y = 0;
1391
- else
1392
- total.x = 0;
1482
+ if (e instanceof core.MoveEvent) {
1483
+ if (e.moveType !== 'drag') {
1484
+ const { moveable, resizeable } = this.mergeConfig;
1485
+ const move = e.getLocalMove(this.element);
1486
+ if (moveable === 'move')
1487
+ e.stop(), this.move(move.x, move.y);
1488
+ else if (resizeable === 'zoom')
1489
+ e.stop();
1490
+ }
1491
+ }
1492
+ else {
1493
+ const total = { x: e.totalX, y: e.totalY };
1494
+ if (e.shiftKey) {
1495
+ if (Math.abs(total.x) > Math.abs(total.y))
1496
+ total.y = 0;
1497
+ else
1498
+ total.x = 0;
1499
+ }
1500
+ this.move(core.DragEvent.getValidMove(this.element, this.dragStartPoint, total));
1393
1501
  }
1394
- this.move(core.DragEvent.getValidMove(this.element, this.dragStartPoint, total));
1395
1502
  }
1396
1503
  onScale(e) {
1397
1504
  const { element } = this;
1505
+ let { around, lockRatio, resizeable, flipable, editSize } = this.mergeConfig;
1398
1506
  if (e instanceof core.ZoomEvent) {
1399
- if (this.mergeConfig.resizeable === 'zoom') {
1400
- e.stop();
1401
- this.scaleOf(element.getInnerPoint(e), e.scale, e.scale);
1402
- }
1507
+ if (resizeable === 'zoom')
1508
+ e.stop(), this.scaleOf(element.getInnerPoint(e), e.scale, e.scale);
1403
1509
  }
1404
1510
  else {
1405
1511
  const { direction } = e.current;
1406
- let { around, lockRatio } = this.mergeConfig;
1407
1512
  if (e.shiftKey || element.lockRatio)
1408
1513
  lockRatio = true;
1409
- const data = EditDataHelper.getScaleData(element.boxBounds, direction, e.getInnerMove(element), lockRatio, EditDataHelper.getAround(around, e.altKey));
1514
+ const data = EditDataHelper.getScaleData(element, this.dragStartBounds, direction, e.getInnerTotal(element), lockRatio, EditDataHelper.getAround(around, e.altKey), flipable, this.multiple || editSize === 'scale');
1410
1515
  if (this.editTool.onScaleWithDrag) {
1411
1516
  data.drag = e;
1412
1517
  this.scaleWithDrag(data);
@@ -1417,23 +1522,21 @@ class Editor extends draw.Group {
1417
1522
  }
1418
1523
  }
1419
1524
  onRotate(e) {
1420
- const { skewable, around, rotateGap } = this.mergeConfig;
1525
+ const { skewable, rotateable, around, rotateGap } = this.mergeConfig;
1421
1526
  const { direction, name } = e.current;
1422
1527
  if (skewable && name === 'resize-line')
1423
1528
  return this.onSkew(e);
1424
1529
  const { element } = this;
1425
1530
  let origin, rotation;
1426
1531
  if (e instanceof core.RotateEvent) {
1427
- if (this.mergeConfig.rotateable === 'rotate') {
1428
- e.stop();
1429
- rotation = e.rotation, origin = element.getInnerPoint(e);
1430
- }
1532
+ if (rotateable === 'rotate')
1533
+ e.stop(), rotation = e.rotation, origin = element.getInnerPoint(e);
1431
1534
  else
1432
1535
  return;
1433
1536
  }
1434
1537
  else {
1435
1538
  const last = { x: e.x - e.moveX, y: e.y - e.moveY };
1436
- const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (around || 'center'));
1539
+ const data = EditDataHelper.getRotateData(element.boxBounds, direction, e.getInner(element), element.getInnerPoint(last), e.shiftKey ? null : (element.around || element.origin || around || 'center'));
1437
1540
  rotation = data.rotation;
1438
1541
  origin = data.origin;
1439
1542
  }
@@ -1467,8 +1570,7 @@ class Editor extends draw.Group {
1467
1570
  if (!this.mergeConfig.resizeable || this.element.locked)
1468
1571
  return;
1469
1572
  const { element } = this;
1470
- const worldOrigin = element.getWorldPoint(data.origin);
1471
- const event = new EditorScaleEvent(EditorScaleEvent.SCALE, Object.assign(Object.assign({}, data), { target: element, editor: this, worldOrigin }));
1573
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, Object.assign(Object.assign({}, data), { target: element, editor: this, worldOrigin: element.getWorldPoint(data.origin) }));
1472
1574
  this.editTool.onScaleWithDrag(event);
1473
1575
  this.emitEvent(event);
1474
1576
  }
@@ -1476,28 +1578,28 @@ class Editor extends draw.Group {
1476
1578
  if (!this.mergeConfig.resizeable || this.element.locked)
1477
1579
  return;
1478
1580
  const { element } = this;
1479
- const worldOrigin = element.getWorldPoint(draw.LeafHelper.getInnerOrigin(element, origin));
1480
- let transform;
1481
- if (this.multiple) {
1482
- const oldMatrix = new draw.Matrix(element.worldTransform);
1483
- element.scaleOf(origin, scaleX, scaleY);
1484
- transform = new draw.Matrix(element.worldTransform).divide(oldMatrix);
1485
- }
1581
+ const worldOrigin = this.getWorldOrigin(origin);
1582
+ const transform = this.multiple && this.getChangedTransform(() => element.scaleOf(origin, scaleX, scaleY));
1486
1583
  const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX, scaleY, transform });
1487
1584
  this.editTool.onScale(event);
1488
1585
  this.emitEvent(event);
1489
1586
  }
1587
+ flip(axis) {
1588
+ if (this.element.locked)
1589
+ return;
1590
+ const { element } = this;
1591
+ const worldOrigin = this.getWorldOrigin('center');
1592
+ const transform = this.multiple ? this.getChangedTransform(() => element.flip(axis)) : new draw.Matrix(draw.LeafHelper.getFlipTransform(element, axis));
1593
+ const event = new EditorScaleEvent(EditorScaleEvent.SCALE, { target: element, editor: this, worldOrigin, scaleX: axis === 'x' ? -1 : 1, scaleY: axis === 'y' ? -1 : 1, transform });
1594
+ this.editTool.onScale(event);
1595
+ this.emitEvent(event);
1596
+ }
1490
1597
  rotateOf(origin, rotation) {
1491
1598
  if (!this.mergeConfig.rotateable || this.element.locked)
1492
1599
  return;
1493
1600
  const { element } = this;
1494
- const worldOrigin = element.getWorldPoint(draw.LeafHelper.getInnerOrigin(element, origin));
1495
- let transform;
1496
- if (this.multiple) {
1497
- const oldMatrix = new draw.Matrix(element.worldTransform);
1498
- element.rotateOf(origin, rotation);
1499
- transform = new draw.Matrix(element.worldTransform).divide(oldMatrix);
1500
- }
1601
+ const worldOrigin = this.getWorldOrigin(origin);
1602
+ const transform = this.multiple && this.getChangedTransform(() => element.rotateOf(origin, rotation));
1501
1603
  const event = new EditorRotateEvent(EditorRotateEvent.ROTATE, { target: element, editor: this, worldOrigin, rotation, transform });
1502
1604
  this.editTool.onRotate(event);
1503
1605
  this.emitEvent(event);
@@ -1506,19 +1608,21 @@ class Editor extends draw.Group {
1506
1608
  if (!this.mergeConfig.skewable || this.element.locked)
1507
1609
  return;
1508
1610
  const { element } = this;
1509
- const worldOrigin = element.getWorldPoint(draw.LeafHelper.getInnerOrigin(element, origin));
1510
- let transform;
1511
- if (this.multiple) {
1512
- const oldMatrix = new draw.Matrix(element.worldTransform);
1513
- element.skewOf(origin, skewX, skewY);
1514
- transform = new draw.Matrix(element.worldTransform).divide(oldMatrix);
1515
- }
1516
- const event = new EditorSkewEvent(EditorSkewEvent.SKEW, {
1517
- target: element, editor: this, skewX, skewY, transform, worldOrigin
1518
- });
1611
+ const worldOrigin = this.getWorldOrigin(origin);
1612
+ const transform = this.multiple && this.getChangedTransform(() => element.skewOf(origin, skewX, skewY));
1613
+ const event = new EditorSkewEvent(EditorSkewEvent.SKEW, { target: element, editor: this, worldOrigin, skewX, skewY, transform });
1519
1614
  this.editTool.onSkew(event);
1520
1615
  this.emitEvent(event);
1521
1616
  }
1617
+ getWorldOrigin(origin) {
1618
+ return this.element.getWorldPoint(draw.LeafHelper.getInnerOrigin(this.element, origin));
1619
+ }
1620
+ getChangedTransform(func) {
1621
+ const { element } = this;
1622
+ const oldMatrix = new draw.Matrix(element.worldTransform);
1623
+ func();
1624
+ return new draw.Matrix(element.worldTransform).divide(oldMatrix);
1625
+ }
1522
1626
  group(userGroup) {
1523
1627
  if (this.multiple) {
1524
1628
  this.target = EditorHelper.group(this.list, this.element, userGroup);
@@ -1629,6 +1733,9 @@ class Editor extends draw.Group {
1629
1733
  if (!this.targetEventIds.length) {
1630
1734
  const { leafer } = this.list[0];
1631
1735
  this.targetEventIds = [
1736
+ this.app.on_(core.MoveEvent.BEFORE_MOVE, this.onMove, this, true),
1737
+ this.app.on_(core.ZoomEvent.BEFORE_ZOOM, this.onScale, this, true),
1738
+ this.app.on_(core.RotateEvent.BEFORE_ROTATE, this.onRotate, this, true),
1632
1739
  leafer.on_(draw.RenderEvent.START, this.update, this),
1633
1740
  leafer.on_([core.KeyEvent.HOLD, core.KeyEvent.UP], (e) => { updateCursor(this, e); }),
1634
1741
  leafer.on_(core.KeyEvent.DOWN, this.editBox.onArrow, this.editBox)