|
|
<template> <div ref="chart" class="chart-box" /></template>
<script>import { debounce } from '@/utils/index'
export default { name: 'YearInFlowChart', props: { yearData: { type: Array, default: () => [] } }, data() { return { chart: null, ro: null } }, computed: { xAxis() { return this.yearData.map((i) => i.month + '月') }, series() { return this.yearData.map((i) => i.count || 0) } }, watch: { yearData() { this.setOption() } }, mounted() { this.$nextTick(() => this.initChart()) }, beforeDestroy() { this.stopTipLoop() if (this.ro) { this.ro.disconnect() this.ro = null } if (this.chart) { this.chart.dispose() this.chart = null } }, methods: { initChart() { this.chart = this.$echarts.init(this.$refs.chart) this.setOption() // 用 ResizeObserver 监听容器自身尺寸变化,比 window.resize 更可靠
const doResize = debounce(() => { if (this.chart) this.chart.resize() }, 100) this.ro = new ResizeObserver(() => doResize()) this.ro.observe(this.$refs.chart) }, setOption() { if (!this.chart) return const idx = Math.max(0, this.series.length - 1) const lastVal = this.series[idx] this.chart.setOption({ tooltip: { trigger: 'axis', backgroundColor: 'rgba(11, 26, 48, 0.92)', borderColor: '#18E3A7', textStyle: { color: '#e2e8f0', fontSize: 14 }, axisPointer: { type: 'line', lineStyle: { color: '#18E3A7' }} }, grid: { left: 40, right: 20, top: 50, bottom: 30, containLabel: false }, xAxis: { type: 'category', data: this.xAxis, boundaryGap: false, axisLine: { lineStyle: { color: 'rgba(24,227,167,0.4)' }}, axisTick: { show: false }, axisLabel: { color: 'rgba(255,255,255,0.7)', fontSize: 12, interval: 'auto' }, splitLine: { show: false } }, yAxis: { type: 'value', min: 0, max: (v) => v.max === 0 ? 100 : Math.ceil(v.max * 1.25), axisLine: { show: false }, axisTick: { show: false }, axisLabel: { color: 'rgba(255,255,255,0.6)', fontSize: 12 }, splitLine: { lineStyle: { color: 'rgba(24,227,167,0.12)', type: 'dashed' }} }, series: [{ name: '进馆人次', type: 'line', smooth: true, symbol: 'none', showSymbol: false, data: this.series, lineStyle: { color: '#18E3A7', width: 3, shadowColor: '#18E3A7', shadowBlur: 12 }, itemStyle: { color: '#18E3A7' }, areaStyle: { color: new this.$echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: 'rgba(24,227,167,0.45)' }, { offset: 1, color: 'rgba(24,227,167,0.02)' } ]) }, markPoint: { symbol: 'circle', symbolSize: 12, label: { position: 'top', distance: 12, formatter: () => String(lastVal), fontSize: 26, fontWeight: 800, color: '#fff', textShadowColor: 'rgba(24,227,167,0.8)', textShadowBlur: 10 }, itemStyle: { color: '#18E3A7', shadowColor: 'rgba(24,227,167,1)', shadowBlur: 12 }, data: [{ coord: [idx, lastVal] }] } }] }) this.startTipLoop() }, // 动态轮播 tooltip,适配大屏无人交互场景
startTipLoop() { this.stopTipLoop() if (!this.series.length) return this.tipIndex = -1 this.tipTimer = setInterval(() => { if (!this.chart || !this.series.length) return this.tipIndex = (this.tipIndex + 1) % this.series.length this.chart.dispatchAction({ type: 'showTip', seriesIndex: 0, dataIndex: this.tipIndex }) }, 2500) }, stopTipLoop() { if (this.tipTimer) { clearInterval(this.tipTimer) this.tipTimer = null } } }}</script>
<style lang="scss">@import "~@/assets/styles/index.scss";</style>
|