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>
复制