You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
4.0 KiB
Vue

3 weeks ago
<template>
<div class="line-chart-page">
<div ref="chartRef" class="line-chart"></div>
<!-- 控制按钮 -->
<div class="controls">
<el-button @click="refreshData"></el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
const chartRef = ref<HTMLElement>();
let chartInstance: echarts.ECharts | null = null;
let isSmooth = false;
// 原始数据
const baseData = [160, 230, 224, 218, 135, 147, 260];
const categories = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// 生成随机数据
const generateRandomData = () => {
return baseData.map((val) => Math.floor(val * (0.8 + Math.random() * 0.4)));
};
// 初始化图表
const initChart = () => {
if (!chartRef.value) return;
chartInstance = echarts.init(chartRef.value);
const option: EChartsOption = {
title: {
text: '周数据统计',
left: 'center',
top: 10
},
tooltip: {
trigger: 'axis',
formatter: '{b}: {c}'
},
xAxis: {
type: 'category',
data: categories,
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#ddd'
}
},
axisLabel: {
color: '#666'
}
},
yAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#ddd'
}
},
axisLabel: {
color: '#666'
},
splitLine: {
lineStyle: {
color: '#f0f0f0'
}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '60px',
containLabel: true
},
series: [
{
name: '数据',
type: 'line',
data: baseData,
smooth: true, //平滑曲线
symbol: 'circle',
symbolSize: 8,
itemStyle: {
color: '#409EFF',
borderColor: '#fff',
borderWidth: 2
},
lineStyle: {
width: 3,
color: '#409EFF'
},
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(64, 158, 255, 0.3)'
},
{
offset: 1,
color: 'rgba(64, 158, 255, 0.05)'
}
])
},
emphasis: {
focus: 'series'
}
}
]
};
chartInstance.setOption(option);
// 初始调用一次 resize确保图表正确获取容器尺寸
setTimeout(() => {
chartInstance?.resize();
}, 10);
};
// 刷新数据
const refreshData = () => {
if (!chartInstance) return;
const newData = generateRandomData();
chartInstance.setOption({
series: [
{
data: newData,
type: 'line',
smooth: true
}
]
});
};
// 监听窗口大小变化 - 使用 ResizeObserver 更精确地监听容器变化
let resizeObserver: ResizeObserver | null = null;
const handleResize = () => {
chartInstance?.resize();
};
onMounted(() => {
initChart();
// 方案 1: 监听 window resize适用于视口大小变化
window.addEventListener('resize', handleResize);
// 方案 2: 使用 ResizeObserver 监听容器本身的大小变化(更精确)
if (chartRef.value && typeof ResizeObserver !== 'undefined') {
resizeObserver = new ResizeObserver(() => {
handleResize();
});
resizeObserver.observe(chartRef.value.parentElement!);
}
});
onUnmounted(() => {
resizeObserver?.disconnect();
window.removeEventListener('resize', handleResize);
chartInstance?.dispose();
});
</script>
<style scoped lang="scss">
.line-chart-page {
width: 100%;
height: 100%;
h2 {
text-align: center;
color: #333;
margin-bottom: 20px;
}
.line-chart {
width: 100%;
height: 100%;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.controls {
margin-top: 20px;
text-align: center;
.el-button {
margin-right: 10px;
}
}
}
</style>