引言
K 线图是金融领域中常用的图表类型,用于展示股票、外汇等资产的价格波动。ECharts 是一个功能强大的 JavaScript 图表库,能够帮助我们轻松实现复杂的 K 线图。本文将详细介绍如何在 Vue 3 中使用 ECharts 实现一个动态 K 线图,并逐步解析代码的实现细节。
资源
代码中的'candlestickData '已经上传至数据资源,请自行下载!!!
效果
1. 环境准备
在开始之前,确保你已经安装了以下依赖:
-
Vue 3
-
ECharts
可以通过以下命令安装 ECharts:
npm install echarts
2. 项目结构
我们将创建一个 Vue 组件来实现 K 线图。以下是项目的文件结构:
src/
├── components/
│ └── BackButton.vue
├── utils/
│ └── candlestickData.ts
├── views/
│ └── KLineChart.vue
3. 实现步骤
3.1 创建 Vue 组件
在 KLineChart.vue
中,我们定义了一个 Vue 组件,用于渲染 K 线图。
<template>
<div class="w-full justify-start flex h-[180px] items-center pl-10">
<BackButton @click="goBack"/>
</div>
<div class="font-bold text-[24px]">在Vue3中使用Echarts实现K线图</div>
<div class="chart-container mt-4">
<div ref="chartRef" class="stock-chart"></div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
import {candlestickData} from '@/utils/candlestickData'
import BackButton from "@/views/components/BackButton.vue";
const chartRef = ref<HTMLElement | null>(null)
let chart: echarts.ECharts | null = null
import router from "@/router";
const goBack = () => {
setTimeout(() => {
router.push('/Echarts')
}, 1000)
}
// Raw data array
function splitData(candlestickData: any[]) {
const categoryData = []
const values = []
const macds = []
const difs = []
const deas = []
for (let i = 0; i < candlestickData.length; i++) {
categoryData.push(candlestickData[i].splice(0, 1)[0])
values.push(candlestickData[i])
macds.push(candlestickData[i][6])
difs.push(candlestickData[i][7])
deas.push(candlestickData[i][8])
}
return {
categoryData,
values,
macds,
difs,
deas
}
}
const data0 = splitData(candlestickData)
function calculateMA(dayCount: number) {
const result = []
for (let i = 0, len = data0.values.length; i < len; i++) {
if (i < dayCount) {
result.push('-')
continue
}
let sum = 0
for (let j = 0; j < dayCount; j++) {
sum += data0.values[i - j][1]
}
result.push(sum / dayCount)
}
return result
}
const initChart = () => {
if (!chartRef.value) return
chart = echarts.init(chartRef.value)
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
}
},
grid: [{
left: '3%',
top: '0',
height: '75%'
}, {
left: '3%',
right: '10%',
top: '80%',
height: '10%'
}],
xAxis: [{
type: 'category',
data: data0.categoryData,
scale: true,
boundaryGap: false,
axisLine: {
onZero: false,
lineStyle: {
color: 'red'
}
},
splitLine: {
show: false
},
splitNumber: 20
}, {
type: 'category',
gridIndex: 1,
data: data0.categoryData,
axisLabel: { show: false }
}],
yAxis: [{
scale: true,
splitArea: {
show: true
},
axisLine: {
lineStyle: {
color: 'red'
}
},
position: 'right'
}, {
gridIndex: 1,
splitNumber: 3,
axisLine: { onZero: false },
axisTick: { show: false },
splitLine: { show: false },
axisLabel: { show: true },
axisLine: {
lineStyle: {
color: 'red'
}
},
position: 'right'
}],
dataZoom: [{
type: 'inside',
start: 100,
end: 80
}, {
show: true,
type: 'slider',
y: '90%',
start: 50,
end: 100
}, {
show: false,
xAxisIndex: [0, 1],
type: 'slider',
start: 20,
end: 100
}],
series: [{
name: '555',
type: 'candlestick',
data: data0.values,
markPoint: {
data: [{
name: 'XX标点'
}]
},
markLine: {
silent: true,
data: [{
yAxis: 2222
}]
}
}, {
name: 'MA5',
type: 'line',
data: calculateMA(5),
smooth: true,
lineStyle: {
normal: {
opacity: 0.5
}
}
}, {
name: 'MA10',
type: 'line',
data: calculateMA(10),
smooth: true,
lineStyle: {
normal: {
opacity: 0.5
}
}
}, {
name: 'MA20',
type: 'line',
data: calculateMA(20),
smooth: true,
lineStyle: {
normal: {
opacity: 0.5
}
}
}, {
name: 'MA30',
type: 'line',
data: calculateMA(30),
smooth: true,
lineStyle: {
normal: {
opacity: 0.5
}
}
}, {
name: 'MACD',
type: 'bar',
xAxisIndex: 1,
yAxisIndex: 1,
data: data0.macds,
itemStyle: {
normal: {
color: function(params: any) {
return params.data >= 0 ? '#ef232a' : '#14b143'
}
}
}
}, {
name: 'DIF',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
data: data0.difs
}, {
name: 'DEA',
type: 'line',
xAxisIndex: 1,
yAxisIndex: 1,
data: data0.deas
}]
}
chart.setOption(option)
}
const handleResize = () => {
chart?.resize()
}
onMounted(() => {
initChart()
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
chart?.dispose()
window.removeEventListener('resize', handleResize)
})
</script>
<style scoped>
.chart-container {
width: 80%;
height: 70%;
min-height: 600px;
margin-left: 10%;
}
.stock-chart {
width: 100%;
height: 100%;
}
@media screen and (max-width: 768px) {
.chart-container {
min-height: 400px;
}
}
@media screen and (max-width: 480px) {
.chart-container {
min-height: 300px;
}
}
</style>
3.2 代码解析
-
模板部分:
-
使用
ref
绑定了一个div
元素作为 ECharts 的容器。 -
页面顶部有一个返回按钮,点击后会延迟 1 秒跳转到
/Echarts
路由。
-
-
脚本部分:
-
引入了 Vue 3 的
ref
、onMounted
和onUnmounted
生命周期钩子。 -
使用
echarts
初始化图表,并在组件挂载时调用initChart
函数。 -
定义了一个
splitData
函数,用于将原始数据拆分为不同的数组。 -
calculateMA
函数用于计算移动平均线。 -
initChart
函数将数据转换为 ECharts 所需的格式,并设置图表的配置项。 -
监听窗口的
resize
事件,以便在窗口大小变化时调整图表大小。 -
在组件卸载时销毁图表实例并移除事件监听器。
-
-
样式部分:
-
定义了图表容器的样式,包括宽度、高度和背景颜色。
-
使用媒体查询对移动端进行了适配。
-
4. 优化建议
-
数据动态化:
-
通过 API 或父组件传递数据,使图表更具通用性。
-
-
图表配置优化:
-
将图表的配置项提取为一个单独的函数或文件,便于复用和维护。
-
-
响应式处理:
-
进一步优化图表内容(如字体大小、符号大小等)以适应不同屏幕尺寸。
-
-
代码复用:
-
将图表初始化逻辑封装为一个自定义 Hook 或组件。
-
5. 总结
通过本文的介绍,你已经学会了如何在 Vue 3 中使用 ECharts 实现一个动态 K 线图。希望这篇文章对你有所帮助!如果你有任何问题或建议,欢迎在评论区留言。
参考链接
版权声明:本文代码版权归吉檀迦俐所有,可供学习和借鉴或商用。转载请注明出处。
希望这篇文章能帮助你在 CSDN 上获得更多的阅读和点赞!如果有其他需求,欢迎随时联系我!
标签:教程,Vue,const,true,type,candlestickData,data,ECharts From: https://blog.csdn.net/Miller777_/article/details/145053690