<script setup>
import {
ref,
onMounted,
onBeforeUnmount,
watch,
markRaw
} from 'vue';
import {
debounce
} from "@/utils"; //节流函数
import * as echarts from "echarts";
const emit = defineEmits(['chartClick', 'chartMouseover', 'chartMouseout'])
const props = defineProps({
option: {
type: Object,
defined: () => {}
},
width: {
type: String,
defined: '100%'
}, // 必须指定容器的宽高,否则无法显示。(容器内图表会自动获取父元素宽高)
height: {
type: String,
defined: '100%'
},
theme: {
type: [Object, String],
defined: ''
},
loading: {
type: Boolean,
defined: false
}, // 受控
onMouseover: {
type: Function,
defined: () => {}
},
onMouseout: {
type: Function,
defined: () => {}
},
onClick: {
type: Function,
defined: () => {}
}
})
const chartRef = ref(null);
const chartInstance = ref();
const draw = () => {
if (chartInstance.value) {
// console.log('修改了', props.option);
chartInstance.value.setOption(props.option, {
notMerge: true
});
}
};
const init = () => {
if (!chartRef.value) return;
// 校验 Dom 节点上是否已经挂载了 ECharts 实例,只有未挂载时才初始化
chartInstance.value = echarts.getInstanceByDom(chartRef.value);
if (!chartInstance.value) {
chartInstance.value = markRaw(
echarts.init(chartRef.value, props.theme, {
renderer: 'canvas',
})
);
// 绑定鼠标事件:
if (props.onMouseover) {
chartInstance.value.on('mouseover', (event) => {
props.onMouseover(event, chartInstance.value, props.option);
});
}
if (props.onMouseout) {
chartInstance.value.on('mouseout', (event) => {
props.onMouseout(event, chartInstance.value, props.option);
});
}
if (props.onClick) {
chartInstance.value.on('click', (event) => {
props.onClick(event, chartInstance.value, props.option);
});
}
chartInstance.value.on('mouseover', (event) => {
emit('chartMouseover', event, chartInstance.value, props.option)
})
chartInstance.value.on('mouseout', (event) => {
emit('chartMouseout', event, chartInstance.value, props.option)
})
chartInstance.value.on('click', (event) => {
emit('chartClick', event, chartInstance.value, props.option)
})
draw();
}
};
// 窗口自适应并开启过渡动画
const resize = () => {
if (chartInstance.value) {
chartInstance.value.resize({
animation: {
duration: 300
}
});
}
};
// 自适应防抖优化
const debouncedResize = debounce(resize, 500, {
maxWait: 800
});
// 对父组件暴露获取 ECharts 实例的方法,可直接通过实例调用原生函数
defineExpose({
getInstance: () => chartInstance.value,
resize,
draw,
});
watch(props, () => {
draw();
});
// 展示 loading 动画
watch(
() => props.loading,
loading => {
loading
?
chartInstance.value.showLoading() :
chartInstance.value.hideLoading();
}
);
onMounted(() => {
init();
window.addEventListener('resize', debouncedResize);
});
onBeforeUnmount(() => {
// 容器被销毁之后,销毁实例,避免内存泄漏
chartInstance.value?.dispose();
window.removeEventListener('resize', debouncedResize);
});
</script>
<template>
<div id="echart" ref="chartRef" :style="{ width: props.width, height: props.height }" />
</template>
注意:如果你要使用渐变颜色还得自己引入echarts
<template>
<div class="main-box" style="width: 100%;height: 100%;">
<!-- :onClick="clickChart" :onMouseout="onMouseout" :onMouseover="onMouseover"-->
<!-- @chartClick="clickChart" @chartMouseover="chartMouseover" @chartMouseout="chartMouseout" -->
<!-- 上面有两种点击事件和鼠标事件 都能使用 -->
<BaseChart @chartClick="clickChart" width="100%" height="100%" :option="chartOptions">
</BaseChart>
</div>
</template>
<script setup>
import BaseChart from '@/components/BaseChart/index.vue'
import {
requestGet
} from '@/api/index.js'
import {
onMounted,
ref
} from 'vue'
import * as echarts from "echarts";
onMounted(() => {
initChart();
})
const chartOptions = ref({})
const clickChart = (e, chart, option) => {
console.log('图标数据', e);
console.log('图标dom', chart);
console.log('图标option', option);
}
const initChart = async () => {
chartOptions.value = {
grid: {
top: '15%',
left: '1%',
right: '7%',
bottom: '0%',
containLabel: true,
},
legend: {
top: '0%',
right: '10%',
itemGap: 50,
data: ['产量', '产值'],
textStyle: {
color: '#f9f9f9',
borderColor: '#fff'
},
},
xAxis: [{
name: '年',
nameGap: 5,
type: 'category',
axisLine: { //坐标轴轴线相关设置。数学上的x轴
show: true,
lineStyle: {
color: '#999'
},
},
axisLabel: { //坐标轴刻度标签的相关设置
color: '#999',
},
axisTick: {
show: false,
},
data: ['2017', '2018', '2019', '2020', '2021', '2022', '2023', ],
}],
yAxis: [{
type: 'value',
min: 0,
// max: 140,
splitNumber: 7,
splitLine: {
show: true,
lineStyle: {
color: '#0a3256'
}
},
axisLine: {
show: false,
},
axisLabel: {
// margin: 20,
color: '#999',
},
axisTick: {
show: false,
},
}],
tooltip: {
trigger: 'axis',
},
series: [{
name: '产量',
type: 'line',
// smooth: true, //是否平滑曲线显示
// symbol:'circle', // 默认是空心圆(中间是白色的),改成实心圆
showAllSymbol: true,
symbol: 'emptyCircle',
// symbolSize: 6,
lineStyle: {
color: "#28ffb3", // 线条颜色
borderColor: '#f0f'
},
label: {
show: false,
position: 'top',
color: '#fff',
},
itemStyle: {
color: "#28ffb3",
lineStyle: {
width: 1,
type: 'solid' //'dotted'虚线 'solid'实线
}
},
areaStyle: { //区域填充样式
//线性渐变,前4个参数分别是x0,y0,x2,y2(范围0~1);相当于图形包围盒中的百分比。如果最后一个参数是‘true’,则该四个值是绝对像素位置。
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0,154,120,1)'
},
{
offset: 1,
color: 'rgba(0,0,0, 0)'
}
], false),
shadowColor: 'rgba(53,142,215, 0.9)', //阴影颜色
shadowBlur: 20 //shadowBlur设图形阴影的模糊大小。配合shadowColor,shadowOffsetX/Y, 设置图形的阴影效果。
},
data: [393, 438, 485, 631, 689, 824, 987]
}, {
name: '产值',
type: 'bar',
barWidth: 15,
// tooltip: {
// show: false
// },
label: {
show: false,
position: 'top',
color: '#fff',
},
itemStyle: {
color: "#1cfffb",
lineStyle: {
width: 1,
type: 'solid' //'dotted'虚线 'solid'实线
},
// barBorderRadius: [30, 30, 0, 0],
},
}]
};
}
</script>
<style scoped lang="scss">
.main-box {
width: 100%;
height: 100%;
}
.main-content {
width: 100%;
height: 100%;
}
</style>```