用水球图显示餐厅的人流量
一、业务要求
用水球图显示餐厅的人流量,
当高于高基准线(0.6)时,显示红色边框和红色背景;
当低于低基准线(0.4)时,显示绿色背景;
当基于之间时,显示黄色背景。
二、实现效果
三、代码实现
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>