import { CircleConfig } from "konva/lib/shapes/Circle"; import { BaseItem, generateSnapInfos, getBaseItem, getRectSnapPoints, } from "../util.ts"; import { getMouseColors } from "@/utils/colors.ts"; import { lineCenter, Pos } from "@/utils/math.ts"; import { Transform } from "konva/lib/Util"; import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts"; import { MathUtils } from "three"; export { default as Component } from "./circle.vue"; export { default as TempComponent } from "./temp-circle.vue"; export const shapeName = "圆形"; export const defaultStyle = { dash: [30, 0], stroke: "#000000", strokeWidth: 5, fontSize: 22, fixed: true, align: "center", fontStyle: "normal", fontColor: "#000000", padding: 8, }; export const addMode = "area"; export const fixedStrokeOptions = [1, 2, 4]; export const getMouseStyle = (data: CircleData) => { const fillStatus = data.fill && getMouseColors(data.fill); const strokeStatus = data.stroke && getMouseColors(data.stroke); const strokeWidth = data.strokeWidth; return { default: { stroke: data.stroke, strokeWidth, fill: data.fill }, hover: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus && strokeStatus.hover, }, select: { fill: fillStatus && fillStatus.select, stroke: strokeStatus && strokeStatus.select, }, focus: { fill: fillStatus && fillStatus.hover, stroke: strokeStatus && strokeStatus.hover, }, press: { fill: fillStatus && fillStatus.press, stroke: strokeStatus && strokeStatus.press, }, }; }; export const getSnapInfos = (data: CircleData) => { return generateSnapInfos(getSnapPoints(data), true, false); }; export const getSnapPoints = (data: CircleData) => { const dec = new Transform(data.mat).decompose(); const points = getRectSnapPoints(data.radiusX * 2, data.radiusY * 2).map( (v) => ({ x: v.x + dec.x, y: v.y + dec.y, }) ); // const size = data.radius * 2; return points; }; export type CircleData = Partial & BaseItem & { opacity?: number; fill?: string; mat: number[]; radiusX: number; radiusY: number; content?: string; desc?: string padding?: number; }; export const dataToConfig = (data: CircleData): CircleConfig => ({ ...defaultStyle, ...data, }); export const interactiveToData: InteractiveTo<"circle"> = ({ info, preset = {}, ...args }) => { if (info.cur) { const item = { ...defaultStyle, fill: null, ...getBaseItem(), ...preset, } as unknown as CircleData; return interactiveFixData({ ...args, info, data: item }); } }; export const interactiveFixData: InteractiveFix<"circle"> = ({ data, info, }) => { const area = info.cur!; const sx = Math.abs(area[1].x - area[0].x) / 2; const sy = Math.abs(area[1].y - area[0].y) / 2; const center = lineCenter(area); data.mat = new Transform().translate(center.x, center.y).m; data.radiusX = sx; data.radiusY = sy; return data; }; export const matResponse = ( { data, mat, increment }: MatResponseProps<"circle">, initRadius?: Pos ) => { if (!initRadius) { initRadius = { x: data.radiusX, y: data.radiusY, }; } if (increment) { mat = mat.copy().multiply(new Transform(data.mat)); } const dec = mat.decompose(); data.radiusY = dec.scaleY * initRadius.y; data.radiusX = dec.scaleX * initRadius.x; data.mat = new Transform() .translate(dec.x, dec.y) .rotate(MathUtils.degToRad(dec.rotation)).m; return data; }; export const getPredefine = (key: keyof CircleData) => { if (["fill", "stroke"].includes(key)) { return { canun: true }; } };