@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
JavaScript
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
};