st-comp 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auto-imports.d.ts +1 -1
- package/components.d.ts +2 -1
- package/lib/bundle.js +10097 -9103
- package/lib/bundle.umd.cjs +10 -12
- package/lib/style.css +1 -1
- package/lib/talib.wasm +0 -0
- package/package.json +4 -1
- package/packages/Kline/components/Contextmenu/index.vue +110 -0
- package/packages/Kline/components/Tips/index.vue +18 -86
- package/packages/Kline/formatKlineData.ts +82 -53
- package/packages/Kline/images/buy.svg +1 -0
- package/packages/Kline/images/pen.png +0 -0
- package/packages/Kline/images/sell.svg +1 -0
- package/packages/Kline/images/t.svg +1 -0
- package/packages/Kline/index.vue +452 -119
- package/packages/Kline/option.ts +316 -0
- package/packages/Kline/type.d.ts +192 -24
- package/packages/Kline/utils.ts +576 -171
- package/packages/index.ts +0 -2
- package/public/talib.wasm +0 -0
- package/src/pages/Kline/api.ts +57 -0
- package/src/pages/Kline/components/MultiCycleSingleVariety.vue +728 -0
- package/src/pages/Kline/components/SingleCycleSingleVariety.vue +663 -0
- package/src/pages/Kline/index.vue +85 -16
- package/src/router/routes.ts +0 -5
- package/src/style.css +75 -0
- package/vite.config.ts +37 -27
- package/vitePlugins/testRelese.ts +67 -0
- package/packages/Echarts/index.ts +0 -8
- package/packages/Echarts/index.vue +0 -113
- package/packages/Kline/kline_theme_dark.json +0 -30
- package/packages/Kline/kline_theme_light.json +0 -30
- package/src/components/Echarts/index.vue +0 -31
- package/src/pages/Echarts/index.vue +0 -12
package/packages/Kline/index.vue
CHANGED
|
@@ -1,141 +1,321 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="st-kline">
|
|
3
|
-
<!-- 顶部Tips -->
|
|
4
|
-
<div class="st-kline-header">
|
|
5
|
-
<Tips
|
|
6
|
-
:activeIndex="activeIndex"
|
|
7
|
-
:klineData="klineData"
|
|
8
|
-
:indicatorData="indicatorData"
|
|
9
|
-
:indicatorConfig="indicatorConfigList[indicator]"
|
|
10
|
-
/>
|
|
11
|
-
</div>
|
|
12
|
-
<!-- 图表 -->
|
|
13
|
-
<st-echarts
|
|
14
|
-
v-if="option"
|
|
15
|
-
:option="option"
|
|
16
|
-
:themeConfig="{
|
|
17
|
-
name: 'kline',
|
|
18
|
-
light: klineThemeLight,
|
|
19
|
-
dark: klineThemeDark,
|
|
20
|
-
}"
|
|
21
|
-
@highlight="highlight"
|
|
22
|
-
@afterInit="afterInit"
|
|
23
|
-
/>
|
|
24
|
-
</div>
|
|
25
|
-
</template>
|
|
26
|
-
|
|
27
1
|
<script setup lang="ts">
|
|
28
|
-
import
|
|
29
|
-
import { ref, onMounted } from 'vue'
|
|
2
|
+
import * as echarts from 'echarts'
|
|
3
|
+
import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
|
|
30
4
|
import Tips from './components/Tips/index.vue'
|
|
31
|
-
import
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
import type {
|
|
35
|
-
import {
|
|
5
|
+
import Contextmenu from './components/Contextmenu/index.vue'
|
|
6
|
+
import { getOption, getLineOption } from './option'
|
|
7
|
+
import { printConsole, formatPrice } from './utils'
|
|
8
|
+
import type { EChartsType, EChartsOption, ECElementEvent, DataZoomComponentOption } from 'echarts'
|
|
9
|
+
import type { KlineDataType, LineDataType, InConfig, MenuDataType } from './type.d.ts'
|
|
36
10
|
|
|
37
11
|
/**
|
|
38
12
|
* 组件接收参数
|
|
39
|
-
* @param {
|
|
40
|
-
* @param {
|
|
41
|
-
* @param {
|
|
42
|
-
* @param {
|
|
43
|
-
* @param {
|
|
13
|
+
* @param {Object} indicator 指标线
|
|
14
|
+
* @param {KlineDataType} klineData K线数据
|
|
15
|
+
* @param {Array} markData 标注点位数据 [开平点, 买卖点, 信号点,...]
|
|
16
|
+
* @param {Array} lineData K线额外画线数据 [预警线, 持仓线, 条件单, ...]
|
|
17
|
+
* @param {Array} brushRange 区域刷选范围数据
|
|
18
|
+
* @param {Array} defaultMenuData 菜单项数据
|
|
19
|
+
*
|
|
20
|
+
* @param {InConfig} config 其他配置项数据
|
|
44
21
|
*/
|
|
45
22
|
const props = defineProps({
|
|
46
|
-
|
|
47
|
-
type:
|
|
48
|
-
|
|
23
|
+
indicator: {
|
|
24
|
+
type: Object,
|
|
25
|
+
default: () => ({
|
|
26
|
+
DKX: 'LINE#FFFFFF',
|
|
27
|
+
EMA120: 'LINE#E4007F',
|
|
28
|
+
EMA240: 'LINE#999999',
|
|
29
|
+
EMA60: 'LINE#00FF00',
|
|
30
|
+
MADKX: 'LINE#FFFF00',
|
|
31
|
+
WINDOW: '#0',
|
|
32
|
+
}),
|
|
49
33
|
},
|
|
50
|
-
|
|
51
|
-
type:
|
|
52
|
-
default: () =>
|
|
34
|
+
klineData: {
|
|
35
|
+
type: Array,
|
|
36
|
+
default: () => [],
|
|
53
37
|
},
|
|
54
|
-
|
|
55
|
-
type:
|
|
56
|
-
|
|
38
|
+
markData: {
|
|
39
|
+
type: Array,
|
|
40
|
+
default: () => [],
|
|
57
41
|
},
|
|
58
|
-
|
|
59
|
-
type:
|
|
60
|
-
|
|
42
|
+
lineData: {
|
|
43
|
+
type: Array,
|
|
44
|
+
default: () => [],
|
|
61
45
|
},
|
|
62
|
-
|
|
63
|
-
type:
|
|
64
|
-
|
|
46
|
+
brushRange: {
|
|
47
|
+
type: Array,
|
|
48
|
+
default: () => [],
|
|
49
|
+
},
|
|
50
|
+
defaultMenuData: {
|
|
51
|
+
type: Array,
|
|
52
|
+
default: () => [],
|
|
53
|
+
},
|
|
54
|
+
config: {
|
|
55
|
+
type: Object,
|
|
56
|
+
default: () => ({}),
|
|
65
57
|
},
|
|
66
58
|
})
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
60
|
+
/**
|
|
61
|
+
* K线功能默认配置
|
|
62
|
+
* @param {Number} totalBarCount k线总条数
|
|
63
|
+
* @param {Number} defaultShowBarCount k线默认展示条数
|
|
64
|
+
* @param {Number} preBarCount k线预加载条数,用于计算指标线
|
|
65
|
+
* ---------------------------------------------------------
|
|
66
|
+
* @param {Number} gridLeft k线组件grid: left
|
|
67
|
+
* @param {Number} gridTop k线组件grid: top
|
|
68
|
+
* @param {Number} gridRight k线组件grid: right
|
|
69
|
+
* @param {Number} gridBottom k线组件grid: bottom
|
|
70
|
+
* ---------------------------------------------------------
|
|
71
|
+
* @param {Object} warningConfig 预警线配置
|
|
72
|
+
* @param {Object} positionConfig 持仓线配置
|
|
73
|
+
* @param {Object} conditionConfig 条件单配置
|
|
74
|
+
*/
|
|
75
|
+
const defaultConfig: InConfig = {
|
|
76
|
+
totalBarCount: 3000,
|
|
77
|
+
defaultShowBarCount: 120,
|
|
78
|
+
preBarCount: 800,
|
|
79
|
+
gridLeft: 60,
|
|
80
|
+
gridTop: 0,
|
|
81
|
+
gridRight: 60,
|
|
82
|
+
gridBottom: 30,
|
|
83
|
+
// 预警线配置
|
|
84
|
+
warningConfig: {
|
|
85
|
+
draggable: false,
|
|
86
|
+
lineColor: '#fff',
|
|
87
|
+
textColor: '#fff',
|
|
88
|
+
},
|
|
89
|
+
// 持仓线配置
|
|
90
|
+
positionConfig: {
|
|
91
|
+
draggable: false,
|
|
92
|
+
lineColor: '#e45d07',
|
|
93
|
+
textColor: '#fff',
|
|
94
|
+
},
|
|
95
|
+
// 条件单配置
|
|
96
|
+
conditionConfig: {
|
|
97
|
+
draggable: false,
|
|
98
|
+
lineColor: '#fff',
|
|
99
|
+
textColor: '#fff',
|
|
100
|
+
profitLineColor: '#b71e44',
|
|
101
|
+
profitTextColor: '#fff',
|
|
102
|
+
lossLineColor: '#749b66',
|
|
103
|
+
lossTextColor: '#fff',
|
|
104
|
+
},
|
|
79
105
|
}
|
|
80
106
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
107
|
+
/**
|
|
108
|
+
* @description: 合并后的功能配置项
|
|
109
|
+
*/
|
|
110
|
+
const config: { value: InConfig } = computed(() => {
|
|
111
|
+
return { ...defaultConfig, ...props.config }
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const option = ref<any>(null) // 处理后的echarts配置
|
|
115
|
+
const activeIndex = ref(-1) // 当前鼠标激活的数据索引
|
|
116
|
+
|
|
117
|
+
// Tips: [开, 收, 低, 高, 成交额, 昨收]
|
|
118
|
+
const kLineTips = computed(() => {
|
|
119
|
+
if (option.value && option.value.dataset[0]?.source?.klineData[activeIndex.value]) {
|
|
120
|
+
const klineItem = option.value.dataset[0].source.klineData[activeIndex.value]
|
|
121
|
+
// 计算涨跌比
|
|
122
|
+
let ratio = (((klineItem[1] - klineItem[5]) / klineItem[1]) * 100).toFixed(2)
|
|
123
|
+
let ratioColor = +ratio === 0.0 ? 'white' : +ratio > 0 ? 'red' : '#00ff00'
|
|
124
|
+
return [
|
|
125
|
+
{
|
|
126
|
+
label: '开',
|
|
127
|
+
value: klineItem[0],
|
|
128
|
+
color: 'rgb(153, 153, 153)',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
label: '高',
|
|
132
|
+
value: klineItem[3],
|
|
133
|
+
color: 'rgb(153, 153, 153)',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: '低',
|
|
137
|
+
value: klineItem[2],
|
|
138
|
+
color: 'rgb(153, 153, 153)',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
label: '收',
|
|
142
|
+
value: klineItem[1],
|
|
143
|
+
color: 'rgb(153, 153, 153)',
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
label: '额',
|
|
147
|
+
value: formatPrice(klineItem[4]),
|
|
148
|
+
color: 'rgb(153, 153, 153)',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
label: '涨跌',
|
|
152
|
+
value: `${ratio}%`,
|
|
153
|
+
color: ratioColor,
|
|
154
|
+
},
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
return []
|
|
158
|
+
})
|
|
159
|
+
// Tips: 指标
|
|
160
|
+
const indicatorTips = computed(() => {
|
|
161
|
+
if (option.value && option.value.dataset[0]?.source?.indicatorData) {
|
|
162
|
+
return option.value.dataset[0].source.indicatorData.reduce((result: any, next: any) => {
|
|
163
|
+
next.data[activeIndex.value] &&
|
|
164
|
+
result.push({
|
|
165
|
+
label: next.key,
|
|
166
|
+
value: (next.data[activeIndex.value]).toFixed(2),
|
|
167
|
+
color: next.color,
|
|
168
|
+
})
|
|
169
|
+
return result
|
|
170
|
+
}, [])
|
|
171
|
+
}
|
|
172
|
+
return []
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
// 监视: props[klineData, indicator, markData] -> 重绘全部
|
|
176
|
+
watch(
|
|
177
|
+
() => [props.klineData, props.indicator, props.markData],
|
|
178
|
+
() => {
|
|
179
|
+
draw()
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
deep: true,
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
// 监视: props.lineData - 额外画线数据 -> 重新绘制额外线
|
|
186
|
+
watch(
|
|
187
|
+
() => props.lineData,
|
|
188
|
+
async () => {
|
|
189
|
+
printConsole('st-kline组件消息:props.lineData监控,额外画线数据发生改变,重绘->line', {
|
|
190
|
+
color: 'red',
|
|
191
|
+
})
|
|
192
|
+
draw('line')
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
deep: true,
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
// 监视: props.brushRange - 区域刷选数据 -> 重新刷选
|
|
199
|
+
watch(
|
|
200
|
+
() => props.brushRange,
|
|
201
|
+
async () => {
|
|
202
|
+
printConsole('st-kline组件消息:props.brushRange监控,区域刷选数据发生改变,重绘->brush', {
|
|
203
|
+
color: 'red',
|
|
204
|
+
})
|
|
205
|
+
draw('brush')
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
deep: true,
|
|
209
|
+
}
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* @description: 图表绘制函数
|
|
214
|
+
* @param {?String} type 绘制类型[Kline-K线,line-额外线条,brush-区域刷选,不传-全部]
|
|
215
|
+
*/
|
|
216
|
+
const draw = async (type?: string) => {
|
|
217
|
+
const callBackMap = new Map([
|
|
218
|
+
// kline-K线绘制
|
|
219
|
+
[
|
|
220
|
+
'kline',
|
|
221
|
+
async () => {
|
|
222
|
+
const newOption = await getOption(
|
|
223
|
+
props.klineData as KlineDataType,
|
|
224
|
+
props.markData,
|
|
225
|
+
props.indicator,
|
|
226
|
+
config.value
|
|
227
|
+
)
|
|
228
|
+
const { graphic } = echartsInstance.getOption() ?? { graphic: [] }
|
|
229
|
+
option.value = { ...newOption, graphic }
|
|
230
|
+
echartsInstance.setOption(option.value, true)
|
|
231
|
+
printConsole('st-kline组件消息:K线绘制完毕-draw', { color: 'green' })
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
// line-额外线条绘制
|
|
235
|
+
[
|
|
236
|
+
'line',
|
|
237
|
+
() => {
|
|
238
|
+
const echartsOptions = echartsInstance.getOption()
|
|
239
|
+
const graphic = getLineOption(props.lineData as LineDataType, config.value, echartsInstance)
|
|
240
|
+
option.value = { ...echartsOptions, graphic }
|
|
241
|
+
echartsInstance.setOption(option.value, {
|
|
242
|
+
replaceMerge: ['graphic'],
|
|
243
|
+
})
|
|
244
|
+
printConsole('st-kline组件消息:额外画线绘制完毕-draw', { color: 'green' })
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
// brush-区域刷选
|
|
248
|
+
[
|
|
249
|
+
'brush',
|
|
250
|
+
() => {
|
|
251
|
+
const { brushRange } = props
|
|
252
|
+
if (brushRange instanceof Array && brushRange.length > 0) {
|
|
253
|
+
echartsInstance.dispatchAction({
|
|
254
|
+
type: 'brush',
|
|
255
|
+
areas: [
|
|
256
|
+
{
|
|
257
|
+
brushType: 'lineX',
|
|
258
|
+
coordRange: [brushRange[0] + '', brushRange[1] + ''],
|
|
259
|
+
xAxisIndex: 0,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
})
|
|
263
|
+
printConsole('st-kline组件消息:区域刷选绘制完毕-draw', { color: 'green' })
|
|
103
264
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
// 全部绘制
|
|
268
|
+
[
|
|
269
|
+
undefined,
|
|
270
|
+
async () => {
|
|
271
|
+
await draw('kline')
|
|
272
|
+
await draw('line')
|
|
273
|
+
await draw('brush')
|
|
274
|
+
},
|
|
275
|
+
],
|
|
276
|
+
])
|
|
277
|
+
const callBack = callBackMap.get(type)
|
|
278
|
+
if (callBack instanceof Function) {
|
|
279
|
+
await callBack()
|
|
280
|
+
}
|
|
107
281
|
}
|
|
108
282
|
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
283
|
+
//----------------------------右键菜单功能相关----------------------------------
|
|
284
|
+
const cursorPenVisible = ref(false) // 画笔模式开关
|
|
285
|
+
|
|
286
|
+
const menuData = ref<MenuDataType>([])
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* @description: 点击菜单项
|
|
290
|
+
* @param {Object} item 菜单项的数据
|
|
291
|
+
*/
|
|
292
|
+
const menuClick = (item: any) => {
|
|
293
|
+
const { callBack } = item
|
|
294
|
+
callBack instanceof Function && callBack(echartsInstance, cursorPenVisible)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* @description: 菜单关闭的回调
|
|
299
|
+
* @todo: 进行菜单内容的初始化
|
|
300
|
+
*/
|
|
301
|
+
const closeContextMenuCallBack = () => {
|
|
302
|
+
menuData.value = props.defaultMenuData as MenuDataType
|
|
128
303
|
}
|
|
129
304
|
|
|
305
|
+
//----------------------------Echarts基座-------------------------------
|
|
306
|
+
const echartsRef = ref<HTMLElement>()
|
|
307
|
+
let echartsInstance: EChartsType // echarts实例
|
|
308
|
+
let chartDomObserver: any // 监视图表DOM变化
|
|
309
|
+
|
|
130
310
|
/**
|
|
131
|
-
* echarts
|
|
132
|
-
*
|
|
133
|
-
|
|
311
|
+
* @description: echarts数据高亮回调
|
|
312
|
+
* @param {any} data echarts数据
|
|
313
|
+
* @param {EChartsType} chart echarts实例
|
|
314
|
+
*/
|
|
134
315
|
const highlight = (data: any, chart: EChartsType) => {
|
|
135
316
|
if (data) {
|
|
136
317
|
// 图表内部移动
|
|
137
|
-
activeIndex.value =
|
|
138
|
-
typeof data?.batch[0]?.dataIndex === 'number' ? data?.batch[0]?.dataIndex : -1
|
|
318
|
+
activeIndex.value = typeof data?.batch[0]?.dataIndex === 'number' ? data?.batch[0]?.dataIndex : -1
|
|
139
319
|
} else {
|
|
140
320
|
// 移出图表
|
|
141
321
|
const chartOptions: EChartsOption = chart.getOption() as EChartsOption
|
|
@@ -144,28 +324,181 @@
|
|
|
144
324
|
}
|
|
145
325
|
}
|
|
146
326
|
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* @description: echarts数据缩放的相关参数
|
|
330
|
+
* @param {any} datazoomTimer 缩放回调函数的延时器
|
|
331
|
+
* @param {Number} datazoomTime 缩放回调函数的延时器的时间
|
|
332
|
+
* @param {Function} datazoom 数据缩放的回调函数
|
|
333
|
+
*/
|
|
334
|
+
let datazoomTimer: any = null
|
|
335
|
+
const datazoomTime: number = 300
|
|
336
|
+
const datazoom = () => {
|
|
337
|
+
clearTimeout(datazoomTimer)
|
|
338
|
+
datazoomTimer = setTimeout(() => {
|
|
339
|
+
draw('line')
|
|
340
|
+
clearTimeout(datazoomTimer)
|
|
341
|
+
datazoomTimer = null
|
|
342
|
+
}, datazoomTime)
|
|
343
|
+
}
|
|
344
|
+
|
|
147
345
|
/**
|
|
148
|
-
* echarts
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
346
|
+
* @description: echarts鼠标右击事件回调
|
|
347
|
+
*/
|
|
348
|
+
let echartsContextMenuTimer: any = null
|
|
349
|
+
const echartsContextMenu = (params: ECElementEvent) => {
|
|
350
|
+
echartsContextMenuTimer = setTimeout(() => {
|
|
351
|
+
// 判定是否点击到的元素为额外画线
|
|
352
|
+
if (params.componentType === 'graphic') {
|
|
353
|
+
const { oncontextmenu } = params.info?.event ?? {}
|
|
354
|
+
oncontextmenu instanceof Function && oncontextmenu(params, params.info, menuData)
|
|
355
|
+
}
|
|
356
|
+
clearTimeout(echartsContextMenuTimer)
|
|
357
|
+
echartsContextMenuTimer = null
|
|
358
|
+
})
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// 绑定事件
|
|
362
|
+
const addEventListener = () => {
|
|
363
|
+
echartsInstance.on('highlight', (data: any) => {
|
|
364
|
+
highlight(data, echartsInstance)
|
|
365
|
+
})
|
|
366
|
+
echartsInstance.on('globalout', () => {
|
|
367
|
+
highlight(null, echartsInstance)
|
|
368
|
+
})
|
|
369
|
+
echartsInstance.on('contextmenu', (params: ECElementEvent) => {
|
|
370
|
+
echartsContextMenu(params)
|
|
371
|
+
})
|
|
372
|
+
echartsInstance.on('datazoom', () => {
|
|
373
|
+
datazoom()
|
|
374
|
+
})
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// 解绑事件
|
|
378
|
+
const removeEventListener = () => {
|
|
379
|
+
echartsInstance.off('highlight')
|
|
380
|
+
echartsInstance.off('globalout')
|
|
381
|
+
echartsInstance.off('contextmenu')
|
|
382
|
+
echartsInstance.off('datazoom')
|
|
383
|
+
}
|
|
152
384
|
|
|
385
|
+
/**
|
|
386
|
+
* @description: K线组件初始化
|
|
387
|
+
*/
|
|
388
|
+
const init = async () => {
|
|
389
|
+
let Initializing: boolean | null = true // 正在初始化
|
|
390
|
+
// 1.初始化图表
|
|
391
|
+
echartsInstance = echarts.init(echartsRef.value) as EChartsType
|
|
392
|
+
// 2.绘制
|
|
393
|
+
await draw()
|
|
394
|
+
// 3.初始化右键菜单
|
|
395
|
+
menuData.value = props.defaultMenuData as MenuDataType
|
|
396
|
+
// 4.初始化数据激活索引
|
|
397
|
+
activeIndex.value =
|
|
398
|
+
((echartsInstance.getOption().dataZoom as DataZoomComponentOption[])[0].endValue as number) ?? -1
|
|
399
|
+
// 5.进行图表事件绑定
|
|
400
|
+
addEventListener()
|
|
401
|
+
// 6.进行DOM监控,图表重加载
|
|
402
|
+
chartDomObserver = new ResizeObserver(() => {
|
|
403
|
+
if (Initializing) {
|
|
404
|
+
Initializing = null
|
|
405
|
+
return
|
|
406
|
+
}
|
|
407
|
+
echartsInstance.resize()
|
|
408
|
+
draw('line')
|
|
409
|
+
})
|
|
410
|
+
chartDomObserver.observe(echartsRef.value)
|
|
153
411
|
}
|
|
154
412
|
|
|
155
413
|
onMounted(() => {
|
|
156
414
|
init()
|
|
157
415
|
})
|
|
416
|
+
|
|
417
|
+
onUnmounted(() => {
|
|
418
|
+
// 1.解绑
|
|
419
|
+
removeEventListener()
|
|
420
|
+
// 2.销毁实例
|
|
421
|
+
echartsInstance.dispose()
|
|
422
|
+
// 3.取消监听图表DOM
|
|
423
|
+
chartDomObserver.disconnect()
|
|
424
|
+
chartDomObserver = null
|
|
425
|
+
})
|
|
158
426
|
</script>
|
|
159
427
|
|
|
428
|
+
<template>
|
|
429
|
+
<!-- 神兔-K线组件 -->
|
|
430
|
+
<div class="st-kline">
|
|
431
|
+
<!-- Tips -->
|
|
432
|
+
<div class="st-kline-header">
|
|
433
|
+
<!-- 开, 高, 低, 收 -->
|
|
434
|
+
<Tips :data="kLineTips" />
|
|
435
|
+
<!-- 指标 -->
|
|
436
|
+
<Tips :data="indicatorTips" />
|
|
437
|
+
</div>
|
|
438
|
+
<!-- 图表 + 菜单 -->
|
|
439
|
+
<Contextmenu
|
|
440
|
+
class="st-kline-body"
|
|
441
|
+
@closeContextMenuCallBack="closeContextMenuCallBack"
|
|
442
|
+
>
|
|
443
|
+
<!-- 图表 -->
|
|
444
|
+
<div
|
|
445
|
+
ref="echartsRef"
|
|
446
|
+
:class="cursorPenVisible ? 'st-kline-chart cursorPen' : 'st-kline-chart'"
|
|
447
|
+
/>
|
|
448
|
+
<!-- 菜单 -->
|
|
449
|
+
<template #popover>
|
|
450
|
+
<el-menu class="menu">
|
|
451
|
+
<el-menu-item
|
|
452
|
+
v-for="item in menuData"
|
|
453
|
+
:key="item.label"
|
|
454
|
+
:index="item.label"
|
|
455
|
+
class="menuItem"
|
|
456
|
+
@click="menuClick(item)"
|
|
457
|
+
>
|
|
458
|
+
{{ item.label }}
|
|
459
|
+
</el-menu-item>
|
|
460
|
+
</el-menu>
|
|
461
|
+
</template>
|
|
462
|
+
</Contextmenu>
|
|
463
|
+
</div>
|
|
464
|
+
</template>
|
|
465
|
+
|
|
466
|
+
<style lang="scss">
|
|
467
|
+
// 需要写在外面,不然会被Vue唯一标识符顶掉导致样式不生效
|
|
468
|
+
.cursorPen canvas {
|
|
469
|
+
cursor: url(./images/pen.png) -30 30, auto !important;
|
|
470
|
+
}
|
|
471
|
+
</style>
|
|
160
472
|
<style lang="scss" scoped>
|
|
161
473
|
.st-kline {
|
|
162
474
|
width: 100%;
|
|
163
475
|
height: 100%;
|
|
164
476
|
background: #000;
|
|
165
|
-
|
|
477
|
+
overflow-x: hidden;
|
|
478
|
+
position: relative; // 配合提供给菜单定位
|
|
479
|
+
// K线头部区域: Tips
|
|
166
480
|
&-header {
|
|
481
|
+
height: 34px;
|
|
167
482
|
position: absolute;
|
|
168
|
-
|
|
483
|
+
left: 66px;
|
|
484
|
+
}
|
|
485
|
+
&-body {
|
|
486
|
+
width: 100%;
|
|
487
|
+
height: 100%;
|
|
488
|
+
}
|
|
489
|
+
&-chart {
|
|
490
|
+
width: 100%;
|
|
491
|
+
height: 100%;
|
|
492
|
+
}
|
|
493
|
+
.menu {
|
|
494
|
+
border-radius: 4px;
|
|
495
|
+
overflow: hidden;
|
|
496
|
+
background-color: white;
|
|
497
|
+
border-right: 0;
|
|
498
|
+
.menuItem {
|
|
499
|
+
font-size: 16px;
|
|
500
|
+
height: 32px;
|
|
501
|
+
}
|
|
169
502
|
}
|
|
170
503
|
}
|
|
171
504
|
</style>
|