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.

147 lines (146 loc) 6.43 kB
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 };