首页 前端知识 echarts图分享(3d饼图及特殊的柱状图

echarts图分享(3d饼图及特殊的柱状图

2024-08-14 22:08:15 前端知识 前端哥 994 141 我要收藏

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>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/15661.html
标签
评论
发布的文章

JQuery 详细教程

2024-08-21 22:08:08

jQuery2 高级教程(八)

2024-08-21 22:08:06

jQuery Spellchecker 使用教程

2024-08-21 22:08:50

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!