黄石人流数据大屏
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

157 lines
4.3 KiB

<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>