1、3d饼图,添加了背景图和图标
图像示例:
<template>
<div ref="chart" class="chart"></div>
</template>
<script>
import * as echarts from "echarts";
import "echarts-gl";
export default {
name: "ChartPie",
props: {
pieArr: {
type: Array,
default: () => [
{
name: "婚姻家庭纠纷",
value: 100,
itemStyle: {
color: "#52A9E0",
},
},
{
name: "邻里纠纷",
value: 150,
itemStyle: {
color: "#3780F4",
},
},
{
name: "合同纠纷",
value: 139,
itemStyle: {
color: "#74E6CF",
},
},
{
name: "生产经营纠纷",
value: 170,
itemStyle: {
color: "rgb(195,204,140)",
},
},
],
},
},
data() {
return {
evatotal1: 0,
evatotal2: 0,
evatotal3: 0,
};
},
async mounted() {
const chart = echarts.init(this.$refs.chart);
chart.setOption(this.getPie3D(this.pieArr, 0.75));
// 0.75这个值决定了圆环的宽度
chart.on("click", (params) => {
if (params.seriesName) {
this.$emit("getList", true);
}
});
},
methods: {
getPerSum(arr) {
var s = 0;
for (var i = arr.length - 1; i >= 0; i--) {
s += arr[i].percent;
}
return s;
},
getSum(arr) {
var s = 0;
for (var i = arr.length - 1; i >= 0; i--) {
s += arr[i].value;
}
return s;
},
// 生成扇形的曲面参数方程
getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
// 计算
const midRatio = (startRatio + endRatio) / 2;
const startRadian = startRatio * Math.PI * 2;
const endRadian = endRatio * Math.PI * 2;
const midRadian = midRatio * Math.PI * 2;
// 如果只有一个扇形,则不实现选中效果。
if (startRatio === 0 && endRatio === 1) {
// eslint-disable-next-line no-param-reassign
isSelected = false;
}
// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
// eslint-disable-next-line no-param-reassign
k = typeof k !== "undefined" ? k : 1 / 3;
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
const offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
const offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
// 计算高亮效果的放大比例(未高亮,则比例为 1)
const hoverRate = isHovered ? 1.05 : 1;
// 返回曲面参数方程
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32,
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
x(u, v) {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y(u, v) {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z(u, v) {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u) * 300 * 0.01;
}
// 当前图形的高度是Z根据h(每个value的值决定的)
return Math.sin(v) > 0 ? 1 * 300 * 0.01 : -1;
},
};
},
getPie3D(pieData, internalDiameterRatio) {
const series = [];
// 总和
let sumValue = 0;
let startValue = 0;
let endValue = 0;
const legendData = [];
const k =
typeof internalDiameterRatio !== "undefined"
? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
: 1 / 3;
// 为每一个饼图数据,生成一个 series-surface 配置
for (let i = 0; i < pieData.length; i += 1) {
sumValue += pieData[i].value;
const seriesItem = {
name: typeof pieData[i].name === "undefined" ? `series${i}` : pieData[i].name,
type: "surface",
parametric: true,
wireframe: {
show: false,
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k,
},
};
if (typeof pieData[i].itemStyle !== "undefined") {
const { itemStyle } = pieData[i];
// eslint-disable-next-line no-unused-expressions
typeof pieData[i].itemStyle.color !== "undefined"
? (itemStyle.color = pieData[i].itemStyle.color)
: null;
// eslint-disable-next-line no-unused-expressions
typeof pieData[i].itemStyle.opacity !== "undefined"
? (itemStyle.opacity = pieData[i].itemStyle.opacity)
: null;
seriesItem.itemStyle = itemStyle;
}
series.push(seriesItem);
}
for (let i = 0; i < series.length; i += 1) {
endValue = startValue + series[i].pieData.value;
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = this.getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
// 我这里做了一个处理,使除了第一个之外的值都是10
series[i].pieData.value
);
startValue = endValue;
legendData.push(series[i].name);
}
// 准备待返回的配置项,把准备好的 legendData、series 传入。
const option = {
// animation: false,
// 在graphic里添加背景图圆环和中间图标
graphic: [
{
type: "image", // 图形元素类型
id: "logo", // 更新或删除图形元素时指定更新哪个图形元素,如果不需要用可以忽略。
right: "2%", // 根据父元素进行定位 (居中)
bottom: "2%", // 根据父元素进行定位 (0%), 如果bottom的值是 0,也可以删除该bottom属性值。
z: 0, // 层叠
zlevel: -999,
bounding: "all", // 决定此图形元素在定位时,对自身的包围盒计算方式
style: {
// 自行调整尺寸和位置使图片正好在柱状图的下方,尽量美观
image: require("@/assets/imgs/3d-pie-bg.png"),
// $nowSize是另一个老哥写的适配尺寸的全局方法
width: this.$nowSize(238),
height: this.$nowSize(135),
},
},
{
type: "image", // 图形元素类型
id: "icon", // 更新或删除图形元素时指定更新哪个图形元素,如果不需要用可以忽略。
right: "15.5%", // 根据父元素进行定位 (居中)
bottom: "53%", // 根据父元素进行定位 (0%), 如果bottom的值是 0,也可以删除该bottom属性值。
z: 0, // 层叠
zlevel: 999,
bounding: "all", // 决定此图形元素在定位时,对自身的包围盒计算方式
style: {
image: require("@/assets/imgs/pie-inner-icon.png"),
width: this.$nowSize(95),
height: this.$nowSize(83),
},
},
],
// tooltip模板字符串
tooltip: {
formatter: (params) => {
if (params.seriesName !== "mouseoutSeries") {
return `${
params.seriesName
}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
params.color
};"></span>${option.series[params.seriesIndex].pieData.value}`;
}
return "";
},
},
legend: {
orient: "vertical",
itemGap: 10,
itemWidth: 10,
icon: "circle",
top: 0,
right: "right",
left: "25",
textStyle: {
color: "#fff",
fontSize: 12,
rich: {
num1: {
color: "#4be1ff",
fontWeight: 600,
},
title: {
width: 50,
color: "#CCCCCC",
},
},
},
formatter: function (name) {
let data = series;
let total = 0;
let tarValue;
// let ratio;
for (let i = 0; i < data.length; i++) {
total += data[i].pieData.value;
if (data[i].name === name) {
tarValue = data[i].pieData.value;
}
}
let v = tarValue;
let showStr = "{title|" + name + "}" + " {num1|" + v + "}";
// return `${name} ${v}`;
return showStr;
//name是名称,v是数值
},
},
xAxis3D: {
min: -1,
max: 1,
},
yAxis3D: {
min: -1,
max: 1,
},
zAxis3D: {
min: -1,
max: 1,
},
grid3D: {
show: false,
boxHeight: 5,
top: "-20%",
left: "25%",
viewControl: {
alpha: 25,
// beta: 30,
rotateSensitivity: 1,
zoomSensitivity: 0,
panSensitivity: 0,
autoRotate: true,
distance: 110,
},
postEffect: {
enable: false,
bloom: {
enable: true,
bloomIntensity: 0.1,
},
SSAO: {
enable: true,
quality: "medium",
radius: 2,
},
// temporalSuperSampling: {
// enable: true,
// },
},
},
series: [
...series,
{
type: "pie",
labelLine: {
length: 10,
length2: 30,
},
startAngle: -25,
// 图像会自动旋转
clockwise: true,
radius: ["65%", "65%"],
center: ["35%", "40%"],
data: pieData,
label: {
show: false,
color: "#fff",
},
zlevel: 999,
},
],
};
return option;
},
},
};
</script>
<style scoped>
.chart {
/* height: 100%; */
}
</style>
这个3d柱状图的尺寸我写在了组件的外面,高度是150px。
2、层叠的柱状图
<template lang="html">
<div class="wh100">
<div ref="chart" class="wh100"></div>
</div>
</template>
<script>
import * as echarts from "echarts";
export default {
name: "leftTop",
components: {},
mixins: [],
props: {},
data() {
return {
total: 0,
};
},
computed: {},
watch: {},
created() {},
async mounted() {
await this.$nextTick();
this.initChart();
},
methods: {
async initChart() {
let arr = [
{ name: "硕士以上", value: 129 },
{ name: "本科", value: 80 },
{ name: "大专", value: 64 },
{ name: "高中", value: 34 },
{ name: "小学", value: 15 },
{ name: "文盲", value: 11 },
];
// 自定义颜色数组
let color = [
{
type: "bar",
colorStops: [
{
offset: 0,
color: "#F5FAFF", // 0% 处的颜色
},
{
offset: 1,
color: "#0083B6", // 100% 处的颜色
},
],
globalCoord: false, // 缺省为 false
},
"#0099B7",
"#00AEA0",
"#BB6532",
"#BD9734",
"#00D146",
];
let newArr = [];
let seriesArr = [];
// map循环得出echarts option中的series
arr.map((item, index) => {
// 将颜色一一循环进去
color.map((i, e) => {
if (index === e) {
const { name, value } = item;
newArr.push(name);
seriesArr.push({
name: name,
type: "bar",
// stack都相等,所有柱状图会层叠在一起,实现目前的效果
stack: "2",
barWidth: 8,
itemStyle: {
color: i,
},
label: {
nomal: {
show: false,
},
},
data: [
{
value: value,
itemStyle: {
normal: {
color: i,
},
},
},
],
});
}
});
});
var myChart = echarts.init(this.$refs.chart);
const option = {
grid: {
top: 0,
// bottom: 0,
left: "0",
right: "0",
containLabel: false,
},
tooltip: {
show: false,
formatter: "{b} <br> {c}%",
},
// 自定义legend
legend: {
show: true,
icon: "",
bottom: "10%",
left: "0",
itemWidth: 10,
itemHeight: 10,
itemGap: 10,
textStyle: {
color: "#89A7AF",
rich: {
origin: {
color: "#89A7AF",
width: 50,
},
white: {
color: "#ffffff",
align: "left",
width: 20,
},
blue: {
color: "#00C6FF",
fontFamily: "DIN Alternate",
align: "left",
// fontWeight: 600,
width: 40,
},
},
},
formatter: (name) => {
let obj = arr.find((item) => item.name === name);
let str =
"{origin|" +
obj.name +
"}" +
" " +
"{white|" +
obj.value +
"}" +
" {blue|" +
((obj.value / 550) * 100).toFixed(2) +
"%" +
"} ";
return str;
},
},
xAxis: [
{
type: "value",
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
show: false,
},
splitLine: {
show: false,
},
},
],
yAxis: [
{
//type: 'category',
// 该图不显示y轴
data: [""],
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
textStyle: {
color: "#fff",
},
},
},
],
series: seriesArr,
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
},
},
};
</script>
<style lang="scss" scoped></style>