Files
vf_react/src/components/StockChart/utils/chartUtils.ts
2025-11-26 09:44:21 +08:00

266 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 图表通用工具函数
*
* 包含图表初始化、技术指标管理等通用逻辑
*/
import type { Chart, ActionType } from 'klinecharts';
/**
* 安全地执行图表操作(捕获异常)
*
* @param operation 操作名称
* @param fn 执行函数
* @returns T | null 执行结果或 null
*/
export const safeChartOperation = <T>(
operation: string,
fn: () => T
): T | null => {
try {
return fn();
} catch (error) {
return null;
}
};
/**
* 创建技术指标
*
* @param chart KLineChart 实例
* @param indicatorName 指标名称(如 'MA', 'MACD', 'VOL'
* @param params 指标参数(可选)
* @param isStack 是否叠加(主图指标为 true副图为 false
* @returns string | null 指标 ID
*/
export const createIndicator = (
chart: Chart,
indicatorName: string,
params?: number[],
isStack: boolean = false
): string | null => {
return safeChartOperation(`createIndicator:${indicatorName}`, () => {
const indicatorId = chart.createIndicator(
{
name: indicatorName,
...(params && { calcParams: params }),
},
isStack
);
return indicatorId;
});
};
/**
* 移除技术指标
*
* @param chart KLineChart 实例
* @param indicatorId 指标 ID不传则移除所有指标
*/
export const removeIndicator = (chart: Chart, indicatorId?: string): void => {
safeChartOperation('removeIndicator', () => {
if (indicatorId) {
chart.removeIndicator({ id: indicatorId });
} else {
chart.removeIndicator({});
}
});
};
/**
* 批量创建副图指标
*
* @param chart KLineChart 实例
* @param indicators 指标名称数组
* @returns string[] 指标 ID 数组
*/
export const createSubIndicators = (
chart: Chart,
indicators: string[]
): string[] => {
const ids: string[] = [];
indicators.forEach((name) => {
const id = createIndicator(chart, name, undefined, false);
if (id) {
ids.push(id);
}
});
return ids;
};
/**
* 设置图表缩放级别
*
* @param chart KLineChart 实例
* @param zoom 缩放级别0.5 - 2.0
*/
export const setChartZoom = (chart: Chart, zoom: number): void => {
safeChartOperation('setChartZoom', () => {
// KLineChart 10.0: 使用 setBarSpace 方法调整 K 线宽度(实现缩放效果)
const baseBarSpace = 8; // 默认 K 线宽度px
const newBarSpace = Math.max(4, Math.min(16, baseBarSpace * zoom));
// 注意KLineChart 10.0 可能没有直接的 zoom API需要通过调整样式实现
chart.setStyles({
candle: {
bar: {
upBorderColor: undefined, // 保持默认
upColor: undefined,
downBorderColor: undefined,
downColor: undefined,
},
// 通过调整蜡烛图宽度实现缩放效果
tooltip: {
showRule: 'always',
},
},
});
});
};
/**
* 滚动到指定时间
*
* @param chart KLineChart 实例
* @param timestamp 目标时间戳
*/
export const scrollToTimestamp = (chart: Chart, timestamp: number): void => {
safeChartOperation('scrollToTimestamp', () => {
// KLineChart 10.0: 使用 scrollToTimestamp 方法
chart.scrollToTimestamp(timestamp);
});
};
/**
* 调整图表大小(响应式)
*
* @param chart KLineChart 实例
*/
export const resizeChart = (chart: Chart): void => {
safeChartOperation('resizeChart', () => {
chart.resize();
});
};
/**
* 获取图表可见数据范围
*
* @param chart KLineChart 实例
* @returns { from: number, to: number } | null 可见范围
*/
export const getVisibleRange = (chart: Chart): { from: number; to: number } | null => {
return safeChartOperation('getVisibleRange', () => {
const data = chart.getDataList();
if (!data || data.length === 0) {
return null;
}
// 简化实现:返回所有数据范围
// 实际项目中可通过 chart 的内部状态获取可见范围
return {
from: 0,
to: data.length - 1,
};
});
};
/**
* 清空图表数据
*
* @param chart KLineChart 实例
*/
export const clearChartData = (chart: Chart): void => {
safeChartOperation('clearChartData', () => {
chart.resetData();
});
};
/**
* 截图(导出图表为图片)
*
* @param chart KLineChart 实例
* @param includeOverlay 是否包含 overlay
* @returns string | null Base64 图片数据
*/
export const exportChartImage = (
chart: Chart,
includeOverlay: boolean = true
): string | null => {
return safeChartOperation('exportChartImage', () => {
// KLineChart 10.0: 使用 getConvertPictureUrl 方法
const imageData = chart.getConvertPictureUrl(includeOverlay, 'png', '#ffffff');
return imageData;
});
};
/**
* 切换十字光标显示
*
* @param chart KLineChart 实例
* @param show 是否显示
*/
export const toggleCrosshair = (chart: Chart, show: boolean): void => {
safeChartOperation('toggleCrosshair', () => {
chart.setStyles({
crosshair: {
show,
},
});
});
};
/**
* 切换网格显示
*
* @param chart KLineChart 实例
* @param show 是否显示
*/
export const toggleGrid = (chart: Chart, show: boolean): void => {
safeChartOperation('toggleGrid', () => {
chart.setStyles({
grid: {
show,
},
});
});
};
/**
* 订阅图表事件
*
* @param chart KLineChart 实例
* @param eventName 事件名称
* @param handler 事件处理函数
*/
export const subscribeChartEvent = (
chart: Chart,
eventName: ActionType,
handler: (...args: any[]) => void
): void => {
safeChartOperation(`subscribeChartEvent:${eventName}`, () => {
chart.subscribeAction(eventName, handler);
});
};
/**
* 取消订阅图表事件
*
* @param chart KLineChart 实例
* @param eventName 事件名称
* @param handler 事件处理函数
*/
export const unsubscribeChartEvent = (
chart: Chart,
eventName: ActionType,
handler: (...args: any[]) => void
): void => {
safeChartOperation(`unsubscribeChartEvent:${eventName}`, () => {
chart.unsubscribeAction(eventName, handler);
});
};