index.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { CircleConfig } from "konva/lib/shapes/Circle";
  2. import {
  3. BaseItem,
  4. generateSnapInfos,
  5. getBaseItem,
  6. getRectSnapPoints,
  7. } from "../util.ts";
  8. import { getMouseColors } from "@/utils/colors.ts";
  9. import { lineCenter, Pos } from "@/utils/math.ts";
  10. import { Transform } from "konva/lib/Util";
  11. import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
  12. import { MathUtils } from "three";
  13. export { default as Component } from "./circle.vue";
  14. export { default as TempComponent } from "./temp-circle.vue";
  15. export const shapeName = "圆形";
  16. export const defaultStyle = {
  17. dash: [30, 0],
  18. stroke: "#000000",
  19. strokeWidth: 5,
  20. fontSize: 22,
  21. fixed: true,
  22. align: "center",
  23. fontStyle: "normal",
  24. fontColor: "#000000",
  25. padding: 8,
  26. };
  27. export const addMode = "area";
  28. export const fixedStrokeOptions = [1, 2, 4];
  29. export const getMouseStyle = (data: CircleData) => {
  30. const fillStatus = data.fill && getMouseColors(data.fill);
  31. const strokeStatus = data.stroke && getMouseColors(data.stroke);
  32. const strokeWidth = data.strokeWidth;
  33. return {
  34. default: { stroke: data.stroke, strokeWidth, fill: data.fill },
  35. hover: {
  36. fill: fillStatus && fillStatus.hover,
  37. stroke: strokeStatus && strokeStatus.hover,
  38. },
  39. select: {
  40. fill: fillStatus && fillStatus.select,
  41. stroke: strokeStatus && strokeStatus.select,
  42. },
  43. focus: {
  44. fill: fillStatus && fillStatus.hover,
  45. stroke: strokeStatus && strokeStatus.hover,
  46. },
  47. press: {
  48. fill: fillStatus && fillStatus.press,
  49. stroke: strokeStatus && strokeStatus.press,
  50. },
  51. };
  52. };
  53. export const getSnapInfos = (data: CircleData) => {
  54. return generateSnapInfos(getSnapPoints(data), true, false);
  55. };
  56. export const getSnapPoints = (data: CircleData) => {
  57. const dec = new Transform(data.mat).decompose();
  58. const points = getRectSnapPoints(data.radiusX * 2, data.radiusY * 2).map(
  59. (v) => ({
  60. x: v.x + dec.x,
  61. y: v.y + dec.y,
  62. })
  63. );
  64. // const size = data.radius * 2;
  65. return points;
  66. };
  67. export type CircleData = Partial<typeof defaultStyle> &
  68. BaseItem & {
  69. opacity?: number;
  70. fill?: string;
  71. mat: number[];
  72. radiusX: number;
  73. radiusY: number;
  74. content?: string;
  75. desc?: string
  76. padding?: number;
  77. };
  78. export const dataToConfig = (data: CircleData): CircleConfig => ({
  79. ...defaultStyle,
  80. ...data,
  81. });
  82. export const interactiveToData: InteractiveTo<"circle"> = ({
  83. info,
  84. preset = {},
  85. ...args
  86. }) => {
  87. if (info.cur) {
  88. const item = {
  89. ...defaultStyle,
  90. fill: null,
  91. ...getBaseItem(),
  92. ...preset,
  93. } as unknown as CircleData;
  94. return interactiveFixData({ ...args, info, data: item });
  95. }
  96. };
  97. export const interactiveFixData: InteractiveFix<"circle"> = ({
  98. data,
  99. info,
  100. }) => {
  101. const area = info.cur!;
  102. const sx = Math.abs(area[1].x - area[0].x) / 2;
  103. const sy = Math.abs(area[1].y - area[0].y) / 2;
  104. const center = lineCenter(area);
  105. data.mat = new Transform().translate(center.x, center.y).m;
  106. data.radiusX = sx;
  107. data.radiusY = sy;
  108. return data;
  109. };
  110. export const matResponse = (
  111. { data, mat, increment }: MatResponseProps<"circle">,
  112. initRadius?: Pos
  113. ) => {
  114. if (!initRadius) {
  115. initRadius = {
  116. x: data.radiusX,
  117. y: data.radiusY,
  118. };
  119. }
  120. if (increment) {
  121. mat = mat.copy().multiply(new Transform(data.mat));
  122. }
  123. const dec = mat.decompose();
  124. data.radiusY = dec.scaleY * initRadius.y;
  125. data.radiusX = dec.scaleX * initRadius.x;
  126. data.mat = new Transform()
  127. .translate(dec.x, dec.y)
  128. .rotate(MathUtils.degToRad(dec.rotation)).m;
  129. return data;
  130. };
  131. export const getPredefine = (key: keyof CircleData) => {
  132. if (["fill", "stroke"].includes(key)) {
  133. return { canun: true };
  134. }
  135. };