@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.
147 lines (146 loc) • 6.43 kB
JavaScript
import {
__spreadValues
} from "../chunk-G2ADBYYC.js";
import { getFormated, setArrayValue, cloneDeep } from "../chart-core/deps/utils";
import { itemPoint, itemLabel, itemContent } from "../chart-core/deps/constants";
import { isNull } from "@opentiny/utils";
const pieRadius = 100;
const ringRadius = [90, 100];
const roseRingRadius = [20, 100];
const pieOffsetY = "50%";
const modifySeries = ({ series, limitShowNum, t }) => {
let firstSerie = series[0];
if (limitShowNum && limitShowNum < firstSerie.data.length) {
let firstSerieData = firstSerie.data;
let remainArr = firstSerieData.slice(limitShowNum, firstSerieData.length);
let sum = 0;
remainArr.forEach((item) => sum += item.value);
firstSerie.data = firstSerieData.slice(0, limitShowNum);
firstSerie.data.push({ name: t("ui.chart.other"), value: sum });
}
};
const getPieSeries = (args) => {
const { dataType, digit, dimension, emphasis, innerRows, isRing, itemStyle, label, labelLine } = args;
const { level, limitShowNum, metrics, offsetY, percentShow, radius, roseType, selectedMode, t } = args;
let { series = [], levelTemp = {}, rowsTemp = [] } = {};
if (!level) {
rowsTemp.push(innerRows);
} else {
level.forEach((levelItems, index) => levelItems.forEach((item) => setArrayValue(levelTemp, item, index)));
innerRows.forEach((row) => {
let itemLevel = levelTemp[row[dimension]];
if (itemLevel && itemLevel.length) {
itemLevel.forEach((levelItem) => setArrayValue(rowsTemp, levelItem, row));
}
});
}
let serieBase = { type: "pie", selectedMode, emphasis, roseType, center: ["50%", offsetY] };
let rowsCount = rowsTemp.length;
let centerWidth = radius / rowsCount;
rowsTemp.forEach((dataRows, index) => {
let serie = __spreadValues({ data: [] }, serieBase);
if (!index) {
serie.radius = isRing ? radius : centerWidth;
} else {
let outerWidth = centerWidth + radius / (2 * rowsCount) * (2 * index - 1);
let innerWidth = outerWidth + radius / (2 * rowsCount);
serie.radius = [outerWidth, innerWidth];
}
rowsCount > 1 && index === 0 && (serie.label = { position: "inner" });
serie.label = __spreadValues({ color: "#191919" }, label);
serie.labelLine = __spreadValues({ smooth: true, lineStyle: { color: "#bbb" } }, labelLine);
serie.itemStyle = __spreadValues({ borderWidth: 2, borderColor: "#fff" }, itemStyle);
if (percentShow) {
let position = rowsCount > 1 && index === 0 ? "inner" : "outside";
let formatter = function(item) {
let tplt = [];
tplt.push(`${item.name}:`);
tplt.push(getFormated(item.value, dataType, digit));
tplt.push(`(${item.percent}%)`);
return tplt.join("");
};
serie.label = { normal: { show: true, position, formatter } };
}
serie.data = dataRows.map((row) => ({ name: row[dimension], value: row[metrics] }));
series.push(serie);
});
modifySeries({ series, limitShowNum, t });
return series;
};
const getPieLegend = (args) => {
const { dimension, innerRows, legendLimit, legendName, level, limitShowNum, t } = args;
let { legend = [], levelTemp = [] } = {};
if (level) {
level.forEach((levelItem) => levelItem.forEach((item) => levelTemp.push(item)));
legend = levelTemp;
} else if (limitShowNum && limitShowNum < innerRows.length) {
for (let i = limitShowNum - 1; i >= 0; i--) {
legend.unshift(innerRows[i][dimension]);
}
legend.push(t("ui.chart.other"));
} else {
legend = innerRows.map((row) => row[dimension]);
}
if (legend.length) {
let show = legend.length < legendLimit;
let formatter = function(name) {
return !isNull(legendName[name]) ? legendName[name] : name;
};
return { data: legend, show, formatter };
} else {
return false;
}
};
const getPieTooltip = (args) => {
const { dataType, digit, dimension, innerRows, limitShowNum, metrics, t } = args;
let { localeOther = t("ui.chart.other"), remainArr, sum = 0 } = {};
let mapHandler = (row) => {
sum += row[metrics];
return { name: row[dimension], value: row[metrics] };
};
remainArr = innerRows.map(mapHandler).slice(limitShowNum, innerRows.length);
let formatter = function(item) {
let tplt = [itemPoint(item.color)];
let percent;
if (!limitShowNum || item.name !== localeOther) {
tplt.push(itemLabel(item.name));
tplt.push(itemContent(getFormated(item.value, dataType, digit)));
tplt.push(itemContent(`(${item.percent}%)`));
} else {
tplt.push(localeOther + ":");
remainArr.forEach(({ name, value }) => {
percent = getFormated(value / sum, "percent");
tplt.push(`<br>${itemLabel(name)}`);
tplt.push(itemContent(getFormated(value, dataType, digit)));
tplt.push(itemContent(percent));
});
}
return tplt.join("");
};
return { formatter };
};
const pie = (columns, rows, settings, extra, isRing) => {
const innerRows = cloneDeep(rows);
const { dataType = "normal", digit = 2, dimension = columns[0], emphasis = { scale: true } } = settings;
const { itemStyle, label = false, labelLine, legendLimit = 30, legendName = {}, level = false } = settings;
const { limitShowNum = 0, metrics = columns[1], offsetY = pieOffsetY, percentShow } = settings;
const { roseType = false, selectedMode = false } = settings;
const { radius = isRing ? roseType ? roseRingRadius : ringRadius : pieRadius } = settings;
const { legendVisible, t, tooltipVisible } = extra;
limitShowNum && innerRows.sort((a, b) => b[metrics] - a[metrics]);
const seriesParams = { dataType, digit, dimension, emphasis, innerRows, isRing, itemStyle };
Object.assign(seriesParams, { label, labelLine, legendName, level, limitShowNum, metrics, offsetY });
Object.assign(seriesParams, { percentShow, radius, roseType, selectedMode, t });
const series = getPieSeries(seriesParams);
const legendParams = { dimension, innerRows, legendLimit, legendName, level, limitShowNum, t };
const legend = legendVisible && getPieLegend(legendParams);
const pieTooltip = getPieTooltip({ dataType, innerRows, limitShowNum, digit, metrics, dimension, t });
const tooltip = tooltipVisible && pieTooltip;
const options = { legend, series, tooltip };
return options;
};
const ring = (columns, rows, settings, extra) => pie(columns, rows, settings, extra, true);
export {
pie,
ring
};