|
|
@@ -0,0 +1,598 @@
|
|
|
+// 动画进度全局变量
|
|
|
+declare const process: number;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 图表数据点接口
|
|
|
+ */
|
|
|
+export interface DataPoint {
|
|
|
+ x: number;
|
|
|
+ y: number;
|
|
|
+ color?: string;
|
|
|
+ value?: number;
|
|
|
+ width?: number;
|
|
|
+ height?: number;
|
|
|
+ r?: number; // 气泡图半径
|
|
|
+ t?: string; // 气泡图文本
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 蜡烛图数据点
|
|
|
+ */
|
|
|
+export interface CandleDataPoint {
|
|
|
+ x: number;
|
|
|
+ y: number;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 堆叠数据点(包含 y0 位置)
|
|
|
+ */
|
|
|
+export interface StackDataPoint extends DataPoint {
|
|
|
+ y0: number;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 条形堆叠数据点(包含 x0 位置)
|
|
|
+ */
|
|
|
+export interface BarStackDataPoint {
|
|
|
+ color?: string;
|
|
|
+ y: number;
|
|
|
+ height: number;
|
|
|
+ x: number;
|
|
|
+ x0: number;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 山丘图数据点(包含宽度和值)
|
|
|
+ */
|
|
|
+export interface MountDataPoint extends DataPoint {
|
|
|
+ value: number;
|
|
|
+ width: number;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 图表配置接口
|
|
|
+ */
|
|
|
+export interface ChartOptions {
|
|
|
+ type: string;
|
|
|
+ categories?: string[];
|
|
|
+ xAxis?: {
|
|
|
+ boundaryGap?: string;
|
|
|
+ itemcount?: number;
|
|
|
+ [key: string]: any;
|
|
|
+ };
|
|
|
+ area: [number, number, number, number];
|
|
|
+ width: number;
|
|
|
+ height: number;
|
|
|
+ pix?: number;
|
|
|
+ enableScroll?: boolean;
|
|
|
+ extra?: {
|
|
|
+ mix?: {
|
|
|
+ column?: {
|
|
|
+ seriesGap?: number;
|
|
|
+ categoryGap?: number;
|
|
|
+ width?: number;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ column?: {
|
|
|
+ seriesGap?: number;
|
|
|
+ categoryGap?: number;
|
|
|
+ width?: number;
|
|
|
+ };
|
|
|
+ bar?: {
|
|
|
+ seriesGap?: number;
|
|
|
+ categoryGap?: number;
|
|
|
+ width?: number;
|
|
|
+ };
|
|
|
+ mount?: {
|
|
|
+ widthRatio?: number;
|
|
|
+ };
|
|
|
+ radar?: {
|
|
|
+ max?: number;
|
|
|
+ };
|
|
|
+ [key: string]: any;
|
|
|
+ };
|
|
|
+ chartData?: {
|
|
|
+ xAxisData?: {
|
|
|
+ ranges?: number[][];
|
|
|
+ };
|
|
|
+ [key: string]: any;
|
|
|
+ };
|
|
|
+ [key: string]: any;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * uCharts 配置接口
|
|
|
+ */
|
|
|
+export interface UChartsConfig {
|
|
|
+ version: string;
|
|
|
+ color: string[];
|
|
|
+ [key: string]: any;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 堆叠图系列项
|
|
|
+ */
|
|
|
+export interface SeriesItem {
|
|
|
+ data: (number | null)[];
|
|
|
+ color?: string;
|
|
|
+ [key: string]: any;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 折线动画选项
|
|
|
+ */
|
|
|
+export interface LineOption {
|
|
|
+ animation?: string;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 山丘图配置选项
|
|
|
+ */
|
|
|
+export interface MountOption {
|
|
|
+ widthRatio?: number;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取蜡烛图(K线图)数据点
|
|
|
+ * @param data - 蜡烛图数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @returns 蜡烛图数据点数组
|
|
|
+ */
|
|
|
+export function getCandleDataPoints(
|
|
|
+ data: (number | { value?: number })[][],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig
|
|
|
+): (CandleDataPoint[] | null)[] {
|
|
|
+ let points: (CandleDataPoint[] | null)[] = [];
|
|
|
+ let validHeight = opts.height! - opts.area[0] - opts.area[2];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let cPoints: CandleDataPoint[] = [];
|
|
|
+ item.forEach(function(items, indexs) {
|
|
|
+ let point: CandleDataPoint = { x: 0, y: 0 };
|
|
|
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
|
|
|
+ let value = typeof items === 'object' && items.value !== undefined ? items.value : items;
|
|
|
+ let height = validHeight * ((value as number) - minRange) / (maxRange - minRange);
|
|
|
+ height *= process;
|
|
|
+ point.y = opts.height! - Math.round(height) - opts.area[2];
|
|
|
+ cPoints.push(point);
|
|
|
+ });
|
|
|
+ points.push(cPoints);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取散点图和气泡图数据点
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @returns 数据点数组
|
|
|
+ */
|
|
|
+export function getDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig
|
|
|
+): (DataPoint | null)[] {
|
|
|
+ let boundaryGap = 'center';
|
|
|
+ if (opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' ) {
|
|
|
+ boundaryGap = opts.xAxis?.boundaryGap || 'center';
|
|
|
+ }
|
|
|
+ let points: (DataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ let validWidth = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: DataPoint = { x: 0, y: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ point.x = xAxisPoints[index];
|
|
|
+ let value: any = item;
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ if (Array.isArray(item)) {
|
|
|
+ const ranges = opts.chartData?.xAxisData?.ranges;
|
|
|
+ if (ranges && ranges.length > 0) {
|
|
|
+ const xranges = ranges as number[][];
|
|
|
+ const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
|
|
|
+ const xminRange = allRanges[0];
|
|
|
+ const xmaxRange = allRanges[allRanges.length - 1];
|
|
|
+ value = item[1];
|
|
|
+ point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
|
|
|
+ }
|
|
|
+ if(opts.type == 'bubble'){
|
|
|
+ point.r = item[2] as number | undefined;
|
|
|
+ point.t = item[3] as string | undefined;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ value = item.value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (boundaryGap == 'center') {
|
|
|
+ point.x += eachSpacing / 2;
|
|
|
+ }
|
|
|
+ let height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height *= process;
|
|
|
+ point.y = opts.height - height - opts.area[2];
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取折线图和面积图数据点
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @param lineOption - 折线动画选项
|
|
|
+ * @param chartProcess - 动画进度(未使用,保留用于兼容性)
|
|
|
+ * @returns 数据点数组
|
|
|
+ */
|
|
|
+export function getLineDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig,
|
|
|
+ lineOption: LineOption,
|
|
|
+ chartProcess: number
|
|
|
+): (DataPoint | null)[] {
|
|
|
+ let boundaryGap = opts.xAxis?.boundaryGap || 'center';
|
|
|
+ let points: (DataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ let validWidth = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: DataPoint = { x: 0, y: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ if(lineOption.animation == 'vertical'){
|
|
|
+ point.x = xAxisPoints[index];
|
|
|
+ let value: any = item;
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ if (Array.isArray(item)) {
|
|
|
+ const ranges = opts.chartData?.xAxisData?.ranges;
|
|
|
+ if (ranges && ranges.length > 0) {
|
|
|
+ const xranges = ranges as number[][];
|
|
|
+ const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
|
|
|
+ const xminRange = allRanges[0];
|
|
|
+ const xmaxRange = allRanges[allRanges.length - 1];
|
|
|
+ value = item[1];
|
|
|
+ point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ value = item.value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (boundaryGap == 'center') {
|
|
|
+ point.x += eachSpacing / 2;
|
|
|
+ }
|
|
|
+ let height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height *= process;
|
|
|
+ point.y = opts.height - height - opts.area[2];
|
|
|
+ points.push(point);
|
|
|
+ }else{
|
|
|
+ point.x = xAxisPoints[0] + eachSpacing * index * process;
|
|
|
+ let value: any = item;
|
|
|
+ if (boundaryGap == 'center') {
|
|
|
+ point.x += eachSpacing / 2;
|
|
|
+ }
|
|
|
+ let height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ point.y = opts.height - height - opts.area[2];
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取柱状图数据点
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @param zeroPoints - 零点(未使用,保留用于兼容性)
|
|
|
+ * @param chartProcess - 动画进度(未使用,保留用于兼容性)
|
|
|
+ * @returns 数据点数组
|
|
|
+ */
|
|
|
+export function getColumnDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig,
|
|
|
+ zeroPoints: number[],
|
|
|
+ chartProcess: number
|
|
|
+): (DataPoint | null)[] {
|
|
|
+ let points: (DataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ let validWidth = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: DataPoint = { x: 0, y: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ point.x = xAxisPoints[index];
|
|
|
+ let value: any = item;
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ if (Array.isArray(item)) {
|
|
|
+ const ranges = opts.chartData?.xAxisData?.ranges;
|
|
|
+ if (ranges && ranges.length > 0) {
|
|
|
+ const xranges = ranges as number[][];
|
|
|
+ const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
|
|
|
+ const xminRange = allRanges[0];
|
|
|
+ const xmaxRange = allRanges[allRanges.length - 1];
|
|
|
+ value = item[1];
|
|
|
+ point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ value = item.value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ point.x += eachSpacing / 2;
|
|
|
+ let height = validHeight * (value * process - minRange) / (maxRange - minRange);
|
|
|
+ point.y = opts.height - height - opts.area[2];
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取山丘图数据点
|
|
|
+ * @param series - 系列数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param mountOption - 山丘图配置选项
|
|
|
+ * @param zeroPoints - 零点(未使用,保留用于兼容性)
|
|
|
+ * @returns 山丘图数据点数组
|
|
|
+ */
|
|
|
+export function getMountDataPoints(
|
|
|
+ series: { data: number; color?: string }[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ mountOption: MountOption,
|
|
|
+ zeroPoints: number[]
|
|
|
+): (MountDataPoint | null)[] {
|
|
|
+ let points: (MountDataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ let validWidth = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ let mountWidth = eachSpacing * (mountOption.widthRatio || 1);
|
|
|
+ series.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: MountDataPoint = { x: 0, y: 0, value: 0, width: 0 };
|
|
|
+ point.color = item.color;
|
|
|
+ point.x = xAxisPoints[index];
|
|
|
+ point.x += eachSpacing / 2;
|
|
|
+ let value = item.data;
|
|
|
+ let height = validHeight * (value * process - minRange) / (maxRange - minRange);
|
|
|
+ point.y = opts.height - height - opts.area[2];
|
|
|
+ point.value = value;
|
|
|
+ point.width = mountWidth;
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取条形图数据点
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param yAxisPoints - Y轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @returns 数据点数组
|
|
|
+ */
|
|
|
+export function getBarDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ yAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig
|
|
|
+): DataPoint[] {
|
|
|
+ let points: DataPoint[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ let validWidth = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push({ x: 0, y: 0 });
|
|
|
+ } else {
|
|
|
+ let point: DataPoint = { x: 0, y: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ point.y = yAxisPoints[index];
|
|
|
+ let value: any = item;
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ value = item.value;
|
|
|
+ }
|
|
|
+ let height = validWidth * (value - minRange) / (maxRange - minRange);
|
|
|
+ height *= process;
|
|
|
+ if ('height' in point) {
|
|
|
+ (point as any).height = height;
|
|
|
+ }
|
|
|
+ if ('value' in point) {
|
|
|
+ point.value = value;
|
|
|
+ }
|
|
|
+ point.x = height + opts.area[3];
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取堆叠图数据点(用于柱状图/折线图堆叠)
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param xAxisPoints - X轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @param seriesIndex - 当前系列索引
|
|
|
+ * @param stackSeries - 所有堆叠系列数据
|
|
|
+ * @returns 堆叠数据点数组
|
|
|
+ */
|
|
|
+export function getStackDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ xAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig,
|
|
|
+ seriesIndex: number,
|
|
|
+ stackSeries: SeriesItem[]
|
|
|
+): (StackDataPoint | null)[] {
|
|
|
+ let points: (StackDataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.height - opts.area[0] - opts.area[2];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: StackDataPoint = { x: 0, y: 0, y0: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
|
|
|
+
|
|
|
+ let height: number, height0: number;
|
|
|
+ if (seriesIndex > 0) {
|
|
|
+ let value = 0;
|
|
|
+ for (let i = 0; i <= seriesIndex; i++) {
|
|
|
+ value += stackSeries[i].data[index] || 0;
|
|
|
+ }
|
|
|
+ let value0 = value - (typeof item === 'object' && item !== null ? item.value || 0 : item);
|
|
|
+ height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
|
|
|
+ } else {
|
|
|
+ let value = typeof item === 'object' && item !== null ? item.value || 0 : item;
|
|
|
+ height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height0 = 0;
|
|
|
+ }
|
|
|
+ let heightc = height0;
|
|
|
+ height *= process;
|
|
|
+ heightc *= process;
|
|
|
+ point.y = opts.height - Math.round(height) - opts.area[2];
|
|
|
+ point.y0 = opts.height - Math.round(heightc) - opts.area[2];
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取条形堆叠图数据点
|
|
|
+ * @param data - 数据数组
|
|
|
+ * @param minRange - 最小范围值
|
|
|
+ * @param maxRange - 最大范围值
|
|
|
+ * @param yAxisPoints - Y轴点数组
|
|
|
+ * @param eachSpacing - 每个点之间的间距
|
|
|
+ * @param opts - 图表配置
|
|
|
+ * @param config - uCharts配置
|
|
|
+ * @param seriesIndex - 当前系列索引
|
|
|
+ * @param stackSeries - 所有堆叠系列数据
|
|
|
+ * @returns 条形堆叠数据点数组
|
|
|
+ */
|
|
|
+export function getBarStackDataPoints(
|
|
|
+ data: (number | DataPoint | null)[],
|
|
|
+ minRange: number,
|
|
|
+ maxRange: number,
|
|
|
+ yAxisPoints: number[],
|
|
|
+ eachSpacing: number,
|
|
|
+ opts: ChartOptions,
|
|
|
+ config: UChartsConfig,
|
|
|
+ seriesIndex: number,
|
|
|
+ stackSeries: SeriesItem[]
|
|
|
+): (BarStackDataPoint | null)[] {
|
|
|
+ let points: (BarStackDataPoint | null)[] = [];
|
|
|
+ let validHeight = opts.width - opts.area[1] - opts.area[3];
|
|
|
+ data.forEach(function(item, index) {
|
|
|
+ if (item === null) {
|
|
|
+ points.push(null);
|
|
|
+ } else {
|
|
|
+ let point: BarStackDataPoint = { x: 0, x0: 0, y: 0, height: 0 };
|
|
|
+ if (typeof item === 'object' && item !== null) {
|
|
|
+ point.color = item.color;
|
|
|
+ }
|
|
|
+ point.y = yAxisPoints[index];
|
|
|
+ let height: number, height0: number;
|
|
|
+ if (seriesIndex > 0) {
|
|
|
+ let value = 0;
|
|
|
+ for (let i = 0; i <= seriesIndex; i++) {
|
|
|
+ value += stackSeries[i].data[index] || 0;
|
|
|
+ }
|
|
|
+ let value0 = value - (typeof item === 'object' && item !== null ? item.value || 0 : item);
|
|
|
+ height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
|
|
|
+ } else {
|
|
|
+ let value = typeof item === 'object' && item !== null ? item.value || 0 : item;
|
|
|
+ height = validHeight * (value - minRange) / (maxRange - minRange);
|
|
|
+ height0 = 0;
|
|
|
+ }
|
|
|
+ let heightc = height0;
|
|
|
+ height *= process;
|
|
|
+ heightc *= process;
|
|
|
+ point.height = height - heightc;
|
|
|
+ point.x = opts.area[3] + height;
|
|
|
+ point.x0 = opts.area[3] + heightc;
|
|
|
+ points.push(point);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return points;
|
|
|
+}
|