Echarts+vue实现3d轮播饼图

效果如下

在这里插入图片描述

3D饼图的实现方式

surface曲面的原理:
使用surface的parametricEquation属性,为每一项数据生成了一个扇形的曲面参数方程,然后生成了不同的曲面,这里的方程完全看不懂,直接拿来用就行了。

/**
 * 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
 */
const 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) {
    isSelected = false;
  }
  // 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
  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: 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) * h * 0.1;
      }
      return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
    },
  };
};

轮播的实现方式

定时器循环currentIndex并setOptions

    async pipeAnimation(myChart) {
      let { curIndex } = this;
      let that = this;
      let timer = setInterval(() => {
        curIndex = curIndex + 1;
        if (curIndex === that.optionData.length) {
          curIndex = 0;
        }
        that.highLight(myChart, "option", {
          seriesIndex: curIndex,
          seriesName: that.optionData[curIndex].name,
        });
      }, 2000);
    },

    // 把需要高的那一项的高度h调高,然后setOption
    highLight(myChart, optionName, params) {
      // 准备重新渲染扇形所需的参数
      let isSelected;
      let isHovered;
      let startRatio;
      let endRatio;
      let k;
      // 如果触发 mouseover 的扇形当前已高亮,则不做操作
      if (this.hoveredIndex === params.seriesIndex) {
        // 否则进行高亮及必要的取消高亮操作
      } else {
        // 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
        if (this.hoveredIndex !== "") {
          // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
          isSelected =
            this[optionName].series[this.hoveredIndex].pieStatus.selected;
          isHovered = false;
          startRatio =
            this[optionName].series[this.hoveredIndex].pieData.startRatio;
          endRatio =
            this[optionName].series[this.hoveredIndex].pieData.endRatio;
          k = this[optionName].series[this.hoveredIndex].pieStatus.k;
          // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
          this[optionName].series[this.hoveredIndex].parametricEquation =
            getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              this[optionName].series[this.hoveredIndex].pieData.value
            );
          this[optionName].series[this.hoveredIndex].pieStatus.hovered =
            isHovered;
          // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
          this.hoveredIndex = "";
        }
        // 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
        if (params.seriesName !== "mouseoutSeries") {
          // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
          isSelected =
            this[optionName].series[params.seriesIndex].pieStatus.selected;
          isHovered = true;
          startRatio =
            this[optionName].series[params.seriesIndex].pieData.startRatio;
          endRatio =
            this[optionName].series[params.seriesIndex].pieData.endRatio;
          k = this[optionName].series[params.seriesIndex].pieStatus.k;
          // 对当前点击的扇形,执行高亮操作(对 option 更新)
          this[optionName].series[params.seriesIndex].parametricEquation =
            getParametricEquation(
              startRatio,
              endRatio,
              isSelected,
              isHovered,
              k,
              this[optionName].series[params.seriesIndex].pieData.value + 5
            );
          this[optionName].series[params.seriesIndex].pieStatus.hovered =
            isHovered;
          // 记录上次高亮的扇形对应的系列号 seriesIndex
          this.hoveredIndex = params.seriesIndex;
        }
        // 使用更新后的 option,渲染图表
        myChart.setOption(this[optionName]);
      }
    },
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值