123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- import { Group } from "konva/lib/Group";
- import { Path } from "konva/lib/shapes/Path";
- import { Rect } from "konva/lib/shapes/Rect";
- export type SVGPath = {
- fill?: string;
- stroke?: string;
- strokeWidth?: number;
- data: string;
- };
- export type SVGProps = {
- size: number[];
- realWidth: number;
- offset: number[];
- paths: SVGPath[];
- };
- export type SVGPathProps = {
- realWidth?: number;
- offset?: number[];
- fixed?: boolean;
- };
- export type PathsShapeAct = ReturnType<typeof pathsToShapeAct>;
- export const pathsToShapeAct = (
- svg: SVGProps,
- props: SVGPathProps = { fixed: true },
- test = false
- ) => {
- const size = svg.size;
- const realSize = props.realWidth || svg.realWidth;
- const scale = realSize / size[0];
- const realBound = size.map((p) => p * scale);
- const offset = (props.offset || svg.offset).map((v) => v * scale);
- const paths = svg.paths.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 = svg.paths[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 offsetGroup = new Group();
- offsetGroup.add(...paths, rect);
- offsetGroup.x(-realBound[0] / 2);
- offsetGroup.y(-realBound[1] / 2);
- common();
- return {
- shape: offsetGroup,
- common,
- setStroke(color: string) {
- paths.forEach((path) => {
- path.stroke(color);
- });
- },
- setFill(color: string) {
- paths.forEach((path) => {
- path.fill(color);
- });
- },
- };
- };
- const temp = document.createElement("div");
- export const analysisSvgContent = (svgContent: string) => {
- temp.innerHTML = svgContent;
- const svg = temp.querySelector("svg");
- const viewBoxStr = svg.getAttribute("viewBox");
- const realWidth = svg.width.baseVal.value;
- const offset = [0, 0];
- const size = [svg.width.baseVal.value, svg.height.baseVal.value];
- if (viewBoxStr) {
- const viewBox = viewBoxStr.split(" ").map(Number);
- offset[0] = viewBox[0];
- offset[1] = viewBox[1];
- size[0] = viewBox[2] - viewBox[0];
- size[1] = viewBox[3] - viewBox[1];
- }
- const paths = Array.from(svg.querySelectorAll("path"));
- const pathDatas = paths.map((path) => {
- const fill = path.getAttribute("fill") || "#000";
- const data = path.getAttribute("d");
- const stroke = path.getAttribute("stroke") || "#000";
- const strokeWidth = path.getAttribute("stroke-width");
- return {
- fill,
- data,
- stroke,
- strokeWidth: strokeWidth && Number(strokeWidth),
- };
- });
- return {
- size,
- realWidth,
- offset,
- paths: pathDatas,
- };
- };
- const cache: { [key in string]: Promise<string> | string } = {};
- export const loadSvgContent = (url: string) => {
- if (url in cache) {
- if (typeof cache[url] === "string") {
- return Promise.resolve(cache[url]);
- } else {
- return cache[url];
- }
- } else {
- return (cache[url] = fetch(url, { method: "GET" })
- .then((res) => res.text())
- .then((data) => {
- cache[url] = data;
- return data;
- }));
- }
- };
- const SVGTypes: { [key in string]: SVGProps } = {};
- export const getSVGProps = async (url: string) => {
- if (!(url in SVGTypes)) {
- const svgContent = await loadSvgContent(url);
- SVGTypes[url] = analysisSvgContent(svgContent);
- }
- return SVGTypes[url];
- };
|