import { ELineBindAnchors } from '@/config-center/system/types'; import { EDoneJsonType, IConfigItem } from '@/config-center/types'; import type { IDoneJson } from '@/store/global/types'; /** * 生成随机字符串 * @param len 生成个数 */ export const randomString = (len?: number) => { len = len || 10; const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const maxPos = str.length; let random_str = ''; for (let i = 0; i < len; i++) { random_str += str.charAt(Math.floor(Math.random() * maxPos)); } return random_str; }; // 通过泛型定义通用类型保护函数 export const isOfType = (target: unknown, prop: keyof T): target is T => { return (target as T)[prop] !== undefined; }; /** * 获取坐标偏移量 * @param length 真实宽/高 * @param scale 缩放倍数 * @returns 坐标偏移量 */ export const getCoordinateOffset = (length: number, scale: number) => { return (length / 2) * (scale - 1); }; // 角度转弧度 // Math.PI = 180 度 export const angleToRadian = (angle: number) => { return (angle * Math.PI) / 180; }; /** * 计算根据圆心旋转后的点的坐标 * @param {Object} point 旋转前的点坐标 * @param {Object} center 旋转中心 * @param {Number} rotate 旋转的角度 * @return {Object} 旋转后的坐标 * https://www.zhihu.com/question/67425734/answer/252724399 旋转矩阵公式 */ export const calculateRotatedPointCoordinate = ( point: { x: number; y: number }, center: { x: number; y: number }, rotate: number ) => { /** * 旋转公式: * 点a(x, y) * 旋转中心c(x, y) * 旋转后点n(x, y) * 旋转角度θ tan ?? * nx = cosθ * (ax - cx) - sinθ * (ay - cy) + cx * ny = sinθ * (ax - cx) + cosθ * (ay - cy) + cy */ return { x: (point.x - center.x) * Math.cos(angleToRadian(rotate)) - (point.y - center.y) * Math.sin(angleToRadian(rotate)) + center.x, y: (point.x - center.x) * Math.sin(angleToRadian(rotate)) + (point.y - center.y) * Math.cos(angleToRadian(rotate)) + center.y }; }; // 求两点之间的中点坐标 export const getCenterPoint = (p1: { x: number; y: number }, p2: { x: number; y: number }) => { return { x: p1.x + (p2.x - p1.x) / 2, y: p1.y + (p2.y - p1.y) / 2 }; }; /** * 坐标数组转换成path路径 * @param position_arr * @returns */ export const positionArrarToPath = (position_arr: { x: number; y: number }[]) => { let path_str = ''; for (let index = 0; index < position_arr.length; index++) { if (index === 0) { path_str += `M ${position_arr[index].x} ${position_arr[index].y}`; } else { path_str += ` L ${position_arr[index].x} ${position_arr[index].y}`; } } return path_str; }; /** * 获取相对于svg最新的坐标 * @param init_pos 相对于页面的初始坐标 * @param finally_pos 相对于页面的最终坐标 * @param svg_init_pos 相对于svg的初始坐标 * @returns svg最新的坐标 */ export const getSvgNowPosition = (init_pos: number, finally_pos: number, svg_init_pos: number) => { return svg_init_pos + (finally_pos - init_pos); }; /** * 对象深拷贝 * @param object * @param default_val * @returns */ export const objectDeepClone = (object: object, default_val: any = {}) => { if (!object) { return default_val as T; } return JSON.parse(JSON.stringify(object)) as T; }; /** * 设置实际的属性 * @param done_json */ export const setSvgActualInfo = (done_json: IDoneJson) => { const queryBbox = document.querySelector(`#${done_json.id}`); // const rectBBox = document.querySelector(`#rect${done_json.id}`); if (queryBbox) { let x = 0, y = 0, width = 0, height = 0; if (done_json.type !== EDoneJsonType.Vue) { const BBox = (queryBbox as SVGGraphicsElement).getBBox(); x = BBox.x; y = BBox.y; (width = BBox.width), (height = BBox.height); } else { (width = (queryBbox as HTMLElement).offsetWidth), (height = (queryBbox as HTMLElement).offsetHeight); x = 50 - width / 2; y = 50 - height / 2; const foreignObjectBox = document.querySelector(`#foreign-object${done_json.id}`); if (foreignObjectBox) { foreignObjectBox.setAttribute('x', x.toString()); foreignObjectBox.setAttribute('y', y.toString()); foreignObjectBox.setAttribute('width', width.toString()); foreignObjectBox.setAttribute('height', height.toString()); } } // rectBBox.setAttribute('x', x.toString()); // rectBBox.setAttribute('y', y.toString()); // rectBBox.setAttribute('width', width.toString()); // rectBBox.setAttribute('height', height.toString()); done_json.actual_bound = { x, y, width, height }; done_json.point_coordinate.tl = { x: done_json.x - (width * done_json.scale_x) / 2, y: done_json.y - (height * done_json.scale_y) / 2 }; done_json.point_coordinate.tc = { x: done_json.x, y: done_json.y - (height * done_json.scale_y) / 2 }; done_json.point_coordinate.tr = { x: done_json.x + (width * done_json.scale_x) / 2, y: done_json.y - (height * done_json.scale_y) / 2 }; done_json.point_coordinate.l = { x: done_json.x - (width * done_json.scale_x) / 2, y: done_json.y }; done_json.point_coordinate.r = { x: done_json.x + (width * done_json.scale_x) / 2, y: done_json.y }; done_json.point_coordinate.bl = { x: done_json.x - (width * done_json.scale_x) / 2, y: done_json.y + (height * done_json.scale_y) / 2 }; done_json.point_coordinate.bc = { x: done_json.x, y: done_json.y + (height * done_json.scale_y) / 2 }; done_json.point_coordinate.br = { x: done_json.x + (width * done_json.scale_x) / 2, y: done_json.y + (height * done_json.scale_y) / 2 }; if (done_json.rotate !== 0) { setAfterRotationPointCoordinate(done_json); } } }; /** * 根据锚点类型获取锚点坐标 * @param anchor_type * @param done_json * @returns */ export const getAnchorPosByAnchorType = (anchor_type: ELineBindAnchors, done_json: IDoneJson) => { if (anchor_type === ELineBindAnchors.BottomCenter) { return done_json.point_coordinate.bc; } else if (anchor_type === ELineBindAnchors.Left) { return done_json.point_coordinate.l; } else if (anchor_type === ELineBindAnchors.Right) { return done_json.point_coordinate.r; } else { return done_json.point_coordinate.tc; } }; /** * 旋转之后重新设置组件八点坐标 * @param item */ export const setAfterRotationPointCoordinate = (item: IDoneJson) => { item.point_coordinate = { tl: calculateRotatedPointCoordinate( item.point_coordinate.tl, { x: item.x, y: item.y }, item.rotate ), tc: calculateRotatedPointCoordinate( item.point_coordinate.tc, { x: item.x, y: item.y }, item.rotate ), tr: calculateRotatedPointCoordinate( item.point_coordinate.tr, { x: item.x, y: item.y }, item.rotate ), l: calculateRotatedPointCoordinate( item.point_coordinate.l, { x: item.x, y: item.y }, item.rotate ), r: calculateRotatedPointCoordinate( item.point_coordinate.r, { x: item.x, y: item.y }, item.rotate ), bl: calculateRotatedPointCoordinate( item.point_coordinate.bl, { x: item.x, y: item.y }, item.rotate ), bc: calculateRotatedPointCoordinate( item.point_coordinate.bc, { x: item.x, y: item.y }, item.rotate ), br: calculateRotatedPointCoordinate( item.point_coordinate.br, { x: item.x, y: item.y }, item.rotate ) }; }; export const prosToVBind = (item: IConfigItem) => { let temp = {}; if (item.state) { for (const key in item.state) { if (key === 'OnOff') { for (const on_off_key in item.state[key]?.props) { temp = { ...temp, ...{ [on_off_key]: item.state[key]?.default ? item.state[key]?.props[on_off_key].openVal : item.state[key]?.props[on_off_key].closeVal } }; } } } } for (const key in item.props) { temp = { ...temp, ...{ [key]: item.props[key].val } }; } return temp; };