123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- import { reactive } from "vue";
- import { Pos, Size } from "./math";
- let imageCache: Record<string, Promise<HTMLImageElement>>;
- let imageCache1: Record<string, HTMLImageElement>;
- export let imageInfo: Record<string, Record<'width' | 'height', number>> = reactive({})
- export let getImage = (url: string): Promise<HTMLImageElement> => {
- imageCache = {};
- imageCache1 = {};
- getImage = (url: string) => {
- if (url in imageCache) {
- if (imageCache1[url]?.width === 0 || imageCache1[url]?.height === 0) {
- delete imageCache1[url]
- delete imageCache[url];
- delete imageInfo[url]
- } else {
- return imageCache[url];
- }
- }
- return (imageCache[url] = new Promise((resolve, reject) => {
- const image = new Image();
- image.crossOrigin = "anonymous";
- image.onload = () => {
- resolve(image);
- imageInfo[url] = {
- width: image.width,
- height: image.height
- }
- imageCache1[url] = image
- };
- image.onerror = (e) => {
- console.error(e)
- reject(e);
- };
- image.src = url;
- }));
- };
- return getImage(url);
- };
- export const isSvgString = (str: string) => {
- // 检查字符串是否以 <svg> 标签开头
- const svgRegex = /^<svg[^>]*>.*<\/svg>$/is;
- return svgRegex.test(str);
- }
- let svgContentCache: Record<string, Promise<string>>;
- export let getSvgContent = (url: string): Promise<string> => {
- svgContentCache = {};
- getSvgContent = async (url: string) => {
- if (isSvgString(url)) {
- return url;
- }
- if (url in svgContentCache) {
- return svgContentCache[url];
- } else {
- const res = await fetch(url);
- return (svgContentCache[url] = res.text());
- }
- };
- return getSvgContent(url);
- };
- export type SVGPath = {
- fill?: string;
- stroke?: string;
- strokeWidth?: number;
- data: string;
- };
- export type SVGParseResult = Size & Pos & {
- paths: SVGPath[];
- };
- let svgParseCache: Record<string, SVGParseResult>;
- let helpDOM: HTMLDivElement;
- export let parseSvgContent = (svgContent: string): SVGParseResult => {
- svgParseCache = {};
- helpDOM = document.createElement("div");
- helpDOM.style.position = "absolute";
- helpDOM.style.left = "-99999px";
- helpDOM.style.top = "-99999px";
- parseSvgContent = (svgContent: string) => {
- if (svgContent in svgParseCache) return svgParseCache[svgContent];
- helpDOM.innerHTML = svgContent;
- document.body.appendChild(helpDOM);
- let right = 0;
- let bottom = 0;
- let x = Number.MAX_VALUE;
- let y = Number.MAX_VALUE;
- const svgPaths = Array.from(helpDOM.querySelectorAll("path"));
- const paths = svgPaths.map((path) => {
- const box = path.getBBox();
- x = Math.min(box.x, x);
- y = Math.min(box.y, y);
- right = Math.max(right, box.x + box.width);
- bottom = Math.max(bottom, box.y + box.height);
- 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)) || 1,
- };
- });
- helpDOM.innerHTML = "";
- document.body.removeChild(helpDOM);
- return (svgParseCache[svgContent] = { paths, width: right - x, height: bottom - y, x, y });
- };
- return parseSvgContent(svgContent);
- };
|