Brak opisu

index.ts 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. import { SvgHelper } from '../../renderer/SvgHelper';
  2. import { BaseMarker } from '../BaseMarker';
  3. import { RectangularMarkerGrips } from './RectangularMarkerGrips';
  4. import { ResizeGrip } from '../BaseMarker/ResizeGrip';
  5. import { PositionType } from 'fc-whiteboard/src/event/Event';
  6. export class RectangularMarker extends BaseMarker {
  7. public static createMarker = (): RectangularMarker => {
  8. const marker = new RectangularMarker();
  9. marker.setup();
  10. return marker;
  11. };
  12. protected MIN_SIZE = 5;
  13. private controlBox: SVGGElement;
  14. private readonly CB_DISTANCE: number = 10;
  15. private controlRect: SVGRectElement;
  16. private controlGrips: RectangularMarkerGrips;
  17. private activeGrip: ResizeGrip | null;
  18. public endManipulation() {
  19. super.endManipulation();
  20. this.isResizing = false;
  21. this.activeGrip = null;
  22. }
  23. public select() {
  24. super.select();
  25. this.controlBox.style.display = '';
  26. }
  27. public deselect() {
  28. super.deselect();
  29. this.controlBox.style.display = 'none';
  30. }
  31. protected setup() {
  32. super.setup();
  33. this.addControlBox();
  34. }
  35. protected resizeByEvent(x: number, y: number, pos: PositionType) {
  36. this.activeGrip = this.controlGrips[pos];
  37. this.resize(x, y);
  38. }
  39. protected resize(x: number, y: number, onPosition?: (pos: PositionType) => void) {
  40. let translateX = 0;
  41. let translateY = 0;
  42. switch (this.activeGrip) {
  43. case this.controlGrips.topLeft:
  44. this.width -= x;
  45. this.height -= y;
  46. translateX += x;
  47. translateY += y;
  48. if (onPosition) {
  49. onPosition('topLeft');
  50. }
  51. break;
  52. case this.controlGrips.bottomLeft:
  53. this.width -= x;
  54. this.height += y;
  55. translateX += x;
  56. if (onPosition) {
  57. onPosition('bottomLeft');
  58. }
  59. break;
  60. case this.controlGrips.topRight:
  61. this.width += x;
  62. this.height -= y;
  63. translateY += y;
  64. if (onPosition) {
  65. onPosition('topRight');
  66. }
  67. break;
  68. case this.controlGrips.bottomRight:
  69. this.width += x;
  70. this.height += y;
  71. if (onPosition) {
  72. onPosition('bottomRight');
  73. }
  74. break;
  75. case this.controlGrips.centerLeft:
  76. this.width -= x;
  77. translateX += x;
  78. if (onPosition) {
  79. onPosition('centerLeft');
  80. }
  81. break;
  82. case this.controlGrips.centerRight:
  83. this.width += x;
  84. if (onPosition) {
  85. onPosition('centerRight');
  86. }
  87. break;
  88. case this.controlGrips.topCenter:
  89. this.height -= y;
  90. translateY += y;
  91. if (onPosition) {
  92. onPosition('topCenter');
  93. }
  94. break;
  95. case this.controlGrips.bottomCenter:
  96. this.height += y;
  97. if (onPosition) {
  98. onPosition('bottomCenter');
  99. }
  100. break;
  101. default:
  102. break;
  103. }
  104. if (this.width < this.MIN_SIZE) {
  105. const offset = this.MIN_SIZE - this.width;
  106. this.width = this.MIN_SIZE;
  107. if (translateX !== 0) {
  108. translateX -= offset;
  109. }
  110. }
  111. if (this.height < this.MIN_SIZE) {
  112. const offset = this.MIN_SIZE - this.height;
  113. this.height = this.MIN_SIZE;
  114. if (translateY !== 0) {
  115. translateY -= offset;
  116. }
  117. }
  118. if (translateX !== 0 || translateY !== 0) {
  119. const translate = this.visual.transform.baseVal.getItem(0);
  120. translate.setMatrix(translate.matrix.translate(translateX, translateY));
  121. this.visual.transform.baseVal.replaceItem(translate, 0);
  122. }
  123. this.adjustControlBox();
  124. }
  125. protected onTouch(ev: TouchEvent) {
  126. super.onTouch(ev);
  127. }
  128. private addControlBox = () => {
  129. this.controlBox = SvgHelper.createGroup([['class', 'fc-whiteboard-rect-control-box']]);
  130. const translate = SvgHelper.createTransform();
  131. translate.setTranslate(-this.CB_DISTANCE / 2, -this.CB_DISTANCE / 2);
  132. this.controlBox.transform.baseVal.appendItem(translate);
  133. this.addToVisual(this.controlBox);
  134. this.controlRect = SvgHelper.createRect(
  135. this.width + this.CB_DISTANCE,
  136. this.height + this.CB_DISTANCE,
  137. [['class', 'fc-whiteboard-rect-control-rect']]
  138. );
  139. this.controlBox.appendChild(this.controlRect);
  140. this.controlGrips = new RectangularMarkerGrips();
  141. this.addControlGrips();
  142. };
  143. private adjustControlBox = () => {
  144. this.controlRect.setAttribute('width', (this.width + this.CB_DISTANCE).toString());
  145. this.controlRect.setAttribute('height', (this.height + this.CB_DISTANCE).toString());
  146. this.positionGrips();
  147. };
  148. private addControlGrips = () => {
  149. this.controlGrips.topLeft = this.createGrip();
  150. this.controlGrips.topCenter = this.createGrip();
  151. this.controlGrips.topRight = this.createGrip();
  152. this.controlGrips.centerLeft = this.createGrip();
  153. this.controlGrips.centerRight = this.createGrip();
  154. this.controlGrips.bottomLeft = this.createGrip();
  155. this.controlGrips.bottomCenter = this.createGrip();
  156. this.controlGrips.bottomRight = this.createGrip();
  157. this.positionGrips();
  158. };
  159. private createGrip = (): ResizeGrip => {
  160. const grip = new ResizeGrip();
  161. grip.visual.transform.baseVal.appendItem(SvgHelper.createTransform());
  162. this.controlBox.appendChild(grip.visual);
  163. grip.visual.addEventListener('mousedown', this.gripMouseDown);
  164. grip.visual.addEventListener('mousemove', this.gripMouseMove);
  165. grip.visual.addEventListener('mouseup', this.gripMouseUp);
  166. grip.visual.addEventListener('touchstart', this.onTouch, { passive: false });
  167. grip.visual.addEventListener('touchend', this.onTouch, { passive: false });
  168. grip.visual.addEventListener('touchmove', this.onTouch, { passive: false });
  169. return grip;
  170. };
  171. private positionGrips = () => {
  172. const gripSize = this.controlGrips.topLeft.GRIP_SIZE;
  173. const left = -gripSize / 2;
  174. const top = left;
  175. const cx = (this.width + this.CB_DISTANCE) / 2 - gripSize / 2;
  176. const cy = (this.height + this.CB_DISTANCE) / 2 - gripSize / 2;
  177. const bottom = this.height + this.CB_DISTANCE - gripSize / 2;
  178. const right = this.width + this.CB_DISTANCE - gripSize / 2;
  179. this.positionGrip(this.controlGrips.topLeft.visual, left, top);
  180. this.positionGrip(this.controlGrips.topCenter.visual, cx, top);
  181. this.positionGrip(this.controlGrips.topRight.visual, right, top);
  182. this.positionGrip(this.controlGrips.centerLeft.visual, left, cy);
  183. this.positionGrip(this.controlGrips.centerRight.visual, right, cy);
  184. this.positionGrip(this.controlGrips.bottomLeft.visual, left, bottom);
  185. this.positionGrip(this.controlGrips.bottomCenter.visual, cx, bottom);
  186. this.positionGrip(this.controlGrips.bottomRight.visual, right, bottom);
  187. };
  188. private positionGrip = (grip: SVGGraphicsElement, x: number, y: number) => {
  189. const translate = grip.transform.baseVal.getItem(0);
  190. translate.setTranslate(x, y);
  191. grip.transform.baseVal.replaceItem(translate, 0);
  192. };
  193. private gripMouseDown = (ev: MouseEvent) => {
  194. this.isResizing = true;
  195. this.activeGrip = this.controlGrips.findGripByVisual(ev.target as SVGGraphicsElement) || null;
  196. this.previousMouseX = ev.screenX;
  197. this.previousMouseY = ev.screenY;
  198. ev.stopPropagation();
  199. };
  200. private gripMouseUp = (ev: MouseEvent) => {
  201. this.isResizing = false;
  202. this.activeGrip = null;
  203. ev.stopPropagation();
  204. };
  205. private gripMouseMove = (ev: MouseEvent) => {
  206. if (this.isResizing) {
  207. this.manipulate(ev);
  208. }
  209. };
  210. }