feat: 更新交易视图,添加成交量数据支持并优化用户界面
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type { Awaitable } from "@vueuse/core";
|
||||
import type { ChartOptions, DeepPartial, IChartApi, ISeriesApi, LayoutOptions, SeriesDataItemTypeMap, SeriesType } from "lightweight-charts";
|
||||
import type { ChartOptions, DeepPartial, HistogramData, IChartApi, ISeriesApi, LayoutOptions, SeriesDataItemTypeMap, SeriesType, Time } from "lightweight-charts";
|
||||
import type { ThemeMode } from "./useTheme";
|
||||
import { AreaSeries, BarSeries, BaselineSeries, CandlestickSeries, ColorType, createChart, HistogramSeries, LineSeries } from "lightweight-charts";
|
||||
import { cloneDeep, mergeWith } from "lodash-es";
|
||||
@@ -12,12 +12,19 @@ export type WeightChartOptions = DeepPartial<ChartOptions>;
|
||||
|
||||
export type TradingViewData = (() => Awaitable<TData[]>) | MaybeRefOrGetter<TData[]>;
|
||||
|
||||
export interface VolumeData extends HistogramData {
|
||||
value: number;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export interface TradingViewOptions<T = Series> {
|
||||
theme?: ThemeMode;
|
||||
type?: T;
|
||||
data?: TradingViewData;
|
||||
volumeData?: MaybeRefOrGetter<VolumeData[]>;
|
||||
weightChartOptions?: MaybeRefOrGetter<WeightChartOptions>;
|
||||
autosize?: boolean;
|
||||
showVolume?: boolean;
|
||||
}
|
||||
|
||||
const lightThemeLayout: Partial<LayoutOptions> = {
|
||||
@@ -34,11 +41,13 @@ const initializeOptions: Required<TradingViewOptions> = {
|
||||
theme: "dark",
|
||||
type: "Candlestick",
|
||||
data: [],
|
||||
volumeData: [],
|
||||
weightChartOptions: {
|
||||
width: 400,
|
||||
height: 300,
|
||||
},
|
||||
autosize: true,
|
||||
showVolume: true,
|
||||
};
|
||||
|
||||
function getChartSeriesDefinition(type: Series) {
|
||||
@@ -68,6 +77,7 @@ export function useTradingView(target: MaybeRefOrGetter<HTMLElement | null>, opt
|
||||
const chartSeriesDefinition = getChartSeriesDefinition(opts.type);
|
||||
const chartEl = ref<HTMLElement | null>(null);
|
||||
const series = ref<ISeriesApi<SeriesType> | null>(null);
|
||||
const volumeSeries = ref<ISeriesApi<"Histogram"> | null>(null);
|
||||
|
||||
function fitContent() {
|
||||
chart.value?.timeScale().fitContent();
|
||||
@@ -103,6 +113,13 @@ export function useTradingView(target: MaybeRefOrGetter<HTMLElement | null>, opt
|
||||
}
|
||||
}
|
||||
|
||||
function setVolumeData(data: MaybeRefOrGetter<VolumeData[]>) {
|
||||
if (!volumeSeries.value)
|
||||
return;
|
||||
const volumeData = toValue(data);
|
||||
volumeSeries.value.setData(volumeData);
|
||||
}
|
||||
|
||||
function changeTheme(theme: ThemeMode) {
|
||||
if (!chart.value)
|
||||
return;
|
||||
@@ -115,11 +132,43 @@ export function useTradingView(target: MaybeRefOrGetter<HTMLElement | null>, opt
|
||||
if (!el)
|
||||
return;
|
||||
chartEl.value = el;
|
||||
chart.value = createChart(el, toValue(opts.weightChartOptions));
|
||||
series.value = chart.value.addSeries(chartSeriesDefinition);
|
||||
|
||||
const chartOptions = toValue(opts.weightChartOptions);
|
||||
chart.value = createChart(el, chartOptions);
|
||||
series.value = chart.value.addSeries(chartSeriesDefinition, {
|
||||
priceFormat: {
|
||||
type: "price",
|
||||
precision: 1,
|
||||
},
|
||||
});
|
||||
|
||||
// 添加成交量副图
|
||||
if (opts.showVolume) {
|
||||
volumeSeries.value = chart.value.addSeries(HistogramSeries, {
|
||||
priceFormat: {
|
||||
type: "volume",
|
||||
},
|
||||
priceScaleId: "", // 设置为右侧价格轴
|
||||
});
|
||||
|
||||
// 配置成交量图表在底部
|
||||
chart.value.priceScale("").applyOptions({
|
||||
scaleMargins: {
|
||||
top: 0.8,
|
||||
bottom: 0,
|
||||
},
|
||||
});
|
||||
|
||||
// 设置成交量数据
|
||||
if (opts.volumeData) {
|
||||
setVolumeData(opts.volumeData);
|
||||
}
|
||||
}
|
||||
|
||||
watch(isDark, (dark) => {
|
||||
changeTheme(dark ? "dark" : "light");
|
||||
}, { immediate: true });
|
||||
|
||||
setData(opts.data);
|
||||
fitContent();
|
||||
|
||||
@@ -129,6 +178,12 @@ export function useTradingView(target: MaybeRefOrGetter<HTMLElement | null>, opt
|
||||
}, { deep: true });
|
||||
}
|
||||
|
||||
if (isRef(opts.volumeData)) {
|
||||
watch(opts.volumeData, (newData) => {
|
||||
setVolumeData(newData);
|
||||
}, { deep: true });
|
||||
}
|
||||
|
||||
if (opts.autosize) {
|
||||
useTimeoutFn(() => {
|
||||
resize();
|
||||
@@ -149,5 +204,5 @@ export function useTradingView(target: MaybeRefOrGetter<HTMLElement | null>, opt
|
||||
chart.value.applyOptions(newOptions);
|
||||
}, { deep: true });
|
||||
|
||||
return { chart, series, fitContent, resize };
|
||||
return { chart, series, volumeSeries, fitContent, resize, setVolumeData };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user