基于vue3 和 echarts (echarts 5.4.3)
// echarts.vue
<template>
<!-- 容器-->
<div class="echartsContainer"></div>
</template>
<script setup lang="ts">
import {onMounted,ref,watch} from 'vue';
import {nextTick} from 'process';
import moment from 'moment';
const props = defineProps({
// 轴数据
lineEchartsData:{
type: Array,
default: ()=> [],
},
echartsYdata:{
type: Array,
default: ()=> [],
},
echartsType:{
type: String,
default: ''
},
yMax:{
type: [Number, String],
default: 1,
},
xStartTime:{
type: Number,
default: ()=>{
//当前时间减一个月加一天 转时间戳
return moment.subtract(1,'year').add(1,'day').valueOf();
}
},
xEndTime:{
type: Number,
default: ()=>{
//当前时间 转时间戳
return moment().valueOf();
}
}
});
const emit = defineEmits = (['getEchartsPointHand']);
const cointerDom = ref(null);
let startMinTime = null;
let endMaxTime = null;
// 配置项数据
let option = ref({
// 标题
title:{
text: "",
// 副标题
subTitle: ''
},
// 图例
legend:{
show: true,
top: '15px',
left: '20%',
// 图例形状
icon: "rect",
// 图例之间的间距
itemGap: 30,
// 图例图形宽度 默认25
itemWidth: 15,
// 图例图形高度 默认25
itemHeight: 5,
},
// 鼠标悬停显示弹框
tooltip:{
borderColor: '#FF620D',
color: "white",
borderWidth: 1,
padding: [2, 8],
trigger: 'axis',
// 是否显示文本
showContent: false,
// 是否将 tooltip 框限制在图表的区域内
confine: true,
// 坐标轴指示器配置项
axisPointer:{
// 指示器类型 cross 十字准星指示器
type: 'cross',
// 自动吸附到数据点上
snap: true,
lineStyle:{
color: '#FF620D',
},
crossStyle:{
color: '#FF620D'
},
// 坐标轴指示器的文本标签
label: {
show: true,
borderColor: '#FF620D',
color: "white",
backGroundColor: '#FF620D',
},
backGroundColor: '#FF620D',
},
// 图表位置
grid:{
show: true,
left: '3%',
right: '8%',
bottom: '3%',
// 网格边框颜色
borderColor: '#FFF7F3',
// grid 区域是否包含坐标轴的刻度标签
containLabel: true,
// 网格边框线宽
borderWidth: 0
},
// X轴
xAxis:{
min: startMinTime,
max: endMaxTime,
offset: 2,
// 类型 time 时间
type: 'time',
// 坐标轴两边是否留白
boundaryGap: true,
// 坐标轴刻度标签相关设置
axisLabel:{
// 是否展示X轴
show: true,
// 显示最小刻度标签
showMinLabel: true,
// 显示最大刻度标签
showMaxLabel: true,
textStyle:{
color: "",
fontStyle: 'normal',
fontSize: 24,
fontFamily: 'D-DIN-PRO-Medium, D-DIN-PRO'
},
// 格式化
formatter: function(value){
// 开始日期时间戳
let startTime = startMinTime;
// 结束日期时间戳
let endTime = endMaxTime;
if(value >startTime && value < endTime){
return "";
}else{
return echarts.format.formatTime('yyyy-MM', value);
}
}
},
axisPointer:{
snap: true,
label:{
formatter: function(params){
return echarts.format.formatTime('yyyy-MM-dd',params.value);
}
}
},
// 坐标轴线相关设置
axisLine:{
// 改变x轴位置
onZero: false,
lineStyle:{
color:'#c4c5c7'
}
}
},
// y轴
yAxis:{
lineWidth: 2,
// 坐标轴刻度标签相关设置
axisLabel:{
formatter: function(value){
return props.echartsType==='组合业绩'? value.toFixed(2)+'%':value.toFixed(4);
},
textStyle:{
color: "#C4C5C7",
fontStyle: 'normal',
fontSize: 24,
fontFamily: 'D-DIN-PRO-Medium, D-DIN-PRO'
},
},
axisPointer:{
snap: true,
label:{
formatter: function(params){
return props.echartsType==='组合业绩'? value.toFixed(2)+'%':value.toFixed(4);
}
}
},
// 网格线
splitLine:{
// y轴分隔线是否展示
show: true,
// 分隔线样式
lineStyle:{
type: 'dashed',
}
}
},
// 系列数据配置项(一个对象一条折线)
series:[
{
// 数据格式是二维数组,包含x轴时间戳格式值和对应的Y轴的值
// 例[[时间戳,y值],[时间戳,y值],[时间戳,y值]]
data: [],
name: '业绩增长率',
type: 'line',
// 实心圆点 默认空心
symbol: 'circle',
// 圆点大小
symbolSize: 8,
// 是否展示数据点,如为false,只有tooltip时候显示
showSymbol: false,
lineStyle: {
color: '#FF620D',
},
// 数据点颜色
itemStyle:{
color: '#FF620D',
},
// 折线下方区域渐变色图块
areaStyle:{
color:{
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops:[
{ offset: 1, color: 'rgba(255,247,243,0.00)'},
{ offset: 0, color: 'rgba(255,247,243,0.21)'},
]
}
}
},
{
data: [],
name: '业绩基准',
type: 'line',
// 实心圆点 默认空心
symbol: 'circle',
// 圆点大小
symbolSize: 8,
// 是否展示数据点,如为false,只有tooltip时候显示
showSymbol: false,
lineStyle: {
color: '#65A9D2',
},
// 数据点颜色
itemStyle:{
color: '#65A9D2',
},
},
]
}
});
// 监听
watch(
()=>props.xStartTime,
(val)=>{
if(val){
startMinTime = val;
}else{
startMinTime = moment().subtract(1,'year').add(1,'day').valueOf();
}
},{ immediate: true });
watch(
()=>props.xEndTime,
(val)=>{
if(val){
endMaxTime = val;
}else{
endMaxTime = moment().startOf('day').valueOf();
}
},{ immediate: true });
watch(
()=>option.value,
(val)=>{
nextTick(()=>{
const echartsDom = echarts.init(document.querySelector('.echartsContainer'));
echartsDom .setOption(val);
})
},{deep:true});
watch(
()=>props.lineEchartsData,
(data)=>{
nextTick(()=>{
if(props.echartsType === '单位净值'){
option.value.series[0].data = data;
option.value.series[0].name = '';
option.value.series[1].name = '';
option.value.series[1].data = [];
option.value.xAxis.min = props.xStartTime;
option.value.xAxis.max = props.xEndTime;
option.value.yAxis.min = parseFloat(props.yMax);
option.value.yAxis.max = 0;
}else if(props.echartsType === '组合业绩'){
option.value.series[0].data = data[0];
option.value.series[0].name= '组合业绩';
option.value.series[1].data = data[1];
option.value.series[1].name = [基准业绩];
option.value.xAxis.min = props.xStartTime;
option.value.xAxis.max = props.xEndTime;
option.value.yAxis.min = -parseFloat(props.yMax);
option.value.yAxis.max = parseFloat(props.yMax);
}
})
},{
immediate: true,
deep:true
});
onMounted(()=>{
nextTick(()=>{
const echartsDom = echarts.init(document.querySelector('.echartsContainer'));
echartsDom.setOption(option.value);
// 对数据点绑定事件
echartsDom.on('mousemove',(params)=>{
let emitData = [];
if(params.seriesName === '组合业绩'){
emitData = [params.data,props.echartsType];
// 自定义事件传值给父组件
emit('getEchartsPointHand',emitData )
}
if(!params.seriesName && params.seriesName === '单位净值'){
emitData = [params.data,props.echartsType];
// 自定义事件传值给父组件
emit('getEchartsPointHand',emitData )
}
})
// 监视浏览器窗口大小变动,调用API进行重置折线图
window.addEventListener('resize',()=>{
echartsDom.resize();
})
})
})
</script>
<style lang="postcss" scoped>
/* css是基于tailwindcss开发;
容器必须有宽高,可以考虑做动态的,我的项目是应用于小程序,配置了适配,所以没做*/
.echartsContainer{
height:360px;
width:638px;
</style>
效果图