echarts3d饼图

<template>

  <div>

    <div class="left" ref="chart" style="width: 100%; height: 151px"></div>

    <!-- <div class="right">

      <div class="chanye_con_right_li">

        <span></span>

        <div class="chanye_con_right_li_text">

          {{ pondRenovation[0].xaixy }}

        </div>

        <div>{{ pondRenovation[0].yaixy }}个</div>

        <div>

          {{

            (

              (pondRenovation[0].yaixy /

                (parseFloat(this.pondRenovation[0].yaixy) +

                  parseFloat(this.pondRenovation[1].yaixy) +

                  parseFloat(this.pondRenovation[2].yaixy))) *

              100

            ).toFixed(2)

          }}%

        </div>

      </div>

      <div class="chanye_con_right_li">

        <span></span>

        <div class="chanye_con_right_li_text">

          {{ pondRenovation[1].xaixy }}

        </div>

        <div>{{ pondRenovation[1].yaixy }}个</div>

        <div>

          {{

            (

              (pondRenovation[1].yaixy /

                (parseFloat(this.pondRenovation[0].yaixy) +

                  parseFloat(this.pondRenovation[1].yaixy) +

                  parseFloat(this.pondRenovation[2].yaixy))) *

              100

            ).toFixed(2)

          }}%

        </div>

      </div>

      <div class="chanye_con_right_li">

        <span></span>

        <div class="chanye_con_right_li_text">

          {{ pondRenovation[2].xaixy }}

        </div>

        <div>{{ pondRenovation[2].yaixy }}个</div>

        <div>

          {{

            (

              (pondRenovation[2].yaixy /

                (parseFloat(this.pondRenovation[0].yaixy) +

                  parseFloat(this.pondRenovation[1].yaixy) +

                  parseFloat(this.pondRenovation[2].yaixy))) *

              100

            ).toFixed(2)

          }}%

        </div>

      </div>

    </div> -->

  </div>

</template>

<script>

import * as echarts from "echarts";

import "echarts-gl";

export default {

  props: ["pondRenovation"],

  data: {},

  mounted() {},

  watch: {

    pondRenovation: {

      handler(n) {

        console.log(n, "ceshidse");

        let all = 0;

        n.forEach((e) => {

          e.yaixy = parseFloat(e.yaixy);

          all += e.yaixy;

        });

        this.renderChart(n, all);

      },

      deep: true,

    },

  },

  methods: {

    renderChart(n, all) {

      // 生成扇形的曲面参数方程,用于 series-surface.parametricEquation

      function getParametricEquation(

        startRatio,

        endRatio,

        isSelected,

        isHovered,

        k,

        height

      ) {

        // 计算

        let midRatio = (startRatio + endRatio) / 2;

        let startRadian = startRatio * Math.PI * 2;

        let endRadian = endRatio * Math.PI * 2;

        let midRadian = midRatio * Math.PI * 2;

        // 如果只有一个扇形,则不实现选中效果。

        if (startRatio === 0 && endRatio === 1) {

          isSelected = false;

        }

        // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)

        k = typeof k !== "undefined" ? k : 1 / 3;

        // 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)

        let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;

        let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;

        // 计算高亮效果的放大比例(未高亮,则比例为 1)

        let 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: function (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: function (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: function (u, v) {

            if (u < -Math.PI * 0.5) {

              return Math.sin(u);

            }

            if (u > Math.PI * 2.5) {

              return Math.sin(u);

            }

            return Math.sin(v) > 0 ? 1 * height : -1;

          },

        };

      }

      // 生成模拟 3D 饼图的配置项

      function getPie3D(pieData, internalDiameterRatio) {

        let series = [];

        let sumValue = 0;

        let startValue = 0;

        let endValue = 0;

        let k =

          typeof internalDiameterRatio !== "undefined"

            ? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)

            : 1 / 3;

        // 为每一个饼图数据,生成一个 series-surface 配置

        for (let i = 0; i < pieData.length; i++) {

          sumValue += pieData[i].value;

          let 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: k,

            },

          };

          if (typeof pieData[i].itemStyle != "undefined") {

            let itemStyle = {};

            typeof pieData[i].itemStyle.color != "undefined"

              ? (itemStyle.color = pieData[i].itemStyle.color)

              : null;

            typeof pieData[i].itemStyle.opacity != "undefined"

              ? (itemStyle.opacity = pieData[i].itemStyle.opacity)

              : null;

            seriesItem.itemStyle = itemStyle;

          }

          series.push(seriesItem);

        }

        let legendData = [];

        // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,

        // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。

        for (let i = 0; i < series.length; i++) {

          endValue = startValue + series[i].pieData.value;

          series[i].pieData.startRatio = startValue / sumValue;

          series[i].pieData.endRatio = endValue / sumValue;

          series[i].parametricEquation = getParametricEquation(

            series[i].pieData.startRatio,

            series[i].pieData.endRatio,

            false,

            false,

            k,

            series[i].pieData.value

          );

          startValue = endValue;

          legendData.push(series[i].name);

        }

        // // 补充一个透明的圆环,用于支撑高亮功能的近似实现。

        series.push({

          name: "mouseoutSeries",

          type: "surface",

          parametric: true,

          wireframe: {

            show: false,

          },

          itemStyle: {

            opacity: 0.1,

            color: "#E1E8EC",

          },

          parametricEquation: {

            u: {

              min: 0,

              max: Math.PI * 2,

              step: Math.PI / 20,

            },

            v: {

              min: 0,

              max: Math.PI,

              step: Math.PI / 20,

            },

            x: function (u, v) {

              return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2;

            },

            y: function (u, v) {

              return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2;

            },

            z: function (u, v) {

              return Math.cos(v) > 0 ? -0.5 : -5;

            },

          },

        });

        // // 补充一个透明的圆环,用于支撑高亮功能的近似实现。

        series.push({

          name: "mouseoutSeries",

          type: "surface",

          parametric: true,

          wireframe: {

            show: false,

          },

          itemStyle: {

            opacity: 0.1,

            color: "#E1E8EC",

          },

          parametricEquation: {

            u: {

              min: 0,

              max: Math.PI * 2,

              step: Math.PI / 20,

            },

            v: {

              min: 0,

              max: Math.PI,

              step: Math.PI / 20,

            },

            x: function (u, v) {

              return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2;

            },

            y: function (u, v) {

              return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2;

            },

            z: function (u, v) {

              return Math.cos(v) > 0 ? -5 : -7;

            },

          },

        });

        series.push({

          name: "mouseoutSeries",

          type: "surface",

          parametric: true,

          wireframe: {

            show: false,

          },

          itemStyle: {

            opacity: 0.1,

            color: "#E1E8EC",

          },

          parametricEquation: {

            u: {

              min: 0,

              max: Math.PI * 2,

              step: Math.PI / 20,

            },

            v: {

              min: 0,

              max: Math.PI,

              step: Math.PI / 20,

            },

            x: function (u, v) {

              return (

                ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2.2

              );

            },

            y: function (u, v) {

              return (

                ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2.2

              );

            },

            z: function (u, v) {

              return Math.cos(v) > 0 ? -7 : -7;

            },

          },

        });

        return series;

      }

      const colors = [

        "#FFCC04",

        "#00C8FF",

        "#FFA68F",

        "#8FD7FC",

        "#466BE7",

        "#F4BB29",

        "#49C384",

        "#8FD7FC",

        "#466BE7",

        "#F4BB29",

        "#49C384",

      ];

      let dataname = [];

      // 传入数据生成 option

      const optionsData = [];

      n.forEach((e, o) => {

        optionsData.push({

          name: e.xaixy,

          value: e.yaixy,

          itemStyle: {

            //   opacity: 0.5,

            color: colors[o],

          },

        });

        dataname.push(e.xaixy);

      });

      const series = getPie3D(optionsData, 0.5, 240, 28, 26, 0.5);

      series.push({

        name: "pie2d",

        type: "pie",

        label: {

          show: false,

          opacity: 1,

          fontSize: 13,

          lineHeight: 20,

          textStyle: {

            fontSize: 22,

          },

        },

        labelLine: {

          length: 60,

          length2: 60,

        },

        startAngle: -30, //起始角度,支持范围[0, 360]。

        clockwise: false, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式

        radius: ["40%", "80%"],

        center: ["50%", "50%"],

        data: optionsData,

        itemStyle: {

          opacity: 0,

        },

      });

      // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,

      // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。

      // console.log(pieData, "pieData");

      // 准备待返回的配置项,把准备好的 legendData、series 传入。

      var option = {

        legend: {

          data: dataname,

          color: colors,

          //图例列表的布局朝向。

          orient: "vertical",

          type: "scroll",

          scroll: {

            position: "top", // 将滚动切换按钮放置在图例的上方

          },

          right: 50,

          bottom: 20,

          //图例文字每项之间的间隔

          itemGap: 5,

          show: true,

          icon: "rect",

          itemHeight: 10,

          itemWidth: 10,

          textStyle: {

            //图例字体大小

            fontSize: 14,

            color: "#000",

            lineHeight: 20,

            lineWidth: 50,

          },

          //格式化图例文本

          formatter: function (name) {

            var target;

            var pj;

            for (var i = 0, l = optionsData.length; i < l; i++) {

              if (optionsData[i].name == name) {

                target = optionsData[i].value;

                pj = ((optionsData[i].value / all) * 100).toFixed(2);

              }

            }

            return `${name}   ${target}个  ${pj}%`;

          },

        },

        tooltip: {

          show: true,

        },

        animation: true,

        tooltip: {

          formatter: (params) => {

            if (

              params.seriesName !== "mouseoutSeries" &&

              params.seriesName !== "pie2d"

            ) {

              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 + ""

              }`;

            }

          },

          textStyle: {

            fontSize: 16,

          },

        },

        title: {

          x: "center",

          top: "20",

          textStyle: {

            color: "#fff",

            fontSize: 22,

          },

        },

        // backgroundColor: "#333",

        labelLine: {

          show: true,

          lineStyle: {

            color: "#7BC0CB",

          },

        },

        label: {

          show: true,

          position: "outside",

          formatter: "{b} \n{c} {d}%",

        },

        xAxis3D: {

          min: -1,

          max: 1,

        },

        yAxis3D: {

          min: -1,

          max: 1,

        },

        zAxis3D: {

          min: -1,

          max: 1,

        },

        grid3D: {

          show: false,

          boxHeight: 0.4,

          //top: '30%',

          left: "-25%",

          bottom: "50%",

          // environment: "#021041",

          viewControl: {

            distance: 180,

            alpha: 25,

            beta: 60,

            autoRotate: false, // 自动旋转

          },

        },

        series: series,

      };

      const chart = echarts.init(this.$refs.chart);

      chart.setOption(option);

    },

  },

};

</script>

<style scoped lang="scss">

.left {

  margin-left: 20px;

  float: left;

}

.right {

  float: left;

  width: 114px;

  height: 102px;

  // background-color: #fff;

  margin: 23px 16px;

  .chanye_con_right_li {

    position: relative;

    width: 180px;

    padding: 12px 0 12px 28px;

    height: 32px;

    line-height: 32px;

    font-size: 14px;

    font-family: PingFangSC-Medium, PingFang SC;

    font-weight: 500;

    color: #06543e;

    line-height: 14px;

    display: flex;

    justify-content: space-between;

    span {

      display: inline-block;

      position: absolute;

      top: 16px;

      left: 12px;

      width: 8px;

      height: 8px;

      background-color: #ffc900;

    }

  }

  .chanye_con_right_li:nth-child(2) {

    span {

      display: inline-block;

      position: absolute;

      top: 16px;

      left: 12px;

      width: 8px;

      height: 8px;

      background-color: #00adff;

    }

  }

  .chanye_con_right_li:nth-child(3) {

    span {

      display: inline-block;

      position: absolute;

      top: 16px;

      left: 12px;

      width: 8px;

      height: 8px;

      background-color: #ff7c5c;

    }

  }

}

</style>

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值