Vue3+ECharts 切换markArea显示隐藏

352 阅读1分钟

效果如图: 动画.gif

思路

  1. 随机生成数据,渲染3条带markArea的折线,legend设为全选
  2. 标签显隐通过markArea.label.show控制,标域显隐通过markArea.itemStyle.opacity控制
  3. 点击图例隐藏Line2,再点击隐藏标域按钮,发现markArea隐藏的同时Line2显示,因为option不是响应式的,legend.selected会一直保持图表实例化时的值,需要通过监听legendselectchanged事件手动更新

代码

Vue函数、生命周期钩子等已通过unplugin-auto-import自动导入

<template>
  <div class="container">
    <button class="btn" @click="toggleMarkarea(markareaVisible)">
      {{ markareaVisible ? '隐藏' : '显示' }}标域
    </button>
    <div ref="chartRef" style="height: 100%"></div>
  </div>
</template>

<script setup>
import * as echarts from 'echarts'

const chartRef = shallowRef()
let chart
const option = {
  grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
  legend: {
    selected: {}
  },
  xAxis: {
    type: 'category',
    data: []
  },
  yAxis: { type: 'value' },
  series: [],
  animation: false
}

const markareaVisible = ref(true)
const toggleMarkarea = (visible) => {
  if (!chart) return
  option.series.forEach((item) => {
    item.markArea.itemStyle.opacity = visible ? 0 : 1
    item.markArea.label.show = !visible
  })
  chart.clear()
  chart.setOption(option)
  markareaVisible.value = !visible
}

function renderChart() {
  if (chart) chart.clear()
  option.xAxis.data.length = 0
  option.series.length = 0
  /* 重置结束 */
  option.xAxis.data = Array.from({ length: 90 }, (_, i) => `Day${i + 1}`)
  for (let i = 0; i < 3; i++) {
    const lineName = `Line${i + 1}`
    option.series.push({
      type: 'line',
      name: lineName,
      data: Array.from({ length: 90 }, () => Math.random() * 200),
      markArea: {
        data: [[{ name: `${lineName} Markarea`, xAxis: 30 * i }, { xAxis: 30 * (i + 1) }]],
        itemStyle: { opacity: 1 },
        label: { show: true }
      }
    })
    option.legend.selected[lineName] = true
  }
  nextTick(() => {
    if (!chart) chart = echarts.init(chartRef.value)
    chart.setOption(option)
    chart.on('legendselectchanged', (params) => {
      option.legend.selected = params.selected
    })
  })
}

onBeforeMount(() => {
  renderChart()
})

onBeforeUnmount(() => {
  if (chart) chart.dispose()
})
</script>

<style lang="scss" scoped>
.container {
  position: relative;
  height: 400px;
  border: 1px solid #ccc;
}

.btn {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 1;
}
</style>