echarts在绘制饼状图的时候,为了让饼状图能够多样性,会设计出多种不同样式的饼状图,今天的饼状图是有一种立体感的饼状图,效果如下:
这里的饼状图分为两层,我们让两层饼状图稍微错位一点再给一个深浅不同的颜色就实现了我们想要的效果。
实例代码
<template>
<div class="echartsBody">
<div class="echartsBody1" ref="echarts1"></div>
<div class="echartsBg">
<div class="echartsBgInner"></div>
</div>
</div>
</template>
<script>
import * as echarts from "echarts"
export default {
name: 'echarts1',
components: {},
data() {
return {}
},
props: {
list: {
type: Array,
default() {
return [];
}
},
shadowColor: {
type: String,
default() {
return 'rgba(254, 175, 87, 0.5)';
}
},
title: {
type: String,
default() {
return '各班组效率';
}
},
total: {
type: String,
default() {
return 0;
}
},
},
mounted() {
var that = this;
const viewElem = document.body;
// 监听窗口变化,重绘echarts
const resizeObserver = new ResizeObserver(() => {
setTimeout(() => {
that.drawEcharts();
}, 300)
});
resizeObserver.observe(viewElem);
},
computed: {
colorList: function () {
var that = this;
var colorList = []
that.list.forEach((type) => {
if (type.checked) {
var color = new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: type.color1
}, {
offset: 1,
color: type.color2
}])
colorList.push(color)
}
}
);
return colorList
}
},
methods: {
drawEcharts() {
var that = this
let myChart = echarts.init(this.$refs.echarts1)
var colors = this.colorList
var data = []
var data2 = []
that.list.forEach((type) => {
if (type.checked) {
var datas = {
...type,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: type.color1
}, {
offset: 1,
color: type.color2
}]),
shadowColor: that.shadowColor
}
}
}
data.push(datas)
}
});
that.list.forEach((type) => {
if (type.checked) {
var datas = {
...type,
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [{
offset: 0,
color: type.color1.replace('1)', '0.5)')
}, {
offset: 1,
color: type.color2.replace('1)', '0.5)')
}]),
}
}
}
data2.push(datas)
}
});
var option = {
// color: colors,
tooltip: {
trigger: 'item',
// formatter: '{a} {b} : {c} ({d}%)'
},
series: [
{
type: 'pie',
center: ['50%', '50%'],
radius: ['55%', '75%'],
labelLine: {
normal: {
length: 20
}
},
z: 1,
label: {
show: true,
formatter: function (params) {
return `{a|${params.name}}\n{b|${params.percent}%}`
},
rich: {
a: {
fontSize: 14,
fontFamily: 'MiSans',
fontWeight: 400,
color: '#D4F2F1'
},
b: {
fontSize: 16,
fontFamily: 'MiSans',
fontWeight: 600,
color: '#FFFFFF'
}
},
},
itemStyle: {
normal: {
borderColor: '#142b47',
borderWidth: 1
}
},
data: data
},
{
z: 0,
type: 'pie',
center: ['50%', '48.5%'],
radius: ['55%', '75%'],
labelLine: {
normal: {
length: 20
}
},
label: {
show: false,
position: 'inside',
formatter: '{d}%',
color: '#fff',
fontSize: 16
},
itemStyle: {
normal: {
borderColor: '#142b47',
borderWidth: 1
}
},
data: data2
},
]
}
myChart.clear()
myChart.resize()
myChart.setOption(option)
},
}
}
</script>
<style lang="scss" scoped>
.echartsBody {
position: relative;
width: 100%;
height: calc(100% - 0px);
.echartsBody1 {
position: relative;
width: 100%;
height: calc(100% - 0px);
}
.echartsBody2 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: calc(100% - 0px);
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
pointer-events: none;
.echartsTitle {
font-size: 30px;
font-family: DIN;
font-weight: normal;
color: #FFFFFF;
text-shadow: 0 0 10px rgba(120, 168, 238, 1.00);
}
.echartsDesc {
font-size: 14px;
font-family: MicrosoftYaHei;
font-weight: 400;
color: #9DB9E9;
}
}
.echartsBg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;
flex-direction: row;
align-content: flex-start;
.echartsBgInner {
width: 100%;
height: 100%;
background: url("./assets/echartsbg.png") center center no-repeat;
background-size: contain;
scale: 0.9;
animation: rotate 3s linear infinite;
}
}
}
@keyframes rotate {
0% {
transform: rotateZ(0deg); /*从0度开始*/
}
100% {
transform: rotateZ(360deg); /*360度结束*/
}
}
</style>
传值
<template>
<div class="echartsBodys">
<div class="echartsTop">
<echarts1 title="立体饼状图" :total="total" :list="list" ref="echarts"></echarts1>
</div>
<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(0deg,'+item.color1+' 0%, '+item.color2+' 100%);'"></div>
<span :class="{disabled:!item.checked}">{{ item.name }}</span>
</div>
<div class="num"
v-if="item.checked">
{{ item.percentage }}%
</div>
</div>
</div>
</div>
</template>
<script>
import echarts1 from "./echarts/echarts.vue";
export default {
name: "title",
data() {
return {
// 颜色格式要用rgba格式,以便于echarts根据颜色设置透明度为0.8的背景形成立体饼状图
list: [
{
name: '类型1',
value: 100,
checked: true,
color1: 'rgba(254, 246, 71, 1)',
color2: 'rgba(254, 246, 71, 1)',
percentage: 0
},
{
name: '类型2',
value: 100,
checked: true,
color1: 'rgba(74, 231, 230, 1)',
color2: 'rgba(74, 231, 230, 1)',
percentage: 0
},
{
name: '类型3',
value: 100,
checked: true,
color1: 'rgba(252, 108, 126, 1)',
color2: 'rgba(252, 108, 126, 1)',
percentage: 0
},
{
name: '类型4',
value: 100,
checked: true,
color1: 'rgba(101, 252, 125, 1)',
color2: 'rgba(101, 252, 125, 1)',
percentage: 0
},
{
name: '类型5',
value: 100,
checked: true,
color1: 'rgba(252, 168, 108, 1)',
color2: 'rgba(252, 168, 108, 1)',
percentage: 0
},
{
name: '类型6',
value: 100,
checked: true,
color1: 'rgba(16, 173, 255, 1)',
color2: 'rgba(16, 173, 255, 1)',
percentage: 0
},
]
}
},
computed: {
total: function () {
var total = 0
this.list.forEach((type) => {
total += type.value
});
return total
},
},
watch: {
total: function (newTotal, oldTotal) {
this.list.forEach((type) => {
type.percentage = Math.floor((type.value / this.total) * 100);
});
}
},
components: {echarts1},
mounted() {
this.list.forEach((type) => {
type.percentage = Math.floor((type.value / this.total) * 100);
});
},
methods: {
getChecked(index) {
this.list[index].checked = !this.list[index].checked
this.$refs.echarts.drawEcharts()
},
},
}
</script>
<style lang="scss" scoped>
.echartsBodys {
width: 100%;
position: relative;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: nowrap;
flex-direction: column;
align-content: flex-start;
.list {
position: relative;
width: 100%;
height: 100px;
//background: url("./assets/jiaobiaobg.png") no-repeat;
//background-size: 100% 100%;
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
flex-direction: row;
align-content: flex-start;
margin-top: 20px;
.listItem {
font-size: 14px;
display: flex;
height: 50%;
width: calc(33.33% - 20px);
margin: 0 auto;
justify-content: flex-start;
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;
width: 340px;
}
span {
font-size: 14px;
font-family: MiSans;
font-weight: 400;
color: #D4F2F1;
}
.dot {
width: 4px;
height: 14px;
background: #FEF647;
border-radius: 2px;
margin-right: 10px;
}
.dot.disabled {
background: rgba(#999, 0.8) !important;
}
span.disabled {
color: rgba(#999, 0.8) !important;
}
.num {
font-size: 14px;
font-family: MiSans;
font-weight: 400;
color: #FFFFFF;
}
}
}
.echartsTop {
position: relative;
width: 100%;
height: calc(100% - 100px);
}
}
</style>