UNPKG

@opentiny/vue-renderless

Version:

An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.

372 lines (371 loc) 13.2 kB
import { __spreadProps, __spreadValues } from "../chunk-G2ADBYYC.js"; import { layout, bpath, txt, hexToRgba } from "./river"; const buildOption = ({ api, emit, props, state, vm }) => () => { const WIDTH = state.canvasWidth = api.getContainerWidth() || props.config.canvasWidth; const { statusYes: STATUS_YES, statusNo: STATUS_NO, canvasHeight: HEIGHT, statusColor: STATUS_COLOR, tooltip: userTooltip, title: userTitle } = props.config; const chartData = layout(props.data, __spreadProps(__spreadValues({}, props.config), { canvasWidth: WIDTH }), vm.$el); const chartNodeData = chartData.filter((item) => item.type === "node"); const chartLinkData = chartData.filter((item) => item.type === "link"); const chartIconData = chartData.filter((item) => item.type === "icon"); const chartLegeData = chartData.filter((item) => item.type === "lege"); state.nameInfo = chartData.find((item) => item.type === "name"); emit("paths", JSON.parse(JSON.stringify(state.nameInfo.paths))); const renderNode = api.getRenderNode(chartNodeData); const renderLink = api.getRenderLink(chartLinkData); const renderIcon = api.getRenderIcon({ chartIconData, STATUS_COLOR, STATUS_YES, STATUS_NO }); const renderLege = api.getRenderLege(chartLegeData); const serieLine = api.getMarkLine(HEIGHT); const tooltip = api.getTooltip({ userTooltip, chartData }); const option = { grid: { left: "0%", right: "0%", bottom: "0%", top: "0%" }, xAxis: { min: 0, max: WIDTH, show: false }, yAxis: { min: 0, max: HEIGHT, show: false }, series: [ { type: "custom", name: "1", renderItem: renderNode, data: chartNodeData, zlevel: 1 }, { type: "custom", name: "2", renderItem: renderLink, data: chartLinkData, zlevel: 2 }, { type: "custom", name: "3", renderItem: renderIcon, data: chartIconData, zlevel: 3 }, { type: "custom", name: "4", renderItem: renderLege, data: chartLegeData, zlevel: 4 }, serieLine ], tooltip: { formatter: tooltip }, title: userTitle }; return option; }; const getRenderNode = ({ api: api0, echarts }) => (chartNodeData) => { const so = api0.setRiverRgbaOpacity; return (params, api) => { const { dataIndex, coordSys } = params; const { x: sx, y: sy, width: sw, height: sh } = coordSys; const data = chartNodeData[dataIndex]; const { x, y, width, height, g, lp, data: dataNode } = data; const rectShape = echarts.graphic.clipRectByRect({ x, y, width, height }, { x: sx, y: sy, width: sw, height: sh }); const lg = g[0].map((stop, i) => ({ offset: stop, color: so(dataNode, g[1][i]) })); const nodeLabel = txt(dataNode.label, api.font({}), lp[2]); return { type: "group", name: "node-group", children: [ { type: "rect", transition: ["shape"], shape: rectShape, style: { fill: new echarts.graphic.LinearGradient(0, 0, 1, 0, lg) } }, { type: "text", style: { x: lp[0], y: lp[1], text: nodeLabel.t, textFill: so(dataNode, "rgba(0,0,0,1)") } } ] }; }; }; const getRenderLink = ({ api, echarts }) => (chartLinkData) => { const so = api.setRiverRgbaOpacity; return (params) => { const { dataIndex } = params; const data = chartLinkData[dataIndex]; const { lb, g, data: dataLink } = data; const [posX, posY] = lb; const p = bpath(data); const lg = g[0].map((stop, i) => ({ offset: stop, color: so(dataLink, g[1][i]) })); return { type: "group", name: "link-group", position: [posX, posY], children: [ { type: "path", transition: ["shape"], shape: { d: p }, style: { fill: new echarts.graphic.LinearGradient(0, 0, 1, 0, lg) } } ] }; }; }; const getRenderIcon = ({ api: api0 }) => ({ chartIconData, STATUS_COLOR, STATUS_YES, STATUS_NO }) => { const so = api0.setRiverRgbaOpacity; const si = api0.setRiverIconStyle; return (params, api) => { const { dataIndex } = params; const data = chartIconData[dataIndex]; const { x, y, radius, lp, data: dataIcon } = data; const { status, text, skip } = dataIcon; if (skip) return null; const circleFill = STATUS_COLOR[String(status)]; const labelText = txt(dataIcon.label, api.font({}), lp[2]); const labelTextX = labelText.o ? lp[0] - x : lp[0] + lp[2] / 2 - x; const labelTextTa = labelText.o ? "" : "center"; const iconText = getIconText({ status, STATUS_YES, STATUS_NO, text, api, si, dataIcon }); return { type: "group", position: [x, y], children: [ { type: "circle", transition: ["shape"], shape: { cx: 0, cy: 0, r: si(dataIcon, "radius", radius) }, style: { fill: so(dataIcon, hexToRgba(si(dataIcon, "fill", circleFill))) } }, { type: "text", style: { x: labelTextX, y: lp[1] - y, text: labelText.t, textFill: so(dataIcon, hexToRgba(si(dataIcon, "labelColor", "#000"))), textAlign: labelTextTa } }, iconText ] }; }; }; const getIconText = ({ status, STATUS_YES, STATUS_NO, text, api, si, dataIcon }) => { let tmp = { type: "path", transition: ["shape"], shape: {}, style: { fill: si(dataIcon, "color", "#fff") } }; if (status === STATUS_YES) { tmp.shape.d = "M-1.7 4.5l9.4-9.4c.4-.4 1-.4 1.4 0 .4.4.4 1 0 1.4l-10 10.1c-.4.4-1 .4-1."; tmp.shape.d += "4 0-.1 0-.1-.1-.2-.1l-5.8-5.8c-.4-.4-.4-1 0-1.4.4-.4 1-.4 1.4 0l5.2 5.2z"; } else if (status === STATUS_NO) { tmp.shape.d = "M19.1 1.6H-6.9c-.5 0-.9-.4-.9-1s.4-1 .9-1h14.2c.5 0 .9.4.9 1s-.4 1-.9 1z"; } else { tmp = { type: "text", style: { x: 0, y: 1, text, textVerticalAlign: "middle", textAlign: "center", textFill: si(dataIcon, "color", "#fff"), textFont: api.font({ fontSize: 14 }) } }; } return tmp; }; const getRenderLege = () => (chartLegeData) => { return (params, api) => { const { dataIndex } = params; const data = chartLegeData[dataIndex]; const { cx, cy, radius, color, x, y, t, tw } = data; const legeLabel = txt(t, api.font({}), tw); return { type: "group", name: "lege-group", children: [ { type: "circle", transition: ["shape"], shape: { cx, cy, r: radius }, style: { fill: color } }, { type: "text", style: { x, y, text: legeLabel.t, textVerticalAlign: "middle", textAlign: "left", textFill: color } } ] }; }; }; const getTooltip = () => ({ userTooltip, chartData }) => { return (params) => { const { data } = params; const { data: dataItem, type, t: legeLabel, color: legeColor } = data; if (typeof userTooltip === "function") { return userTooltip(params, chartData); } else if (type === "node") { return dataItem.label; } else if (type === "icon") { return ` <div>Status: ${dataItem.status}</div> <div>Label: ${dataItem.label}</div> `; } else if (type === "link") { const riverNodes = chartData.filter((item) => item.type === "node"); const sourceRiverNode = riverNodes.find((riverNode) => riverNode.data.name === dataItem.source); const targetRiverNode = riverNodes.find((riverNode) => riverNode.data.name === dataItem.target); return ` <div>From: ${sourceRiverNode.data.label}</div> <div>To: ${targetRiverNode.data.label}</div> <div>Val: ${dataItem.value}</div> `; } else if (type === "lege") { return `<div style="background:${legeColor};color:#fff">${legeLabel}</div>`; } }; }; const getMarkLine = () => (h) => ({ type: "line", symbol: "none", data: [ [0, 0], [0, h] ], lineStyle: { width: 1, type: [2, 6], color: "#fff" }, zlevel: 0 }); const setChartOption = (state) => (option) => state.myChart.setOption(option); const setListeners = ({ api, emit, state }) => (option) => { const modifyOption = (option2, riverIcon) => { const serieLine = option2.series.find((serie) => serie.type === "line"); if (riverIcon) { const { x } = riverIcon; serieLine.data[0][0] = serieLine.data[1][0] = x; serieLine.lineStyle.color = "#000"; } else { serieLine.lineStyle.color = "#fff"; } return option2; }; state.myChart.on("mousemove", { seriesName: "3" }, (params) => { if (!state.markLineShow) { api.setChartOption(modifyOption(option, params.data)); state.markLineShow = true; } }); state.myChart.getZr().on("mousemove", (event) => { const notIcon = (parent = event.target) => { do { if (~["link-group", "node-group"].indexOf(parent.name)) return true; } while (parent = parent.parent); }; if (state.markLineShow && (!event.target || notIcon())) { api.setChartOption(modifyOption(option)); state.markLineShow = false; } }); state.myChart.on("click", { seriesName: "1" }, (params) => emit("click-node", params)); state.myChart.on("click", { seriesName: "2" }, (params) => emit("click-link", params)); state.myChart.on("click", { seriesName: "3" }, (params) => emit("click-icon", params)); state.myChart.on("click", { seriesName: "4" }, (params) => emit("click-lege", params)); }; const setRiverRgbaOpacity = ({ props, state }) => (data, rgba) => { const { config } = props; const { nameInfo, lighting } = state; const { nameField } = nameInfo; const { grayOpcity, lightOpcity } = config; const isw = (arr, name) => arr.find((item) => !name.indexOf(`${item}/`)); if (lighting && lighting.length) { const ci = rgba.lastIndexOf(","); const bi = rgba.lastIndexOf(")"); const dataName = data[nameField]; if (~lighting.indexOf(dataName)) { return rgba.slice(0, ci + 1) + lightOpcity + rgba.slice(bi); } else if (isw(lighting, dataName)) { return rgba.slice(0, ci + 1) + 1 + rgba.slice(bi); } else { return rgba.slice(0, ci + 1) + grayOpcity + rgba.slice(bi); } } else { return rgba; } }; const lightUp = ({ api, state }) => (param) => { const { nameInfo } = state; const { paths, nameSplit } = nameInfo; const getIndexVal = (i) => i >= 0 && i < paths.length ? paths[i].split(nameSplit) : []; const getPathVal = (path) => path ? path.split(nameSplit) : []; const getArrayVal = (arr) => { let res = []; arr.forEach((item) => { if (typeof item === "number") res = res.concat(getIndexVal(item)); else if (typeof item === "string") res = res.concat(getPathVal(item)); res = [...new Set(res)]; }); return res; }; if (typeof param === "number") { state.lighting = getIndexVal(param); } else if (typeof param === "string") { state.lighting = getPathVal(param); } else if (Array.isArray(param) && param.length) { state.lighting = getArrayVal(param); } else { state.lighting = []; } api.setChartOption(state.option); }; const setRiverIconStyle = (state) => (data, type, oldValue) => { const { styling, nameInfo } = state; const { nameField } = nameInfo; const dataName = data[nameField]; if (styling && styling.length) { for (let i = 0; i < styling.length; i++) { const stl = styling[i]; if (stl.name && dataName === stl.name && type && stl[type]) return stl[type]; } } return oldValue; }; const style = ({ api, state }) => (param) => { const styl = (obj) => { const { nodeName, iconIndex, styles } = obj; return Object.assign({}, styles, { name: `n${nodeName}/${iconIndex}`.toLowerCase() }); }; if (Array.isArray(param)) { const styling = []; param.forEach((item) => styling.push(styl(item))); state.styling = styling; } else if (typeof param === "object") { state.styling = [styl(param)]; } else { state.styling = []; } api.setChartOption(state.option); }; const computeCanvasStyle = ({ props, state }) => () => { const { canvasWidth, canvasTransformOrigin, canvasTransform } = state; const { canvasHeight } = props.config; const res = {}; if (canvasWidth) res.width = canvasWidth + "px"; if (canvasHeight) res.height = canvasHeight + "px"; if (canvasTransformOrigin) res.transformOrigin = canvasTransformOrigin; if (canvasTransform) res.transform = canvasTransform; return res; }; const getContainerWidth = (state) => () => state.containerEl && state.containerEl.getBoundingClientRect().width; const resizeListener = ({ props, state }) => () => { const { ignoreZoom = true } = props.config; const ratio = ignoreZoom ? window.innerWidth / window.outerWidth : 1; state.canvasTransform = "scale(" + ratio + ")"; }; export { buildOption, computeCanvasStyle, getContainerWidth, getMarkLine, getRenderIcon, getRenderLege, getRenderLink, getRenderNode, getTooltip, lightUp, resizeListener, setChartOption, setListeners, setRiverIconStyle, setRiverRgbaOpacity, style };