| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535 |
- 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,
- upColor: string,
- downColor: string,
- equalColor: string,
- }
- export type Source = {
- date: string, // xAxis数据,必须是第一个属性
- open: number,
- close: number,
- lowest: number,
- highest: number,
- ma5: string,
- ma10: string,
- ma15: string,
- vol: number,
- macd: string,
- dif: string,
- dea: string,
- k: string,
- d: string,
- j: string,
- cci: string,
- }
- // 图表数据
- type ChartData = {
- source: Source[],
- }
- export function handleEchart() {
- const options = ref<EChartsOption>();
- // 当前主题
- const theme = getTheme();
- // 图表数据
- const chartData = ref<ChartData>({
- source: []
- });
- // 初始化图表配置
- const initOptions = (seriesType: string) => {
- const { source } = chartData.value;
- const option: EChartsOption = {
- dataset: {
- dimensions: ['date', 'open', 'close', 'lowest', 'highest', 'ma5', 'ma10', 'ma15', 'vol', 'macd', 'dif', 'dea', 'k', 'd', 'j', 'cci'],
- source
- },
- animation: false,
- axisPointer: {
- link: [
- {
- xAxisIndex: 'all'
- }
- ],
- },
- legend: {
- //图例控件,点击图例控制哪些系列不显示
- type: 'scroll',
- data: ['MA5', 'MA10', 'MA15'],
- selected: {
- VOL: seriesType === 'VOL',
- MACD: seriesType === 'MACD',
- DIF: seriesType === 'MACD',
- DEA: seriesType === 'MACD',
- K: seriesType === 'KDJ',
- D: seriesType === 'KDJ',
- J: seriesType === 'KDJ',
- CCI: seriesType === 'CCI',
- },
- itemWidth: 14,
- itemHeight: 2,
- left: '5%',
- top: 0,
- 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, index: number) => {
- if (index === 0) {
- result += '<div class="tooltip-title">' + moment(item.data.date).format('YYYY-MM-DD HH:mm') + '</div>';
- }
- if (item.seriesType === 'candlestick') {
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>开盘</span><span>' + item.data.open + '</span></div>';
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>收盘</span><span>' + item.data.close + '</span></div>';
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>最低</span><span>' + item.data.lowest + '</span></div>';
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>最高</span><span>' + item.data.highest + '</span></div>';
- } else {
- const key = item.dimensionNames[item.encode.y[0]];
- result += '<div class="tooltip-item"><span><i style="background-color:' + item.color + ';"></i>' + item.seriesName + '</span><span>' + item.data[key] + '</span></div>';
- }
- })
- return result;
- },
- },
- grid: [
- // K线
- {
- top: '8%',
- left: '8%',
- right: '8%',
- height: '55%',
- },
- // MACD、VOL、KDJ
- {
- top: '73%',
- left: '8%',
- right: '8%',
- height: '20%',
- }
- ],
- xAxis: [
- // K线时间轴
- {
- type: 'category',
- axisLabel: {
- formatter: (val: any) => moment(val).format('YYYY/MM/DD'),
- },
- splitLine: {
- show: true,
- },
- },
- // MACD、VOL、KDJ时间轴
- {
- type: 'category',
- gridIndex: 1,
- axisLabel: {
- show: false,
- formatter: (val: any) => moment(val).format('YYYY/MM/DD'),
- },
- axisLine: {
- show: false,
- },
- axisTick: {
- show: false,
- },
- splitLine: {
- show: true,
- },
- }
- ],
- yAxis: [
- {
- scale: true,
- },
- {
- scale: true,
- gridIndex: 1,
- }
- ],
- dataZoom: [
- {
- type: 'inside',
- xAxisIndex: [0, 1],
- startValue: source.length - 120, // 起始显示K线条数(最新120条)
- endValue: source.length,
- minValueSpan: 60, // 限制窗口缩放显示最少数据条数
- maxValueSpan: 400, // 限制窗口缩放显示最大数据条数
- },
- {
- show: false,
- type: 'slider',
- xAxisIndex: [0, 1],
- },
- ],
- series: [
- {
- name: 'K线',
- type: 'candlestick',
- // Y轴数据
- markLine: {
- animation: false,
- // 标线两端图标
- symbol: 'none',
- // 标线标签样式
- label: {
- fontWeight: 'bold',
- position: 'end',
- },
- // 标线样式
- lineStyle: {
- type: 'dashed',
- },
- data: [
- {
- // 当前价
- yAxis: source.length ? source[source.length - 1].close : 0,
- },
- ],
- },
- },
- {
- name: 'MA5',
- type: 'line',
- sampling: 'average', //折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'MA10',
- type: 'line',
- sampling: 'average',
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'MA15',
- type: 'line',
- sampling: 'average',
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'VOL',
- type: 'bar',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- barWidth: '60%',
- },
- {
- name: 'MACD',
- type: 'bar',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- barWidth: '20%',
- },
- {
- name: 'DIF',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'DEA',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'K',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'D',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'J',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- {
- name: 'CCI',
- type: 'line',
- sampling: 'average',
- xAxisIndex: 1,
- yAxisIndex: 1,
- smooth: true,
- symbol: 'none',
- lineStyle: {
- width: 1,
- opacity: 0.8,
- },
- },
- ],
- };
- options.value = deepMerge(option, getColors(theme.value));
- };
- // 动态更新数据
- const updateOptions = (seriesType: string) => {
- const { source } = chartData.value;
- if (source.length) {
- options.value = {
- legend: {
- selected: {
- VOL: seriesType === 'VOL',
- MACD: seriesType === 'MACD',
- DIF: seriesType === 'MACD',
- DEA: seriesType === 'MACD',
- K: seriesType === 'KDJ',
- D: seriesType === 'KDJ',
- J: seriesType === 'KDJ',
- CCI: seriesType === 'CCI',
- },
- },
- dataset: {
- source
- },
- series: [
- {
- name: 'K线',
- markLine: {
- data: [
- {
- yAxis: source[source.length - 1].close,
- },
- ],
- },
- },
- ],
- }
- }
- };
- // 设置图表样式
- 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: 'VOL',
- itemStyle: {
- color: (params: any) => {
- // 判断收盘价是否高于或等于开盘价
- if (params.data.close >= params.data.open) {
- return colors.upColor;
- } else {
- return colors.downColor;
- }
- },
- }
- },
- {
- name: 'MACD',
- itemStyle: {
- color: (params: any) => {
- if (params.data.macd > 0) {
- return colors.upColor;
- } else {
- return colors.downColor;
- }
- },
- }
- },
- ]
- }
- }
- // 获取图表样式配置
- 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',
- upColor: '#eb5454',
- downColor: '#47b262',
- equalColor: '#fff',
- });
- case ThemeEnum.light:
- return setColors({
- backgroundColor: 'transparent',
- axisPointerLabelColor: '#fff',
- legendTextColor: '#FC9618',
- xAxisLineColor: '#DAE5EC',
- yAxisLineColor: '#DAE5EC',
- seriesMarkLabelColor: '#ACB8C0',
- seriesMarkLineColor: '#ACB8C0',
- upColor: '#eb5454',
- downColor: '#47b262',
- equalColor: '#333',
- });
- }
- }
- watch(theme, (val) => {
- options.value = getColors(val);
- });
- return {
- chartData,
- options,
- initOptions,
- updateOptions,
- }
- }
|