数据看板 项目开发中,有一个饼状图需求:
有多少条数据就生成多少个环形图。
左侧为饼状图,
右侧为自定义legend,可以选中和取消选中,左侧饼状图会随着数据的选中变化而变化。
组件代码
<template>
<div class="echartsPage">
<div class="total">
<p>分类总数</p>
<span>{{total}}</span>
</div>
<div class="echartsBodys">
<echarts1 title="重点场所分类" :total="total" :list="list" ref="echarts"></echarts1>
<div class="list">
<div class="listItem cur" @click="getChecked(index)" v-for="(item,index) in list" :key="index">
<div class="listIteml">
<div class="dot" :class="{disabled:!item.checked}"
:style="'background: linear-gradient(80deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
<span :class="{disabled:!item.checked}">{{ item.name }}</span>
</div>
<em class="num"
v-if="item.checked">{{
item.value
}}</em>
<em class="num"
v-else>{{
item.value
}}</em>
</div>
</div>
</div>
</div>
</template>
<script>
import WOW from "wow.js";
import echarts1 from "./components/echarts.vue";
export default {
name: "title",
data() {
return {
list: [
{
name: '车站',
value: 143,
color1: 'rgba(66, 144, 210, 1)',
color2: 'rgba(66, 144, 210, 1)',
checked: true
},
{
name: '飞机场',
value: 3,
color1: 'rgba(234, 175, 15, 1)',
color2: 'rgba(159, 150, 11, 1)',
checked: true
},
{
name: '党群服务中心',
value: 35,
color1: 'rgba(108, 15, 234, 1)',
color2: 'rgba(70, 11, 159, 1)',
checked: true
},
{
name: '重点企业',
value: 5,
color1: 'rgba(81, 122, 242, 1)',
color2: 'rgba(11, 88, 159, 1)',
checked: true
},
{
name: '宗教活动场所',
value: 34,
color1: 'rgba(15, 234, 234, 1)',
color2: 'rgba(11, 155, 159, 1)',
checked: true
},
{
name: '学校',
value: 206,
color1: 'rgba(6, 114, 91, 1)',
color2: 'rgba(14, 224, 159, 1)',
checked: true
},
{
name: '博物馆/展览馆 陈列馆',
value: 196,
color1: 'rgba(253, 168, 62, 1)',
color2: 'rgba(254, 217, 82, 1)',
checked: true
}]
}
},
computed: {
total: function () {
var total = 0
this.list.forEach((type) => {
total += type.value
});
return total
}
},
components: {echarts1},
props: {
title: {
type: String,
default() {
return '';
}
},
icon: {
type: String,
default() {
return '';
}
},
},
watch: {},
mounted() {
var that = this;
var wow = new WOW({
boxClass: "wow", // animated element css class (default is wow)
animateClass: "animated", // animation css class (default is animated)
offset: 0, // distance to the element when triggering the animation (default is 0)
mobile: true, // trigger animations on mobile devices (default is true)
live: true, // act on asynchronously loaded content (default is true)
callback: function (box) {
// the callback is fired every time an animation is started
// the argument that is passed in is the DOM node being animated
},
scrollContainer: null, // optional scroll container selector, otherwise use window,
resetAnimation: true, // reset animation on end (default is true)
});
wow.init();
},
methods: {
getChecked(index) {
this.list[index].checked = !this.list[index].checked
this.$refs.echarts.drawEcharts()
}
},
}
</script>
<style lang="scss" scoped>
.list {
margin-left: 0px;
position: relative;
width: calc(50% - 0px);
margin-right: 0px;
height: calc(100% - 20px);
margin-bottom: 10px;
//background: url("./assets/jiaobiaobg.png") no-repeat;
//background-size: 100% 100%;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
.listItem {
font-size: 14px;
display: flex;
height: 30%;
width: calc(100% - 30px);
margin: 0 auto;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
.listIteml {
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
font-size: 14px;
font-family: MicrosoftYaHei;
font-weight: 400;
color: #FFFFFF;
}
span {
font-size: 14px;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #E0F9FF;
line-height: 20px;
}
.dot {
width: 8px;
height: 8px;
margin-right: 10px;
flex-shrink: 0;
}
.dot.disabled {
background: rgba(#999, 0.8) !important;
}
span.disabled {
color: rgba(#999, 0.8) !important;
}
.num {
font-size: 18px;
font-family: DIN-Bold;
font-weight: 500;
color: #FFFFFF;
text-shadow: 0 0 8px #2a95f5;
//background: linear-gradient(0deg, rgba(#999, 0.8) 0.1220703125%, rgba(#999, 0.8) 100%);
//-webkit-background-clip: text;
//-webkit-text-fill-color: transparent;
}
}
}
.echartsBodys {
width: 100%;
position: relative;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
}
.echartsPage {
width: 100%;
position: relative;
height: 100%;
display: flex;
justify-content: space-between;
align-items: flex-start;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
}
.total {
height: 50px;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
margin-left: 37px;
font-size: 12px;
font-family: MicrosoftYaHei;
font-weight: 400;
color: #FFFFFF;
span {
font-size: 26px;
font-family: DIN-Bold;
font-weight: 900;
color: #FFFFFF;
margin-left: 13px;
text-shadow: 0 0 10px #2e99ec;
}
}
</style>
echarts代码
<template>
<div class="echarts1" ref="echarts1">
</div>
</template>
<script>
import * as echarts from "echarts"
export default {
name: 'echarts1',
components: {},
data() {
return {}
},
props: {
list: {
type: Array,
default() {
return [];
}
}
},
computed: {
list2: function () {
var list = []
this.list.forEach((type) => {
if (type.checked) {
list.push(type)
}
});
return list
}
},
watch: {
list() {
this.drawEcharts()
},
},
mounted() {
var that = this;
const viewElem = document.body;
// 监听窗口变化,重绘echarts
const resizeObserver = new ResizeObserver(() => {
setTimeout(() => {
that.drawEcharts();
}, 300)
});
resizeObserver.observe(viewElem);
},
methods: {
drawEcharts() {
var that = this;
let myChart = echarts.init(this.$refs.echarts1)
let series = [];
let pieDatas = this.list2;
let maxRadius = 80,
barWidth = 5,
barGap = 5;
let sumValue = 0;
pieDatas.map(item => {
sumValue += item.value;
})
let barColor = this.list2;
pieDatas.map((item, i) => {
series.push({
type: 'pie',
clockWise: true, //顺时加载
hoverAnimation: false, //鼠标移入变大
radius: [(maxRadius - i * (barGap + barWidth)) + '%', (maxRadius - (i + 1) * barWidth - i * barGap) + '%'],
center: ["50%", "50%"],
label: {
show: false
},
itemStyle: {
label: {
show: false,
},
labelLine: {
show: false
},
borderWidth: 5,
},
data: [{
value: item.value,
name: item.name,
itemStyle: {
color: barColor[i] && barColor[i].color1 || 'rgba(68,165,255,1)'
}
}, {
value: sumValue - item.value,
name: '',
itemStyle: {
color: "transparent",
},
tooltip: {
show: false
},
hoverAnimation: false
}]
})
series.push({
name: 'blank',
type: 'pie',
silent: true,
z: 0,
clockWise: true, //顺时加载
hoverAnimation: false, //鼠标移入变大
radius: [(maxRadius - i * (barGap + barWidth)) + '%', (maxRadius - (i + 1) * barWidth - i * barGap) + '%'],
center: ["50%", "50%"],
label: {
show: false
},
itemStyle: {
label: {
show: false,
},
labelLine: {
show: false
},
borderWidth: 5,
},
data: [{
value: 1,
itemStyle: {
color: "#122d57",
borderWidth: 0
},
tooltip: {
show: false
},
hoverAnimation: false
}]
});
})
var option = {
grid: {
left: 0,
right: 0,
top: 0,
bottom: 0,
},
tooltip: {
show: true,
trigger: "item",
},
series: series,
};
myChart.clear()
myChart.resize()
myChart.setOption(option)
},
}
}
</script>
<style lang="scss" scoped>
.echarts1 {
position: relative;
width: 50%;
height: calc(100% - 10px);
}
</style>