123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- import { Transform } from "konva/lib/Util";
- import {
- BaseItem,
- generateSnapInfos,
- getBaseItem,
- getRectSnapPoints,
- } from "../util.ts";
- import { getMouseColors } from "@/utils/colors.ts";
- import { FixScreen } from "@/utils/bound.ts";
- import { InteractiveFix, InteractiveTo, MatResponseProps } from "../index.ts";
- import { Size } from "@/utils/math.ts";
- import { getSvgContent, parseSvgContent } from "@/utils/resource.ts";
- import { Color } from "three";
- export const shapeName = "图例";
- export const defaultStyle = {
- coverFill: "#000000",
- coverOpcatiy: 0,
- strokeScaleEnabled: false,
- width: 80,
- height: 80,
- };
- type ColorCounts = [string, number][];
- const colorsManage = (counts: ColorCounts, color: any) => {
- if (!color) {
- return;
- }
- const colorHex = new Color(color).getHexString();
- const item = counts.find(([c]) => c === colorHex);
- if (!item) {
- counts.push([colorHex, 1]);
- } else {
- item[1]++;
- }
- };
- const findColor = (counts: ColorCounts) => {
- let ndx = -1;
- let max = 0;
- for (let i = 0; i < counts.length; i++) {
- if (counts[i][1] >= max) {
- ndx = i;
- max = counts[i][1];
- }
- }
- if (~ndx) {
- return `#${counts[ndx][0]}`;
- }
- };
- export const getIconStyle = async (
- url: string,
- width = defaultStyle.width,
- height = defaultStyle.height,
- fixed = false
- ) => {
- const svgContent = parseSvgContent(await getSvgContent(url));
- if (!fixed) {
- if (width / height > svgContent.width / svgContent.height) {
- width = (svgContent.width / svgContent.height) * height;
- } else {
- height = (svgContent.height / svgContent.width) * width;
- }
- }
- const fillColorCounts: [string, number][] = [];
- const strokeColorCounts: [string, number][] = [];
- for (let i = 0; i < svgContent.paths.length; i++) {
- colorsManage(fillColorCounts, svgContent.paths[i].fill);
- colorsManage(strokeColorCounts, svgContent.paths[i].stroke);
- }
- const color = {
- fill: findColor(fillColorCounts) || null,
- stroke: findColor(strokeColorCounts) || null,
- };
- if (!color.fill && !color.stroke) {
- color.stroke = "#000000";
- }
- return {
- url,
- width,
- height,
- ...color,
- };
- };
- export const addMode = "dot";
- export const getSnapInfos = (data: IconData) => {
- return generateSnapInfos(getSnapPoints(data), true, false);
- };
- export const getSnapPoints = (data: IconData) => {
- const tf = new Transform(data.mat);
- const w = data.width || defaultStyle.width;
- const h = data.height || defaultStyle.height;
- const points = getRectSnapPoints(w, h);
- return points.map((v) => tf.point(v));
- };
- export const getMouseStyle = (data: IconData) => {
- const fillStatus = getMouseColors(data.coverFill || defaultStyle.coverFill);
- const hCoverOpcaoty = data.coverOpcatiy ? data.coverOpcatiy : 0.3;
- return {
- default: {
- coverFill: data.coverFill || defaultStyle.coverFill,
- coverOpcatiy: data.coverOpcatiy || 0,
- },
- hover: { coverFill: fillStatus.hover, coverOpcatiy: hCoverOpcaoty },
- select: { coverFill: fillStatus.select, coverOpcatiy: hCoverOpcaoty },
- focus: { coverFill: fillStatus.select, coverOpcatiy: hCoverOpcaoty },
- press: { coverFill: fillStatus.press, coverOpcatiy: hCoverOpcaoty },
- };
- };
- export type IconData = Partial<typeof defaultStyle> &
- BaseItem &
- Size & {
- fill?: string | null;
- stroke?: string | null;
- name?: string;
- strokeWidth?: number;
- coverFill?: string;
- coverStroke?: string;
- coverStrokeWidth?: number;
- mat: number[];
- url: string;
- fixScreen?: FixScreen;
- };
- export const dataToConfig = (data: IconData) => {
- return {
- ...defaultStyle,
- ...data,
- };
- };
- export const interactiveToData: InteractiveTo<"icon"> = ({
- info,
- preset = {},
- viewTransform,
- ...args
- }) => {
- if (info.cur) {
- console.error(preset);
- return interactiveFixData({
- ...args,
- viewTransform,
- info,
- data: { ...getBaseItem(), ...preset } as unknown as IconData,
- });
- }
- };
- export const interactiveFixData: InteractiveFix<"icon"> = ({
- data,
- info,
- viewTransform,
- }) => {
- if (data.fixScreen) {
- if ("x" in info.cur! && "y" in info.cur!) {
- // 存储屏幕坐标
- const screen = viewTransform.point(info.cur!);
- data.fixScreen = {
- left: screen.x,
- top: screen.y,
- };
- }
- data.mat = [1, 0, 0, 1, 0, 0];
- } else {
- const mat = new Transform().translate(info.cur!.x, info.cur!.y);
- data.mat = mat.m;
- }
- return data;
- };
- export const matResponse = ({
- data,
- mat,
- increment,
- }: MatResponseProps<"icon">) => {
- data.mat = increment ? mat.copy().multiply(new Transform(data.mat)).m : mat.m;
- return data;
- };
- export const getPredefine = (key: keyof IconData) => {
- if (key === "fill" || key === "stroke") {
- return { canun: true };
- }
- };
|