| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- import { ref, watch } from "vue";
- import { getTheme, ThemeEnum } from '@/common/config/theme';
- import { deepMerge } from '@/utils/objHandle'
- import { EChartsOption } from 'echarts';
- import moment from 'moment';
- // 命名待优化
- type Colors = {
- backgroundColor: string, // 图表背景颜色
- axisPointerLabelColor: string,
- legendTextColor: string,
- xAxisLineColor: string
- yAxisLineColor: string,
- seriesMarkLabelColor: string,
- seriesMarkLineColor: string,
- }
- // 图表数据
- export type ChartData = {
- datas: number[][], // 历史数据
- times: string[], // 历史日期
- ma5: (number | string)[], //均线数据
- ma10: (number | string)[], //均线数据
- ma15: (number | string)[], //均线数据
- dif: (number | string)[],
- dea: (number | string)[],
- macd: (number | string)[],
- }
- export function handleEchart() {
- const options = ref<EChartsOption>();
- // 当前主题
- const theme = getTheme();
- // 图表数据
- const chartData = ref<ChartData>({
- datas: [],
- times: [],
- ma5: [],
- ma10: [],
- ma15: [],
- dif: [],
- dea: [],
- macd: []
- });
- // 图表当前指示数据
- let chartDataIndex = 0;
- // 初始化图表配置
- const initOptions = () => {
- const { datas, times, ma5, ma10, ma15, dea, dif, macd } = chartData.value;
- const option: EChartsOption = {
- axisPointer: {
- link: [
- {
- xAxisIndex: 'all'
- }
- ],
- },
- legend: [
- {
- //图例控件,点击图例控制哪些系列不显示
- type: 'scroll',
- data: ['K线', 'MA5', 'MA10', 'MA15'],
- itemWidth: 14,
- itemHeight: 2,
- left: '5%',
- top: 0,
- textStyle: {
- fontSize: 12,
- },
- },
- {
- //图例控件,点击图例控制哪些系列不显示
- type: 'scroll',
- data: ['MACD', 'DIF', 'DEA'],
- itemWidth: 14,
- itemHeight: 2,
- left: '5%',
- top: '70%',
- textStyle: {
- fontSize: 12,
- },
- },
- ],
- // 悬浮框
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'cross',
- },
- backgroundColor: 'rgba(255,255,255,.95)',
- borderWidth: 1,
- borderRadius: 3,
- textStyle: {
- color: '#4d535c',
- },
- className: 'tooltip',
- formatter: (params: any) => {
- let result = '';
- params.forEach((item: any) => {
- if (item.seriesType === 'candlestick') {
- result += '<div class="tooltip-title">' + moment(item.name).format('YYYY/MM/DD') + '</div>';
- item.value.forEach((data: number[], i: number) => {
- if (i > 0) {
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>';
- switch (i) {
- case 1:
- result += '开盘';
- break;
- case 2:
- result += '收盘';
- break;
- case 3:
- result += '最低';
- break;
- case 4:
- result += '最高';
- break;
- }
- result += '</span><span>' + data + '</span></div>';
- }
- })
- } else if (item.seriesType === 'line') {
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>' + item.seriesName + '</span><span>' + item.value + '</span></div>';
- }
- })
- return result;
- },
- },
- grid: [
- // K线
- {
- top: '8%',
- left: '8%',
- right: '8%',
- height: '55%',
- },
- // MACD
- {
- top: '75%',
- left: '8%',
- right: '8%',
- height: '20%',
- }
- ],
- xAxis: [
- {
- type: 'category',
- // X轴时间线
- data: times,
- axisLabel: {
- formatter: (val: any) => moment(val).format('YYYY/MM/DD'),
- },
- splitLine: {
- // 坐标分隔线
- show: true,
- },
- },
- {
- type: 'category',
- // X轴时间线
- data: times,
- gridIndex: 1,
- axisLabel: {
- show: false,
- },
- splitLine: {
- // 坐标分隔线
- show: true,
- },
- }
- ],
- yAxis: [
- {
- scale: true,
- },
- {
- scale: true,
- gridIndex: 1,
- }
- ],
- dataZoom: [
- {
- type: 'inside',
- xAxisIndex: [0, 1],
- // 起始显示K线条数(最新200条)
- startValue: times.length - 200,
- endValue: times.length,
- // 限制窗口缩放显示最少数据条数
- minValueSpan: 30,
- },
- {
- show: false,
- type: 'slider',
- xAxisIndex: [0, 1],
- },
- ],
- series: [
- {
- name: 'K线',
- type: 'candlestick',
- // Y轴数据
- data: datas,
- markLine: {
- animation: false,
- // 标线两端图标
- symbol: 'none',
- // 标线标签样式
- label: {
- fontWeight: 'bold',
- position: 'end',
- },
- // 标线样式
- lineStyle: {
- type: 'dashed',
- },
- data: [
- {
- // 最新价
- yAxis: datas[datas.length - 1][1],
- },
- ],
- },
- },
- {
- name: 'MA5',
- type: 'line',
- sampling: 'average', //折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率
- data: ma5,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'MA10',
- type: 'line',
- sampling: 'average',
- data: ma10,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'MA15',
- type: 'line',
- sampling: 'average',
- data: ma15,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'MACD',
- type: 'bar',
- sampling: 'average',
- data: macd,
- xAxisIndex: 1,
- yAxisIndex: 1,
- barWidth: '20%',
- },
- {
- name: 'DIF',
- type: 'line',
- sampling: 'average',
- data: dif,
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'DEA',
- type: 'line',
- sampling: 'average',
- data: dea,
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- ],
- };
- options.value = deepMerge(option, getColors(theme.value));
- };
- // 动态更新数据
- const updateOptions = () => {
- const { datas, ma5, ma10, ma15, macd, dif, dea } = chartData.value;
- if (datas.length) {
- options.value = {
- series: [
- {
- name: 'K线',
- data: datas,
- markLine: {
- data: [
- {
- // 最新价
- yAxis: datas[datas.length - 1][1],
- },
- ],
- },
- },
- {
- name: 'MA5',
- data: ma5,
- },
- {
- name: 'MA10',
- data: ma10,
- },
- {
- name: 'MA15',
- data: ma15,
- },
- {
- name: 'MACD',
- data: macd,
- },
- {
- name: 'DIF',
- data: dif,
- },
- {
- name: 'DEA',
- data: dea,
- },
- ],
- };
- }
- };
- // 设置图表样式
- const setColors = (colors: Colors): EChartsOption => {
- return {
- // 图表背景颜色
- backgroundColor: colors.backgroundColor,
- axisPointer: {
- label: {
- color: colors.axisPointerLabelColor,
- },
- },
- legend: [
- {
- textStyle: {
- color: colors.legendTextColor,
- },
- }
- ],
- xAxis: [
- {
- splitLine: {
- lineStyle: {
- // 坐标分隔线颜色
- color: colors.xAxisLineColor,
- },
- },
- },
- {
- splitLine: {
- lineStyle: {
- // 坐标分隔线颜色
- color: colors.xAxisLineColor,
- },
- },
- }
- ],
- yAxis: [
- {
- splitLine: {
- lineStyle: {
- // 坐标分隔线颜色
- color: colors.xAxisLineColor,
- },
- },
- },
- {
- splitLine: {
- lineStyle: {
- // 坐标分隔线颜色
- color: colors.xAxisLineColor,
- },
- },
- }
- ],
- series: [
- {
- name: 'K线',
- markLine: {
- // 标线标签样式
- label: {
- color: colors.seriesMarkLabelColor,
- },
- // 标线样式
- lineStyle: {
- color: colors.seriesMarkLineColor,
- },
- },
- },
- {
- name: 'MA5',
- },
- {
- name: 'MA10',
- },
- {
- name: 'MA15',
- },
- {
- name: 'MACD',
- itemStyle: {
- color: (params: any) => {
- if (params.data > 0) {
- return '#eb5454';
- } else {
- return '#47b262';
- }
- },
- }
- },
- ]
- }
- }
- // 获取图表样式配置
- const getColors = (theme: ThemeEnum) => {
- switch (theme) {
- case ThemeEnum.default:
- case ThemeEnum.dark:
- return setColors({
- backgroundColor: 'transparent',
- axisPointerLabelColor: '#fff',
- legendTextColor: '#0e99e2',
- xAxisLineColor: '#171B1D',
- yAxisLineColor: '#171B1D',
- seriesMarkLabelColor: '#3C454B',
- seriesMarkLineColor: '#33393D',
- });
- case ThemeEnum.light:
- return setColors({
- backgroundColor: 'transparent',
- axisPointerLabelColor: '#fff',
- legendTextColor: '#FC9618',
- xAxisLineColor: '#DAE5EC',
- yAxisLineColor: '#DAE5EC',
- seriesMarkLabelColor: '#ACB8C0',
- seriesMarkLineColor: '#ACB8C0',
- });
- }
- }
- watch(theme, (val) => {
- options.value = getColors(val);
- });
- return {
- chartData,
- options,
- initOptions,
- updateOptions,
- }
- }
|