act.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { Path } from "konva/lib/shapes/Path";
  2. import { Rect } from "konva/lib/shapes/Rect";
  3. import { getRealAbsoluteSize } from "./shape-helper";
  4. import { Group } from "konva/lib/Group";
  5. import { KonvaEventObject } from "konva/lib/Node";
  6. export type SVGPaths = (
  7. | string
  8. | { fill?: string; stroke?: string; strokeWidth?: number; data: string }
  9. )[];
  10. const temp = document.createElement("div");
  11. export const analysisSvg = (
  12. svgString: string
  13. ): Pick<PathsToActShapeProps, "paths" | "size"> => {
  14. temp.innerHTML = svgString;
  15. const svg = temp.querySelector("svg");
  16. const size = [svg.width.baseVal.value, svg.height.baseVal.value];
  17. const paths = Array.from(svg.querySelectorAll("path"));
  18. const pathDatas = paths.map((path) => {
  19. const fill = path.getAttribute("fill");
  20. const data = path.getAttribute("d");
  21. const stroke = path.getAttribute("stroke");
  22. const strokeWidth = path.getAttribute("stroke-width");
  23. return {
  24. fill,
  25. data,
  26. stroke,
  27. strokeWidth: strokeWidth && Number(strokeWidth),
  28. };
  29. });
  30. return {
  31. paths: pathDatas,
  32. size,
  33. };
  34. };
  35. export type PathsToActShapeProps = {
  36. paths: SVGPaths;
  37. size: number[];
  38. realWidth?: number;
  39. offset?: number[];
  40. strokeWidth?: number;
  41. fixed?: boolean;
  42. strokeColor?: string;
  43. };
  44. export const pathsToActShape = (props: PathsToActShapeProps, test = false) => {
  45. const size = props.size;
  46. const realSize = props.realWidth || props.size[0];
  47. const scale = realSize / size[0];
  48. const realBound = size.map((p) => p * scale);
  49. const offset = (props.offset || [0, 0]).map((v) => v * scale);
  50. const strokeWidth = props.strokeWidth ? props.strokeWidth * scale : 1;
  51. const strokeColor = props.strokeColor || "#000";
  52. const pathAttribs = props.paths.map((path) => {
  53. if (typeof path === "string") {
  54. return {
  55. strokeWidth,
  56. stroke: strokeColor,
  57. fill: strokeColor,
  58. data: path,
  59. };
  60. } else {
  61. return path;
  62. }
  63. });
  64. const paths = pathAttribs.map(
  65. (path, ndx) =>
  66. new Path({
  67. data: path.data,
  68. id: `path-${ndx}`,
  69. name: `path`,
  70. strokeScaleEnabled: !!props.fixed,
  71. scale: { x: scale, y: scale },
  72. })
  73. );
  74. const common = () => {
  75. paths.forEach((path, ndx) => {
  76. const attrib = pathAttribs[ndx];
  77. attrib.fill && path.fill(attrib.fill);
  78. attrib.stroke && path.stroke(attrib.stroke);
  79. attrib.strokeWidth && path.strokeWidth(attrib.strokeWidth);
  80. });
  81. };
  82. const rect = new Rect({
  83. x: offset[0],
  84. y: offset[1],
  85. name: "rect",
  86. width: realBound[0],
  87. height: realBound[1],
  88. fill: `rgba(0, 0, 0, ${test ? 0.3 : 0})`,
  89. });
  90. const setStyle = () => {
  91. let [width, height] = getRealAbsoluteSize(group, [1, 1]);
  92. group.scale({ x: width, y: height });
  93. };
  94. const offsetGroup = new Group();
  95. offsetGroup.add(...paths, rect);
  96. offsetGroup.x(-realBound[0] / 2);
  97. offsetGroup.y(-realBound[1] / 2);
  98. const group = new Group();
  99. group.add(offsetGroup);
  100. return {
  101. getSize: () => {
  102. const size = rect.getSize();
  103. if (props.fixed) {
  104. let [scale] = getRealAbsoluteSize(group, [1, 1]);
  105. return [size.width * scale, size.height * scale];
  106. }
  107. return [size.width, size.height];
  108. },
  109. shape: group,
  110. setData(data) {
  111. group.position(data);
  112. props.fixed && setStyle();
  113. if (data.rotate) {
  114. group.rotation(data.rotate);
  115. }
  116. },
  117. common,
  118. };
  119. };
  120. export const getTouchOffset = (ev: KonvaEventObject<any>) => {
  121. const dom = ev.evt.target as HTMLElement;
  122. const rect = dom.getBoundingClientRect();
  123. const offsetX = ev.evt.changedTouches[0].pageX - rect.left;
  124. const offsetY = ev.evt.changedTouches[0].pageY - rect.top;
  125. return {
  126. offsetX,
  127. offsetY,
  128. };
  129. };