import { Path } from "konva/lib/shapes/Path"; import { Rect } from "konva/lib/shapes/Rect"; import { getRealAbsoluteSize } from "./shape-helper"; import { Group } from "konva/lib/Group"; import { KonvaEventObject } from "konva/lib/Node"; export type SVGPaths = ( | string | { fill?: string; stroke?: string; strokeWidth?: number; data: string } )[]; const temp = document.createElement("div"); export const analysisSvg = ( svgString: string ): Pick => { temp.innerHTML = svgString; const svg = temp.querySelector("svg"); const size = [svg.width.baseVal.value, svg.height.baseVal.value]; const paths = Array.from(svg.querySelectorAll("path")); const pathDatas = paths.map((path) => { const fill = path.getAttribute("fill"); const data = path.getAttribute("d"); const stroke = path.getAttribute("stroke"); const strokeWidth = path.getAttribute("stroke-width"); return { fill, data, stroke, strokeWidth: strokeWidth && Number(strokeWidth), }; }); return { paths: pathDatas, size, }; }; export type PathsToActShapeProps = { paths: SVGPaths; size: number[]; realWidth?: number; offset?: number[]; strokeWidth?: number; fixed?: boolean; strokeColor?: string; }; export const pathsToActShape = (props: PathsToActShapeProps, test = false) => { const size = props.size; const realSize = props.realWidth || props.size[0]; const scale = realSize / size[0]; const realBound = size.map((p) => p * scale); const offset = (props.offset || [0, 0]).map((v) => v * scale); const strokeWidth = props.strokeWidth ? props.strokeWidth * scale : 1; const strokeColor = props.strokeColor || "#000"; const pathAttribs = props.paths.map((path) => { if (typeof path === "string") { return { strokeWidth, stroke: strokeColor, fill: strokeColor, data: path, }; } else { return path; } }); const paths = pathAttribs.map( (path, ndx) => new Path({ data: path.data, id: `path-${ndx}`, name: `path`, strokeScaleEnabled: !!props.fixed, scale: { x: scale, y: scale }, }) ); const common = () => { paths.forEach((path, ndx) => { const attrib = pathAttribs[ndx]; attrib.fill && path.fill(attrib.fill); attrib.stroke && path.stroke(attrib.stroke); attrib.strokeWidth && path.strokeWidth(attrib.strokeWidth); }); }; const rect = new Rect({ x: offset[0], y: offset[1], name: "rect", width: realBound[0], height: realBound[1], fill: `rgba(0, 0, 0, ${test ? 0.3 : 0})`, }); const setStyle = () => { let [width, height] = getRealAbsoluteSize(group, [1, 1]); group.scale({ x: width, y: height }); }; const offsetGroup = new Group(); offsetGroup.add(...paths, rect); offsetGroup.x(-realBound[0] / 2); offsetGroup.y(-realBound[1] / 2); const group = new Group(); group.add(offsetGroup); return { getSize: () => { const size = rect.getSize(); if (props.fixed) { let [scale] = getRealAbsoluteSize(group, [1, 1]); return [size.width * scale, size.height * scale]; } return [size.width, size.height]; }, shape: group, setData(data) { group.position(data); props.fixed && setStyle(); if (data.rotate) { group.rotation(data.rotate); } }, common, }; }; export const getTouchOffset = (ev: KonvaEventObject) => { const dom = ev.evt.target as HTMLElement; const rect = dom.getBoundingClientRect(); const offsetX = ev.evt.changedTouches[0].pageX - rect.left; const offsetY = ev.evt.changedTouches[0].pageY - rect.top; return { offsetX, offsetY, }; };