index.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. align: "center",
  22. fontStyle: "normal",
  23. fontColor: '#000000',
  24. padding: 8
  25. };
  26. export const addMode = "area";
  27. export const getMouseStyle = (data: CircleData) => {
  28. const fillStatus = data.fill && getMouseColors(data.fill);
  29. const strokeStatus = data.stroke && getMouseColors(data.stroke);
  30. const strokeWidth = data.strokeWidth
  31. return {
  32. default: { stroke: data.stroke, strokeWidth },
  33. hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus && strokeStatus.hover },
  34. select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus && strokeStatus.select },
  35. focus: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus && strokeStatus.hover },
  36. press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus && strokeStatus.press },
  37. };
  38. };
  39. export const getSnapInfos = (data: CircleData) => {
  40. return generateSnapInfos(getSnapPoints(data), true, false);
  41. };
  42. export const getSnapPoints = (data: CircleData) => {
  43. const dec = new Transform(data.mat).decompose()
  44. const points = getRectSnapPoints(data.radiusX * 2, data.radiusY * 2).map((v) => ({
  45. x: v.x + dec.x,
  46. y: v.y + dec.y,
  47. }));
  48. // const size = data.radius * 2;
  49. return points
  50. }
  51. export type CircleData = Partial<typeof defaultStyle> &
  52. BaseItem & {
  53. opacity?: number,
  54. fill?: string
  55. mat: number[];
  56. radiusX: number
  57. radiusY: number
  58. content?: string;
  59. padding?: number
  60. };
  61. export const dataToConfig = (data: CircleData): CircleConfig => ({
  62. ...defaultStyle,
  63. ...data,
  64. });
  65. export const interactiveToData: InteractiveTo<'circle'> = ({
  66. info,
  67. preset = {},
  68. ...args
  69. }) => {
  70. if (info.cur) {
  71. const item = {
  72. ...defaultStyle,
  73. ...getBaseItem(),
  74. ...preset,
  75. } as unknown as CircleData;
  76. return interactiveFixData({ ...args, info, data: item });
  77. }
  78. };
  79. export const interactiveFixData: InteractiveFix<'circle'> = ({
  80. data,
  81. info,
  82. }) => {
  83. const area = info.cur!;
  84. const sx = Math.abs((area[1].x - area[0].x)) / 2
  85. const sy = Math.abs((area[1].y - area[0].y)) / 2
  86. const center = lineCenter(area)
  87. data.mat = new Transform().translate(center.x, center.y).m
  88. data.radiusX = sx
  89. data.radiusY = sy
  90. return data;
  91. };
  92. export const matResponse = ({data, mat, increment}: MatResponseProps<'circle'>, initRadius?: Pos) => {
  93. if (!initRadius) {
  94. initRadius = {
  95. x: data.radiusX,
  96. y: data.radiusY,
  97. };
  98. }
  99. if (increment) {
  100. mat = mat.copy().multiply(new Transform(data.mat))
  101. }
  102. const dec = mat.decompose();
  103. data.radiusY = dec.scaleY * initRadius.y;
  104. data.radiusX = dec.scaleX * initRadius.x;
  105. data.mat = new Transform()
  106. .translate(dec.x, dec.y)
  107. .rotate(MathUtils.degToRad(dec.rotation)).m;
  108. return data;
  109. }
  110. export const getPredefine = (key: keyof CircleData) => {
  111. if (['fill', 'stroke'].includes(key)) {
  112. return { canun: true }
  113. } else if (key === 'strokeWidth') {
  114. return { proportion: true }
  115. }
  116. }