UNPKG

@visactor/vdataset

Version:

data processing tool

158 lines (147 loc) 8.48 kB
import { Matrix, isString, isValid, isValidNumber, merge, toCamelCase } from "@visactor/vutils"; const tagNameToType = { svg: "group", rect: "rect", line: "rule", polygon: "polygon", path: "path", polyline: "line", g: "group", circle: "arc", ellipse: "arc" }, validTagName = Object.keys(tagNameToType), validGroupNode = [ "g", "svg", "text", "tspan", "switch" ], validTextAttributes = [ "font-size", "font-family", "font-weight", "font-style", "text-align", "text-anchor" ], validCircleAttributes = [ "cx", "cy", "r" ], validEllipseAttributes = [ "cx", "cy", "rx", "ry" ], validLineAttributes = [ "x1", "x2", "y1", "y2" ], validAttributes = [ "visibility", "x", "y", "width", "height", "d", "points", "stroke", "stroke-width", "fill", "fill-opacity", "stroke-opacity", ...validTextAttributes, ...validCircleAttributes, ...validEllipseAttributes, ...validLineAttributes ], validInheritAttributes = [ "visible", "fill", "stroke", "stroke-width", "fill-opacity", "stroke-opacity", ...validTextAttributes ], numberReg = /-?([0-9]*\.)?[0-9]+([eE]-?[0-9]+)?/g; function splitNumberSequence(rawStr) { return rawStr.match(numberReg) || []; } export const svgParser = (data, option = {}, dataView) => { let parser = option.customDOMParser; if (parser || (null === window || void 0 === window ? void 0 : window.DOMParser) && (parser = svg => (new DOMParser).parseFromString(svg, "text/xml")), !parser) throw new Error("No Available DOMParser!"); const svg = parser(data); let node = 9 === svg.nodeType ? svg.firstChild : svg; for (;node && ("svg" !== node.nodeName.toLowerCase() || 1 !== node.nodeType); ) node = node.nextSibling; if (node) { return parseSvgNode(node); } return null; }; let idx = 0; function parseSvgNode(svg, opt = {}) { const elements = [], root = parseNode(svg, null); let width = parseFloat(svg.getAttribute("width") || opt.width), height = parseFloat(svg.getAttribute("height") || opt.height); !isValidNumber(width) && (width = null), !isValidNumber(height) && (height = null); const viewBox = svg.getAttribute("viewBox"); let viewBoxRect; if (viewBox) { const viewBoxArr = splitNumberSequence(viewBox); if (viewBoxArr.length >= 4 && (viewBoxRect = { x: parseFloat(viewBoxArr[0] || 0), y: parseFloat(viewBoxArr[1] || 0), width: parseFloat(viewBoxArr[2]), height: parseFloat(viewBoxArr[3]) }, width || height)) { const boundingRect = { x: 0, y: 0, width: width, height: height }, scaleX = boundingRect.width / viewBoxRect.width, scaleY = boundingRect.height / viewBoxRect.height, scale = Math.min(scaleX, scaleY), transLateX = -(viewBoxRect.x + viewBoxRect.width / 2) * scale + (boundingRect.x + boundingRect.width / 2), transLateY = -(viewBoxRect.y + viewBoxRect.height / 2) * scale + (boundingRect.y + boundingRect.height / 2), viewBoxTransform = (new Matrix).translate(transLateX, transLateY).scale(scale, scale); root.transform = viewBoxTransform; } } return traverse(svg, root, elements), { root: root, width: width, height: height, elements: elements, viewBoxRect: viewBoxRect }; } function parseInheritAttributes(parsedElement) { let inheritedAttrs; const {parent: parent, attributes: attributes} = parsedElement, parse = parent => parent ? validInheritAttributes.reduce(((acc, attrName) => { const camelAttrName = toCamelCase(attrName); return isValid(parent[camelAttrName]) && (acc[camelAttrName] = parent[camelAttrName]), acc; }), {}) : {}; return parent ? (parent._inheritStyle || (parent._inheritStyle = parse(parent.attributes)), inheritedAttrs = merge({}, parent._inheritStyle, parse(attributes))) : inheritedAttrs = parse(attributes), inheritedAttrs; } function parseAttributes(el) { var _a, _b, _c; const attrs = {}, attributes = null !== (_a = el.attributes) && void 0 !== _a ? _a : {}, style = null !== (_b = el.style) && void 0 !== _b ? _b : {}; for (let i = 0; i < validAttributes.length; i++) { const attrName = validAttributes[i], attrValue = isValid(style[attrName]) && "" !== style[attrName] ? style[attrName] : null === (_c = attributes[attrName]) || void 0 === _c ? void 0 : _c.value; isValid(attrValue) && (attrs[toCamelCase(attrName)] = isNaN(+attrValue) ? attrValue : parseFloat(attrValue)); } return "none" === style.display && (attrs.visible = !1), [ "fontSize", "strokeWidth", "width", "height" ].forEach((attr => { const attrValue = attrs[attr]; isString(attrs[attr]) && (attrs[attr] = parseFloat(attrValue)); })), attrs; } function parseNode(node, parent) { var _a, _b, _c, _d, _e; const tagName = null === (_a = node.tagName) || void 0 === _a ? void 0 : _a.toLowerCase(); if (3 === node.nodeType || "text" === tagName || "tspan" === tagName) return parseText(node, parent); if (!validTagName.includes(tagName)) return null; const parsed = { tagName: tagName, graphicType: tagNameToType[tagName], attributes: parseAttributes(node), parent: parent, name: null !== (_b = node.getAttribute("name")) && void 0 !== _b ? _b : null === (_c = null == parent ? void 0 : parent.attributes) || void 0 === _c ? void 0 : _c.name, id: null !== (_d = node.getAttribute("id")) && void 0 !== _d ? _d : `${tagName}-${idx++}`, transform: parseTransform(node) }; return parsed._inheritStyle = parseInheritAttributes(parsed), parent && !isValid(parsed.name) && (parsed._nameFromParent = null !== (_e = parent.name) && void 0 !== _e ? _e : parent._nameFromParent), parsed; } function parseText(node, parent) { var _a, _b, _c, _d, _e, _f; if (!parent) return null; const tagName = null === (_a = node.tagName) || void 0 === _a ? void 0 : _a.toLowerCase(); if (!tagName && "group" !== parent.graphicType) return null; const nodeAsGroup = "text" === tagName || "tspan" === tagName, elType = nodeAsGroup ? "group" : "text", value = nodeAsGroup || null === (_b = node.textContent) || void 0 === _b ? void 0 : _b.replace(/\n/g, " ").replace(/\s+/g, " "); if (" " === value) return null; let parsed; return parsed = nodeAsGroup ? { tagName: tagName, graphicType: elType, attributes: parseAttributes(node), parent: parent, name: node.getAttribute("name"), id: null !== (_c = node.getAttribute("id")) && void 0 !== _c ? _c : `${tagName}-${idx++}`, transform: parseTransform(node), value: value } : { tagName: tagName, graphicType: "text", attributes: parseAttributes(node), parent: parent, name: null == parent ? void 0 : parent.name, id: null !== (_e = null === (_d = node.getAttribute) || void 0 === _d ? void 0 : _d.call(node, "id")) && void 0 !== _e ? _e : `${tagName}-${idx++}`, value: value }, parsed._inheritStyle = parseInheritAttributes(parsed), isValid(parsed.name) || (parsed._nameFromParent = null !== (_f = parent.name) && void 0 !== _f ? _f : parent._nameFromParent), nodeAsGroup ? parent._textGroupStyle ? parsed._textGroupStyle = merge({}, parent._textGroupStyle, parseAttributes(node)) : parsed._textGroupStyle = parseAttributes(node) : parsed.attributes = parsed._inheritStyle, parsed; } function parseTransform(node) { var _a, _b; const transforms = null === (_a = node.transform) || void 0 === _a ? void 0 : _a.baseVal; if (!transforms) return null; const matrix = null === (_b = transforms.consolidate()) || void 0 === _b ? void 0 : _b.matrix; if (!matrix) return null; const {a: a, b: b, c: c, d: d, e: e, f: f} = matrix; return new Matrix(a, b, c, d, e, f); } function traverse(node, parsedParent, result = []) { var _a; if (!node) return; let parseResult; "svg" !== node.nodeName && (parseResult = parseNode(node, parsedParent)), parseResult && result.push(parseResult); let child = validGroupNode.includes(null === (_a = node.tagName) || void 0 === _a ? void 0 : _a.toLocaleLowerCase()) ? node.firstChild : null; for (;child; ) traverse(child, null != parseResult ? parseResult : parsedParent, result), child = child.nextSibling; } //# sourceMappingURL=svg.js.map