UNPKG

@visactor/vgrammar-core

Version:

VGrammar is a visual grammar library

136 lines (129 loc) 8.85 kB
import { Factory } from "../core/factory"; import { isNil } from "@visactor/vutils"; import { registerGlyphGraphic, registerPathGraphic } from "../graph/mark/graphic"; import { registerGlyphMark } from "../view/glyph"; export const getHorizontalPath = (options, ratio) => { var _a; const curvature = null !== (_a = options.curvature) && void 0 !== _a ? _a : .5, thickness = "number" == typeof ratio ? options.thickness * ratio : options.thickness; let x0 = options.x0, x1 = options.x1, y00 = options.y0, y10 = options.y1, cpx0 = x0 + curvature * (x1 - x0), cpx1 = x1 + curvature * (x0 - x1), formatter = v => v; !1 !== options.round && (x0 = Math.round(x0), x1 = Math.round(x1), y00 = Math.round(y00), y10 = Math.round(y10), cpx0 = Math.round(cpx0), cpx1 = Math.round(cpx1), formatter = Math.round); "line" === options.pathType || options.pathType; "center" === options.align ? (y00 = formatter(options.y0 - thickness / 2), y10 = formatter(options.y1 - thickness / 2)) : "end" === options.align ? (y00 = formatter(options.y0 + options.thickness / 2 - thickness), y10 = formatter(options.y1 + options.thickness / 2 - thickness)) : (y00 = formatter(options.y0 - options.thickness / 2), y10 = formatter(options.y1 - options.thickness / 2)); const y01 = formatter(y00 + thickness), y11 = formatter(y10 + thickness), hasLength = Math.abs(x1 - x0) > 1e-6, endArrowPath = options.endArrow && hasLength ? `L${x1},${formatter(y10 - thickness / 2)}L${formatter(x1 + thickness)},${formatter((y10 + y11) / 2)}L${x1},${formatter(y11 + thickness / 2)}` : "", startArrowPath = options.startArrow && hasLength ? `L${x0},${formatter(y01 + thickness / 2)}L${formatter(x0 - thickness)},${formatter((y00 + y01) / 2)}L${x0},${formatter(y00 - thickness / 2)}` : ""; return "line" === options.pathType ? `M${x0},${y00}L${x1},${y10}${endArrowPath}L${x1},${y11}L${x0},${y01}${startArrowPath}Z` : "polyline" === options.pathType ? `M${x0},${y00}L${cpx0},${y00}L${cpx0},${y10}L${x1},${y10}\n ${endArrowPath}L${x1},${y11}L${cpx0},${y11}L${cpx0},${y01}L${x0},${y01}${startArrowPath}Z` : `M${x0},${y00}C${cpx0},${y00},${cpx1},${y10},${x1},${y10}\n ${endArrowPath}L${x1},${y11}C${cpx1},${y11},${cpx0},${y01},${x0},${y01}${startArrowPath}Z`; }; export const getVerticalPath = (options, ratio) => { var _a; const curvature = null !== (_a = options.curvature) && void 0 !== _a ? _a : .5, thickness = "number" == typeof ratio ? options.thickness * ratio : options.thickness; let y0 = options.y0, y1 = options.y1, x00 = options.x0, x10 = options.x1, cpy0 = y0 + curvature * (y1 - y0), cpy1 = y1 + curvature * (y0 - y1), formatter = v => v; !1 !== options.round && (formatter = Math.round, y0 = Math.round(y0), y1 = Math.round(y1), x00 = Math.round(x00), x10 = Math.round(x10), cpy0 = Math.round(cpy0), cpy1 = Math.round(cpy1)); "line" === options.pathType || options.pathType; "center" === options.align ? (x00 = formatter(options.x0 - thickness / 2), x10 = formatter(options.x1 - thickness / 2)) : "end" === options.align ? (x00 = formatter(options.x0 + options.thickness / 2 - thickness), x10 = formatter(options.x1 + options.thickness / 2 - thickness)) : (x00 = formatter(options.x0 - options.thickness / 2), x10 = formatter(options.x1 - options.thickness / 2)); const x01 = formatter(x00 + thickness), x11 = formatter(x10 + thickness), hasLength = Math.abs(y1 - y0) > 1e-6, endArrowPath = options.endArrow && hasLength ? `L${formatter(x10 - thickness / 2)},${y1}L${formatter((x10 + x11) / 2)},${formatter(y1 + thickness)}L${formatter(x11 + thickness / 2)},${y1}` : "", startArrowPath = options.startArrow && hasLength ? `L${formatter(x01 + thickness / 2)},${y0}L${formatter((x01 + x00) / 2)},${formatter(y0 - thickness)}L${formatter(x00 - thickness / 2)},${y0}` : ""; return "line" === options.pathType ? `M${x00},${y0}L${x10},${y1}${endArrowPath}L${x11},${y1}L${x01},${y0}${startArrowPath}Z` : "polyline" === options.pathType ? `M${x00},${y0}L${x00},${cpy0}L${x10},${cpy0}L${x10},${y1}\n ${endArrowPath}L${x11},${y1}L${x11},${cpy0}L${x01},${cpy0}L${x01},${y0}${startArrowPath}Z` : `M${x00},${y0}C${x00},${cpy0},${x10},${cpy1},${x10},${y1}\n ${endArrowPath}L${x11},${y1}C${x11},${cpy1},${x01},${cpy0},${x01},${y0}${startArrowPath}Z`; }; const encoder = (encodeValues, datum, element, config) => { var _a; const direction = null !== (_a = encodeValues.direction) && void 0 !== _a ? _a : null == config ? void 0 : config.direction, parsePath = [ "vertical", "TB", "BT" ].includes(direction) ? getVerticalPath : getHorizontalPath, isRatioShow = "number" == typeof encodeValues.ratio && encodeValues.ratio >= 0 && encodeValues.ratio <= 1, encodeChannels = Object.keys(encodeValues); return [ "x0", "y0", "x1", "y1" ].every((channel => encodeChannels.includes(channel))) ? { back: { path: isRatioShow ? parsePath(encodeValues, 1) : "" }, front: { path: parsePath(encodeValues, isRatioShow ? encodeValues.ratio : 1) } } : {}; }, linkPathGrowIn = (element, options, animationParameters) => { const linkValues = { x0: element.getGraphicAttribute("x0", !1), x1: element.getGraphicAttribute("x1", !1), y0: element.getGraphicAttribute("y0", !1), y1: element.getGraphicAttribute("y1", !1), thickness: element.getGraphicAttribute("thickness", !1), round: element.getGraphicAttribute("round", !1), align: element.getGraphicAttribute("align", !1), pathType: element.getGraphicAttribute("pathType", !1), endArrow: element.getGraphicAttribute("endArrow", !1), startArrow: element.getGraphicAttribute("startArrow", !1) }; return Object.keys(linkValues).forEach((key => { isNil(linkValues[key]) && delete linkValues[key]; })), { from: Object.assign({}, linkValues, { x1: linkValues.x0, y1: linkValues.y0 }), to: linkValues }; }, linkPathGrowOut = (element, options, animationParameters) => { const linkValues = { x0: element.getGraphicAttribute("x0", !0), x1: element.getGraphicAttribute("x1", !0), y0: element.getGraphicAttribute("y0", !0), y1: element.getGraphicAttribute("y1", !0), thickness: element.getGraphicAttribute("thickness", !0), round: element.getGraphicAttribute("round", !0), align: element.getGraphicAttribute("align", !0), pathType: element.getGraphicAttribute("pathType", !0), endArrow: element.getGraphicAttribute("endArrow", !0), startArrow: element.getGraphicAttribute("startArrow", !0) }; return Object.keys(linkValues).forEach((key => { isNil(linkValues[key]) && delete linkValues[key]; })), { from: linkValues, to: Object.assign({}, linkValues, { x1: linkValues.x0, y1: linkValues.y0 }) }; }, linkPathUpdate = (element, options, animationParameters) => { const bassLinkValues = { thickness: element.getGraphicAttribute("thickness", !1), round: element.getGraphicAttribute("round", !1), align: element.getGraphicAttribute("align", !1), pathType: element.getGraphicAttribute("pathType", !1), endArrow: element.getGraphicAttribute("endArrow", !1), startArrow: element.getGraphicAttribute("startArrow", !1) }; Object.keys(bassLinkValues).forEach((key => { isNil(bassLinkValues[key]) && delete bassLinkValues[key]; })); return { from: Object.assign(Object.assign({ x0: element.getGraphicAttribute("x0", !0), x1: element.getGraphicAttribute("x1", !0), y0: element.getGraphicAttribute("y0", !0), y1: element.getGraphicAttribute("y1", !0) }, bassLinkValues), bassLinkValues), to: Object.assign({ x0: element.getGraphicAttribute("x0", !1), x1: element.getGraphicAttribute("x1", !1), y0: element.getGraphicAttribute("y0", !1), y1: element.getGraphicAttribute("y1", !1) }, bassLinkValues) }; }; export const registerLinkPathGlyph = () => { Factory.registerGlyph("linkPath", { back: "path", front: "path" }).registerFunctionEncoder(encoder).registerChannelEncoder("backgroundStyle", ((channel, encodeValue) => ({ back: encodeValue }))).registerDefaultEncoder((() => ({ back: { zIndex: 0 }, front: { zIndex: 1 } }))), Factory.registerAnimationType("linkPathGrowIn", linkPathGrowIn), Factory.registerAnimationType("linkPathGrowOut", linkPathGrowOut), Factory.registerAnimationType("linkPathUpdate", linkPathUpdate), registerGlyphMark(), registerGlyphGraphic(), registerPathGraphic(); };