用水球图显示餐厅的人流量

829 阅读2分钟

用水球图显示餐厅的人流量

一、业务要求

用水球图显示餐厅的人流量,
当高于高基准线(0.6)时,显示红色边框和红色背景;
当低于低基准线(0.4)时,显示绿色背景;
当基于之间时,显示黄色背景。

二、实现效果

image.png

三、代码实现

1、下载依赖

"echarts": "^5.5.0",
"echarts-liquidfill": "^3.1.0",

2、封装组件

<template>
  <div ref="chartRef" :style="styleChart"></div>
</template>

<script>
import 'echarts-liquidfill'
import * as echarts from 'echarts'
export default {
  name: 'ChartLiquidFill',
  props: {
    styleChart: {
      type: Object,
      default: () => {
        return {
          width: '120px',
          height: '120px'
        }
      }
    },
    isShowTitle: {
      type: Boolean,
      default: true
    },
    title: {
      type: String,
      default: '拥挤度'
    },
    borderColor: {
      type: String,
      default: 'rgba(255, 255, 255, 1)'
    },
    backgroundColor: {
      type: String,
      default: 'rgba(255, 255, 255, 1)'
    },
    fillColor: {
      type: Array,
      default: () => {
        return []
      }
    },
    chartData: {
      type: [Number, String],
      default: 0
    }
  },
  data() {
    return {
      chartInst: null,
      option: {}
    }
  },
  watch: {
    chartData: {
      handler(newV, oldV) {
        this.initChart()
      },
      deep: true
    }
  },
  mounted() {
    this.initChart()
  },
  methods: {
    /**
     * 初始化
     */
    initChart() {
      this.chartInst = echarts.init(this.$refs.chartRef)
      this.option = {
        title: {
          show: this.isShowTitle,
          text: this.title,
          x: '46%',
          y: '60%',
          z: 10,
          textAlign: 'center',
          textStyle: {
            color: 'rgba(0, 0, 0, 0.4)',
            fontSize: 12,
            fontWeight: 400
          }
        },
        series: [
          {
            name: this.title,
            type: 'liquidFill',
            radius: '92%',
            center: ['50%', '50%'],
            data: [this.chartData],
            label: {
              color: '#000',
              fontSize: 26,
              fontWeight: 600,
              position: ['50%', '46%']
            },
            color: [
              {
                type: 'linear',
                x: 0,
                y: 1,
                x2: 0,
                y2: 0,
                colorStops: [
                  {
                    offset: 0,
                    color: this.fillColor[0] // 0% 处的颜色
                  },
                  {
                    offset: 1,
                    color: this.fillColor[1] // 100% 处的颜色
                  }
                ],
                global: false // 缺省为 false
              }
            ],
            backgroundStyle: {
              color: this.backgroundColor
            },
            itemStyle: {
              shadowBlur: 0
            },
            outline: {
              show: true,
              borderDistance: 0,
              itemStyle: {
                borderWidth: 10,
                borderColor: this.backgroundColor,
                shadowBlur: 0
              }
            }
          }
        ]
      }
      this.setChartOption()
    },
    /**
     * 设置图表数据
     */
    setChartOption() {
      this.chartInst.setOption(this.option, true)
    }
  },
  beforeDestroy() {
    echarts.init(this.$refs.chartRef).dispose()
  }
}
</script>

3、使用组件

<!--餐厅人流量-->
<template>
  <home-card
    :isMore="false"
    :title="title"
    :content-height="250"
  >
    <div v-loading="initLoading" class="restaurant">
      <template v-if="chartList.length">
        <div v-for="(item, index) in chartList" :key="index" class="restaurant-box">
          <div class="restaurant-inner mb-16" :class="item.boxClass">
            <chart-liquid-fill
              :chart-data="item.value"
              :fill-color="item.fillColor"
              :background-color="item.backgroundColor"
            />
          </div>
          <div class="flex-center h-20px">{{ item.name }}</div>
        </div>
      </template>
      <el-empty v-else :image-size="100" description="暂无内容"></el-empty>
    </div>
  </home-card>
</template>

<script>
import HomeCard from '../common/HomeCard'
import ChartLiquidFill from '../common/ChartLiquidFill'
export default {
  name: 'Restaurant',
  components: { HomeCard, ChartLiquidFill },
  props: {
    title: String
  },
  data() {
    return {
      initLoading: false,
      highValue: 0.6, // 高基准值
      lowValue: 0.4, // 低基准值
      colorList: {
        medium: ['rgba(223, 162, 10, 0)', 'rgba(223, 162, 10, 0.8)'],
        high: ['rgba(255, 104, 104, 0.10)', 'rgba(255, 104, 104, 1)'],
        low: ['rgba(84, 205, 86, 0.1)', 'rgba(84, 205, 86, 0.6)']
      },
      chartList: []
    }
  },
  created() {
    this.initData()
  },
  methods: {
    initData() {
      this.chartList = [
        { name: '6层餐厅', value: '0.52' },
        { name: '5层餐厅', value: '0.72' },
        { name: 'B1层餐厅', value: '0.32' }
      ]
      this.chartList.forEach(item => {
        let num = Number(item.value)
        item.fillColor = num >= this.highValue
          ? this.colorList.high
          : (num < this.lowValue ? this.colorList.low : this.colorList.medium)
        item.backgroundColor = num >= this.highValue
          ? 'rgba(255, 104, 104, 0.2)'
          : 'rgba(255, 255, 255, 1)'
        item.boxClass = num >= this.highValue
          ? 'reb-border'
          : ''
      })
    }
  }
}
</script>

<style scoped lang="scss">
.restaurant {
  height: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  .restaurant-box {
    flex-shrink: 0;
  }
  .restaurant-inner {
    width: 121px;
    height: 121px;
    margin-left: 25px;
    margin-right: 25px;
    border: 1px solid #fff;
    border-radius: 50%;
    &.reb-border {
      border: 1px solid #FF6868;
    }
  }
}
</style>