UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

428 lines (427 loc) 14.6 kB
import { isLinearGradient, isRadialGradient, round4, normalizeColor, getIdURL, isImagePattern, getSRTTransformString, getPathPrecision, adjustTextY, TEXT_ALIGN_TO_ANCHOR, isGradient, isPattern, getMatrixStr, hasShadow, getShadowKey, isAroundZero } from "./helper.mjs"; import Path from "../graphic/Path.mjs"; import ZRImage from "../graphic/Image.mjs"; import { getLineHeight } from "../contain/text.mjs"; import TSpan from "../graphic/TSpan.mjs"; import SVGPathRebuilder from "./SVGPathRebuilder.mjs"; import mapStyleToAttrs from "./mapStyleToAttrs.mjs"; import { vNodeToString, createVNode } from "./core.mjs"; import { retrieve2, isString, assert, clone, isFunction, map } from "../core/util.mjs"; import { createOrUpdateImage } from "../graphic/helper/image.mjs"; import { createCSSAnimation } from "./cssAnimation.mjs"; import { hasSeparateFont, parseFontSize } from "../graphic/Text.mjs"; import { DEFAULT_FONT, DEFAULT_FONT_FAMILY } from "../core/platform.mjs"; var round = Math.round; function isImageLike(val) { return val && isString(val.src); } function isCanvasLike(val) { return val && isFunction(val.toDataURL); } function setStyleAttrs(attrs, style, el, scope) { mapStyleToAttrs(function(key, val) { var isFillStroke = key === "fill" || key === "stroke"; if (isFillStroke && isGradient(val)) { setGradient(style, attrs, key, scope); } else if (isFillStroke && isPattern(val)) { setPattern(el, attrs, key, scope); } else { attrs[key] = val; } }, style, el, false); setShadow(el, attrs, scope); } function noRotateScale(m) { return isAroundZero(m[0] - 1) && isAroundZero(m[1]) && isAroundZero(m[2]) && isAroundZero(m[3] - 1); } function noTranslate(m) { return isAroundZero(m[4]) && isAroundZero(m[5]); } function setTransform(attrs, m, compress) { if (m && !(noTranslate(m) && noRotateScale(m))) { var mul = compress ? 10 : 1e4; attrs.transform = noRotateScale(m) ? "translate(" + round(m[4] * mul) / mul + " " + round(m[5] * mul) / mul + ")" : getMatrixStr(m); } } function convertPolyShape(shape, attrs, mul) { var points = shape.points; var strArr = []; for (var i = 0; i < points.length; i++) { strArr.push(round(points[i][0] * mul) / mul); strArr.push(round(points[i][1] * mul) / mul); } attrs.points = strArr.join(" "); } function validatePolyShape(shape) { return !shape.smooth; } function createAttrsConvert(desc) { var normalizedDesc = map(desc, function(item) { return typeof item === "string" ? [item, item] : item; }); return function(shape, attrs, mul) { for (var i = 0; i < normalizedDesc.length; i++) { var item = normalizedDesc[i]; var val = shape[item[0]]; if (val != null) { attrs[item[1]] = round(val * mul) / mul; } } }; } var builtinShapesDef = { circle: [createAttrsConvert(["cx", "cy", "r"])], polyline: [convertPolyShape, validatePolyShape], polygon: [convertPolyShape, validatePolyShape] }; function hasShapeAnimation(el) { var animators = el.animators; for (var i = 0; i < animators.length; i++) { if (animators[i].targetName === "shape") { return true; } } return false; } function brushSVGPath(el, scope) { var style = el.style; var shape = el.shape; var builtinShpDef = builtinShapesDef[el.type]; var attrs = {}; var needsAnimate = scope.animation; var svgElType = "path"; var strokePercent = el.style.strokePercent; var precision = scope.compress && getPathPrecision(el) || 4; if (builtinShpDef && !scope.willUpdate && !(builtinShpDef[1] && !builtinShpDef[1](shape)) && !(needsAnimate && hasShapeAnimation(el)) && !(strokePercent < 1)) { svgElType = el.type; var mul = Math.pow(10, precision); builtinShpDef[0](shape, attrs, mul); } else { var needBuildPath = !el.path || el.shapeChanged(); if (!el.path) { el.createPathProxy(); } var path = el.path; if (needBuildPath) { path.beginPath(); el.buildPath(path, el.shape); el.pathUpdated(); } var pathVersion = path.getVersion(); var elExt = el; var svgPathBuilder = elExt.__svgPathBuilder; if (elExt.__svgPathVersion !== pathVersion || !svgPathBuilder || strokePercent !== elExt.__svgPathStrokePercent) { if (!svgPathBuilder) { svgPathBuilder = elExt.__svgPathBuilder = new SVGPathRebuilder(); } svgPathBuilder.reset(precision); path.rebuildPath(svgPathBuilder, strokePercent); svgPathBuilder.generateStr(); elExt.__svgPathVersion = pathVersion; elExt.__svgPathStrokePercent = strokePercent; } attrs.d = svgPathBuilder.getStr(); } setTransform(attrs, el.transform); setStyleAttrs(attrs, style, el, scope); scope.animation && createCSSAnimation(el, attrs, scope); return createVNode(svgElType, el.id + "", attrs); } function brushSVGImage(el, scope) { var style = el.style; var image = style.image; if (image && !isString(image)) { if (isImageLike(image)) { image = image.src; } else if (isCanvasLike(image)) { image = image.toDataURL(); } } if (!image) { return; } var x = style.x || 0; var y = style.y || 0; var dw = style.width; var dh = style.height; var attrs = { href: image, width: dw, height: dh }; if (x) { attrs.x = x; } if (y) { attrs.y = y; } setTransform(attrs, el.transform); setStyleAttrs(attrs, style, el, scope); scope.animation && createCSSAnimation(el, attrs, scope); return createVNode("image", el.id + "", attrs); } function brushSVGTSpan(el, scope) { var style = el.style; var text = style.text; text != null && (text += ""); if (!text || isNaN(style.x) || isNaN(style.y)) { return; } var font = style.font || DEFAULT_FONT; var x = style.x || 0; var y = adjustTextY(style.y || 0, getLineHeight(font), style.textBaseline); var textAlign = TEXT_ALIGN_TO_ANCHOR[style.textAlign] || style.textAlign; var attrs = { "dominant-baseline": "central", "text-anchor": textAlign }; if (hasSeparateFont(style)) { var separatedFontStr = ""; var fontStyle = style.fontStyle; var fontSize = parseFontSize(style.fontSize); if (!parseFloat(fontSize)) { return; } var fontFamily = style.fontFamily || DEFAULT_FONT_FAMILY; var fontWeight = style.fontWeight; separatedFontStr += "font-size:" + fontSize + ";font-family:" + fontFamily + ";"; if (fontStyle && fontStyle !== "normal") { separatedFontStr += "font-style:" + fontStyle + ";"; } if (fontWeight && fontWeight !== "normal") { separatedFontStr += "font-weight:" + fontWeight + ";"; } attrs.style = separatedFontStr; } else { attrs.style = "font: " + font; } if (text.match(/\s/)) { attrs["xml:space"] = "preserve"; } if (x) { attrs.x = x; } if (y) { attrs.y = y; } setTransform(attrs, el.transform); setStyleAttrs(attrs, style, el, scope); scope.animation && createCSSAnimation(el, attrs, scope); return createVNode("text", el.id + "", attrs, void 0, text); } function brush(el, scope) { if (el instanceof Path) { return brushSVGPath(el, scope); } else if (el instanceof ZRImage) { return brushSVGImage(el, scope); } else if (el instanceof TSpan) { return brushSVGTSpan(el, scope); } } function setShadow(el, attrs, scope) { var style = el.style; if (hasShadow(style)) { var shadowKey = getShadowKey(el); var shadowCache = scope.shadowCache; var shadowId = shadowCache[shadowKey]; if (!shadowId) { var globalScale = el.getGlobalScale(); var scaleX = globalScale[0]; var scaleY = globalScale[1]; if (!scaleX || !scaleY) { return; } var offsetX = style.shadowOffsetX || 0; var offsetY = style.shadowOffsetY || 0; var blur_1 = style.shadowBlur; var _a = normalizeColor(style.shadowColor), opacity = _a.opacity, color = _a.color; var stdDx = blur_1 / 2 / scaleX; var stdDy = blur_1 / 2 / scaleY; var stdDeviation = stdDx + " " + stdDy; shadowId = scope.zrId + "-s" + scope.shadowIdx++; scope.defs[shadowId] = createVNode("filter", shadowId, { "id": shadowId, "x": "-100%", "y": "-100%", "width": "300%", "height": "300%" }, [ createVNode("feDropShadow", "", { "dx": offsetX / scaleX, "dy": offsetY / scaleY, "stdDeviation": stdDeviation, "flood-color": color, "flood-opacity": opacity }) ]); shadowCache[shadowKey] = shadowId; } attrs.filter = getIdURL(shadowId); } } function setGradient(style, attrs, target, scope) { var val = style[target]; var gradientTag; var gradientAttrs = { "gradientUnits": val.global ? "userSpaceOnUse" : "objectBoundingBox" }; if (isLinearGradient(val)) { gradientTag = "linearGradient"; gradientAttrs.x1 = val.x; gradientAttrs.y1 = val.y; gradientAttrs.x2 = val.x2; gradientAttrs.y2 = val.y2; } else if (isRadialGradient(val)) { gradientTag = "radialGradient"; gradientAttrs.cx = retrieve2(val.x, 0.5); gradientAttrs.cy = retrieve2(val.y, 0.5); gradientAttrs.r = retrieve2(val.r, 0.5); } else { return; } var colors = val.colorStops; var colorStops = []; for (var i = 0, len = colors.length; i < len; ++i) { var offset = round4(colors[i].offset) * 100 + "%"; var stopColor = colors[i].color; var _a = normalizeColor(stopColor), color = _a.color, opacity = _a.opacity; var stopsAttrs = { "offset": offset }; stopsAttrs["stop-color"] = color; if (opacity < 1) { stopsAttrs["stop-opacity"] = opacity; } colorStops.push(createVNode("stop", i + "", stopsAttrs)); } var gradientVNode = createVNode(gradientTag, "", gradientAttrs, colorStops); var gradientKey = vNodeToString(gradientVNode); var gradientCache = scope.gradientCache; var gradientId = gradientCache[gradientKey]; if (!gradientId) { gradientId = scope.zrId + "-g" + scope.gradientIdx++; gradientCache[gradientKey] = gradientId; gradientAttrs.id = gradientId; scope.defs[gradientId] = createVNode(gradientTag, gradientId, gradientAttrs, colorStops); } attrs[target] = getIdURL(gradientId); } function setPattern(el, attrs, target, scope) { var val = el.style[target]; var boundingRect = el.getBoundingRect(); var patternAttrs = {}; var repeat = val.repeat; var noRepeat = repeat === "no-repeat"; var repeatX = repeat === "repeat-x"; var repeatY = repeat === "repeat-y"; var child; if (isImagePattern(val)) { var imageWidth_1 = val.imageWidth; var imageHeight_1 = val.imageHeight; var imageSrc = void 0; var patternImage = val.image; if (isString(patternImage)) { imageSrc = patternImage; } else if (isImageLike(patternImage)) { imageSrc = patternImage.src; } else if (isCanvasLike(patternImage)) { imageSrc = patternImage.toDataURL(); } if (typeof Image === "undefined") { var errMsg = "Image width/height must been given explictly in svg-ssr renderer."; assert(imageWidth_1, errMsg); assert(imageHeight_1, errMsg); } else if (imageWidth_1 == null || imageHeight_1 == null) { var setSizeToVNode_1 = function(vNode, img) { if (vNode) { var svgEl = vNode.elm; var width = imageWidth_1 || img.width; var height = imageHeight_1 || img.height; if (vNode.tag === "pattern") { if (repeatX) { height = 1; width /= boundingRect.width; } else if (repeatY) { width = 1; height /= boundingRect.height; } } vNode.attrs.width = width; vNode.attrs.height = height; if (svgEl) { svgEl.setAttribute("width", width); svgEl.setAttribute("height", height); } } }; var createdImage = createOrUpdateImage(imageSrc, null, el, function(img) { noRepeat || setSizeToVNode_1(patternVNode, img); setSizeToVNode_1(child, img); }); if (createdImage && createdImage.width && createdImage.height) { imageWidth_1 = imageWidth_1 || createdImage.width; imageHeight_1 = imageHeight_1 || createdImage.height; } } child = createVNode("image", "img", { href: imageSrc, width: imageWidth_1, height: imageHeight_1 }); patternAttrs.width = imageWidth_1; patternAttrs.height = imageHeight_1; } else if (val.svgElement) { child = clone(val.svgElement); patternAttrs.width = val.svgWidth; patternAttrs.height = val.svgHeight; } if (!child) { return; } var patternWidth; var patternHeight; if (noRepeat) { patternWidth = patternHeight = 1; } else if (repeatX) { patternHeight = 1; patternWidth = patternAttrs.width / boundingRect.width; } else if (repeatY) { patternWidth = 1; patternHeight = patternAttrs.height / boundingRect.height; } else { patternAttrs.patternUnits = "userSpaceOnUse"; } if (patternWidth != null && !isNaN(patternWidth)) { patternAttrs.width = patternWidth; } if (patternHeight != null && !isNaN(patternHeight)) { patternAttrs.height = patternHeight; } var patternTransform = getSRTTransformString(val); patternTransform && (patternAttrs.patternTransform = patternTransform); var patternVNode = createVNode("pattern", "", patternAttrs, [child]); var patternKey = vNodeToString(patternVNode); var patternCache = scope.patternCache; var patternId = patternCache[patternKey]; if (!patternId) { patternId = scope.zrId + "-p" + scope.patternIdx++; patternCache[patternKey] = patternId; patternAttrs.id = patternId; patternVNode = scope.defs[patternId] = createVNode("pattern", patternId, patternAttrs, [child]); } attrs[target] = getIdURL(patternId); } function setClipPath(clipPath, attrs, scope) { var clipPathCache = scope.clipPathCache, defs = scope.defs; var clipPathId = clipPathCache[clipPath.id]; if (!clipPathId) { clipPathId = scope.zrId + "-c" + scope.clipPathIdx++; var clipPathAttrs = { id: clipPathId }; clipPathCache[clipPath.id] = clipPathId; defs[clipPathId] = createVNode("clipPath", clipPathId, clipPathAttrs, [brushSVGPath(clipPath, scope)]); } attrs["clip-path"] = getIdURL(clipPathId); } export { brush, brushSVGImage, brushSVGPath, brushSVGTSpan, setClipPath, setGradient, setPattern };