index.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. import { ModuleControl } from "queenjs";
  2. import { reactive } from "vue";
  3. import { EditorModule } from "../../module";
  4. import { DesignComp } from "../../objects/DesignTemp/DesignComp";
  5. import * as transforms from "./transforms";
  6. type TransHandle = (this: TransferCtrl, e: MouseEvent) => void;
  7. export type TransCreateFn = (...args: any[]) => {
  8. mousedown?: TransHandle;
  9. mousemove: TransHandle;
  10. mouseup: TransHandle;
  11. };
  12. export class TransferCtrl extends ModuleControl<EditorModule> {
  13. compEl!: HTMLElement;
  14. pageEl!: HTMLElement;
  15. currComp!: DesignComp;
  16. currTransfer!: ReturnType<TransCreateFn>;
  17. currObserver?: MutationObserver;
  18. transforms = transforms;
  19. transEvent = {
  20. startX: 0,
  21. startY: 0,
  22. offsetX: 0,
  23. offsetY: 0,
  24. width: 0,
  25. height: 0,
  26. };
  27. transferStyle = reactive({
  28. top: "",
  29. left: "",
  30. width: "",
  31. height: "",
  32. transform: {
  33. scale: 1,
  34. rotate: "0deg",
  35. translateX: "-50%",
  36. translateY: "-50%",
  37. },
  38. });
  39. originPiont = {
  40. x: 0,
  41. y: 0,
  42. };
  43. init(pageEl: HTMLElement) {
  44. this.currComp = this.module.store.currComp;
  45. this.compEl = this.currComp.$el;
  46. this.pageEl = pageEl;
  47. this.observe();
  48. }
  49. mousedown(e: MouseEvent, type: keyof typeof transforms, currComp?: any) {
  50. if (!currComp) {
  51. currComp = this.store.currComp;
  52. }
  53. this.currComp = currComp;
  54. this.compEl = currComp.$el;
  55. this.transEvent = {
  56. startX: e.clientX,
  57. startY: e.clientY,
  58. offsetX: 0,
  59. offsetY: 0,
  60. width: currComp.layout.size?.[0] || currComp.$el.clientWidth * 2,
  61. height: currComp.layout.size?.[1] || currComp.$el.clientHeight * 2,
  62. };
  63. this.currTransfer = this.transforms[type]();
  64. document.addEventListener("mousemove", this.mousemove);
  65. document.addEventListener("mouseup", this.mouseup);
  66. this.currTransfer.mousedown?.call(this, e);
  67. }
  68. private mousemove = (e: MouseEvent) => {
  69. const { transEvent } = this;
  70. transEvent.offsetX = e.clientX - transEvent.startX;
  71. transEvent.offsetY = e.clientY - transEvent.startY;
  72. this.currTransfer.mousemove.call(this, e);
  73. };
  74. private mouseup = (e: MouseEvent) => {
  75. document.removeEventListener("mousemove", this.mousemove);
  76. document.removeEventListener("mouseup", this.mouseup);
  77. this.currTransfer.mouseup.call(this, e);
  78. };
  79. observe() {
  80. if (this.currObserver) {
  81. this.currObserver.disconnect();
  82. }
  83. this.initStyle();
  84. this.currObserver = new MutationObserver((mutations) => {
  85. mutations.forEach((mutation) => {
  86. if (
  87. mutation.type === "childList" ||
  88. (mutation.type === "attributes" && mutation.attributeName === "style")
  89. ) {
  90. this.initStyle();
  91. }
  92. });
  93. });
  94. this.currObserver.observe(this.compEl, {
  95. attributes: true,
  96. childList: true,
  97. subtree: true,
  98. characterData: true,
  99. });
  100. }
  101. initStyle() {
  102. if (!this.compEl) return;
  103. const rect = this.compEl.getBoundingClientRect();
  104. const pageRect = this.pageEl.getBoundingClientRect();
  105. const transform = getTransform(this.compEl);
  106. const width = this.compEl.clientWidth * transform.scale;
  107. const height = this.compEl.clientHeight * transform.scale;
  108. this.transferStyle.width = width + "px";
  109. this.transferStyle.height = height + "px";
  110. this.transferStyle.top = rect.top + rect.height / 2 - pageRect.top + "px";
  111. this.transferStyle.left = rect.left + rect.width / 2 - pageRect.left + "px";
  112. if (!this.transferStyle.transform) {
  113. this.transferStyle.transform = {
  114. scale: 1,
  115. rotate: "0deg",
  116. translateX: "-50%",
  117. translateY: "-50%",
  118. };
  119. }
  120. this.transferStyle.transform.scale = transform.scale;
  121. this.transferStyle.transform.rotate = transform.rotate;
  122. this.transferStyle.transform.translateY = "-" + height / 2 + "px";
  123. this.originPiont.x = rect.left + rect.width / 2;
  124. this.originPiont.y = rect.top + rect.height / 2;
  125. }
  126. resetStyle() {
  127. Object.keys(this.transferStyle).forEach((key) => {
  128. (this.transferStyle as any)[key] = "";
  129. });
  130. }
  131. destroy() {
  132. this.currObserver?.disconnect();
  133. this.resetStyle();
  134. }
  135. }
  136. export function getTransform(el: HTMLElement) {
  137. const st = getComputedStyle(el, null);
  138. const tr =
  139. st.getPropertyValue("-webkit-transform") ||
  140. st.getPropertyValue("-moz-transform") ||
  141. st.getPropertyValue("-ms-transform") ||
  142. st.getPropertyValue("-o-transform") ||
  143. st.getPropertyValue("transform") ||
  144. "FAIL";
  145. // console.error("Matrix: " + tr);
  146. if (tr == "none")
  147. return {
  148. rotate: "0deg",
  149. scale: 1,
  150. };
  151. // rotation matrix - http://en.wikipedia.org/wiki/Rotation_matrix
  152. const values = tr.split("(")[1].split(")")[0].split(",");
  153. // console.error("values: ", values);
  154. const a: any = values[0];
  155. const b: any = values[1];
  156. const angle = Math.round(Math.atan2(b, a) * (180 / Math.PI));
  157. const scale = Math.sqrt(a * a + b * b);
  158. return {
  159. rotate: `${angle}deg`,
  160. scale,
  161. };
  162. }