Echars图形样例使用

柱状图

双柱状图效果图展示

入参说明:

const chart1 = {
		// 绑定容器id
        idName: 'echart1',
        // 标志图名称
        legend: ['男生','女生'],
        // x轴名称
        xNameArr: ['2021','2022','2023'],
        // y轴单位,数组长度1只显示左边y轴,长度2显示两边y轴
        yUnits: ['万','%'],
        // 数据,二维数组,外层数组为一个组的柱子数量,内层数组与x轴对应
        dataAll: [['123','212','442'],['333','111','421']],
        // 颜色,为二维数组时可渐变,从上往下渐变,二位数组时最内层数组长度必须为二
        itemColors: [['#009BAE','#F8B616'],'#00315D'],
        // 折线数据,二维数组,外层数组为折线条数,内层数组与x轴对应,可不传
        lineAll:[['12.3','21.4','33.1'],['33','12','21'],['23','11','25']],
        // 折线颜色,为二维数组时,内层数组分别为折线颜色和折点颜色
        lineAllColors: [['#009BAE','#F8B616'],'#00315D','#00315D'],
      }
      this.initMoreDubYEchart(chart1)

js

  initMoreDubYEchart(newDataAll) {
    const defaultDataAll = {
      idName : '',
      legend : [],
      xNameArr : [],
      yUnits : ['%'],
      itemColors : [],
      dataAll : [], // 二维数组
      lineAll : [], // 二维数组
      lineAllColors : []
    }
    const dataAll = Object.assign(defaultDataAll,newDataAll)
    var chart = echarts.init(document.getElementById(dataAll.idName));
    var that = this

    const tempYAxis = []
    dataAll.yUnits.forEach(it=>{
      tempYAxis.push(
          {
            type: 'value',
            name: it,
            nameTextStyle: {
              color: '#999',
              fontSize: 8,
            },
            splitLine: {
              show: false
            },
            axisLine: {
              lineStyle: {
                color: '#DCDFE6', //轴线的颜色
              },
            },
            axisLabel: {
              show: true,
              textStyle: {
                color: '#999',
                fontSize: 8,
              },
              formatter: '{value}'
            },
          }
      )
    })

    const tempSeries = []
    dataAll.dataAll.forEach((it,index)=>{
      let color1 = '#F8B616'
      let color0 = 'rgba(248,182,22,0.4)'
      if (dataAll.itemColors.length > index) {
        if (Array.isArray(dataAll.itemColors[index]) && dataAll.itemColors[index].length === 2) {
          color1 = dataAll.itemColors[index][0]
          color0 = dataAll.itemColors[index][1]
        }  else if (typeof dataAll.itemColors[index] === "string") {
          color1 = dataAll.itemColors[index]
          color0 = dataAll.itemColors[index]
        }
      }
      tempSeries.push(
          {
            name: dataAll.legend[index],
            type: 'bar',
            tooltip: {
              valueFormatter: function (value) {
                return value;
              }
            },
            barWidth: 12, // 柱子宽度
            itemStyle: {
              barBorderRadius: [4, 4, 0, 0], // 圆角(左上、右上、右下、左下)
              color: new echarts.graphic.LinearGradient(0, 1, 0, 0,
                  [
                    {
                      offset: 0,
                      color: color0
                    },
                    {
                      offset: 1,
                      color: color1
                    }
                  ],
                  false
              ), // 渐变
              // color: dataAll.itemColors.length> index?dataAll.itemColors[index] : '#009BAE'
            },
            data: it
          }
      )
    })
    dataAll.lineAll.forEach((it,index)=>{
      let color1 = '#009BAE'
      let color0 = '#00315D'
      if (dataAll.lineAllColors.length > index) {
        if (Array.isArray(dataAll.lineAllColors[index]) && dataAll.lineAllColors[index].length === 2) {
          color1 = dataAll.lineAllColors[index][0]
          color0 = dataAll.lineAllColors[index][1]
        } else if (typeof dataAll.lineAllColors[index] === "string") {
          color1 = dataAll.lineAllColors[index]
          color0 = dataAll.lineAllColors[index]
        }
      }
      tempSeries.push(
          {
            name: dataAll.legend[index] + '同比',
            type: 'line',
            yAxisIndex: 1,
            tooltip: {
              valueFormatter: function (value) {
                return value + ' %';
              }
            },
            symbolSize: 6,   //折线点的大小
            itemStyle: {
              normal: {
                color: color0,//折线点的颜色
                lineStyle: {
                  color: color1//折线的颜色
                }
              }
            },
            // lineStyle: {
            //   normal: {
            //     width: 3,
            //   }
            // },
            data: it
          },
      )
    })

    chart.clear();
    var option = {
      title: {
        text: '',
        left: 'right',
        bottom: 5,
        textStyle: {
          color: '#999', //文字的颜色
          fontSize: 8,
        }
      },
      tooltip: {
        trigger: 'axis',
        axisPointer: {
          type: 'shadow',
          shadowStyle: {
            color: 'rgba(220, 223, 230, 1)',
          },
          z: 0,
        }
      },
      legend: {
        itemWidth: 12,// 标志图形的长度
        itemHeight: 5,// 标志图形的宽度
        textStyle: {
          //图例字体大小
          fontSize: 8,
        },
        data: dataAll.legend.length > 0 ? dataAll.legend : []
      },
      grid: {
        top: '25%',
        left: '3%',
        right: '3%',
        bottom: 10,
        containLabel: true
      },
      xAxis: [
        {
          type: 'category',
          data: dataAll.xNameArr,
          boundaryGap: true,
          axisLine: {
            lineStyle: {
              color: '#DCDFE6', //轴线的颜色
            },
          },
          axisLabel: {
            show: true,
            textStyle: {
              color: '#999',
              fontSize: 8,
            },
            interval: 0,
          },
          splitLine: {
            show: false
          },
          axisTick: {
            show: true
          },
        }
      ],
      yAxis: tempYAxis,
      dataZoom: dataAll.dataAll[0].length > 3 ? [{
        type: 'slider',
        show: true,
        xAxisIndex: [0],
        height: 10,//这里可以设置dataZoom的尺寸
        bottom: 0,
        startValue: 0,
        endValue: dataAll.dataAll[0].length,//初始化滚动条
      }] : '',
      series: tempSeries
    };
    chart.setOption(option);
    window.addEventListener("resize", function () {
      chart.resize();
    })
    chart.getZr().off('click')
    chart.getZr().on('click', (params) => {
      console.log(params, '====')
      const pointInPixel = [params.offsetX, params.offsetY];
      //点击第几个柱子
      let index;
      if (chart.containPixel('grid', pointInPixel)) {
        index = Math.abs(chart.convertFromPixel({ seriesIndex: 0 }, [params.offsetX, params.offsetY])[0]);
      }
      // console.log(index)
    })
  }

立体双柱状图(每组支持1~4根柱子)

在这里插入图片描述

弹框背景echarts_modal

<div id="dStereoBar" style="width: 628px;height: 282px;"></div>
::ng-deep.echarts_modal{
  height: 45px;
  //width: 132px;
  background: url(../../../../echarts_modal.png) no-repeat;
  background-size: 100% 100%;
  padding: 12px 10px 0;
  font-size: 15px;
  font-family: Alibaba PuHuiTi;
  font-weight: 400;
  color: #FFFFFF;
  span{
    margin-left: 17px;
    font-size: 17px;
    font-family: Alibaba PuHuiTi;
    font-weight: 400;
    color: #41D5FF;
  }
}

// 扩展柱子要同步扩展色卡:colorObj
      const testData = [{
        DATA:['373',401,556,'235',334],
        YEAR_ID:'我的'
      },{
        DATA:['235',133,222,'145',224],
        YEAR_ID:'他的'
      },{
        DATA:['444',321,551,'234',412],
        YEAR_ID:'你的'
      },{
        DATA:['331',221,312,'412',123],
        YEAR_ID:'大家的'
      }]
 this.initBarChartFn2('dStereoBar', testData, '万', ['美 元', '人民币', '日 元', '韩 元', '欧 元'])
  initBarChartFn2(idName, DataArr, unit, xData) {
    let maxDataItem = this.getMaxData(DataArr);
    let lengendArr = [], maxData = []
    for (let i = 0; i < DataArr.length; i++) {
      lengendArr.push(DataArr[i].YEAR_ID)
    }
    for (let i = 0; i < xData.length; i++) {
      maxData.push(maxDataItem)
    }
    let colorObj = {
      "我的": {
        backColorListLeft_0: '#0078FF',
        backColorListLeft_1: 'rgba(255,255,255,0)',
        backColorListRight_0: '#258AF2',
        backColorListRight_1: 'rgba(255,255,255,0)',
        backColorTop: '#199EF1',
        colorListLeft_0: '#71E1F7',
        colorListRight_0: 'rgba(25, 158, 241, 1)',
        colorListRight_0_5: 'rgba(25, 158, 241, 0.5)',
        colorListRight_1: 'rgba(25, 158, 241, 0.2)',
        colorListTop_0: '#21A4F2',
      },
      "他的": {
        backColorListLeft_0: '#FAA66E',
        backColorListLeft_1: 'rgba(255,255,255,0)',
        backColorListRight_0: '#AC866D',
        backColorListRight_1: 'rgba(255,255,255,0)',
        backColorTop: '#FAA66E',
        colorListLeft_0: '#FFD799',
        colorListRight_0: 'rgba(250, 166, 110, 1)',
        colorListRight_0_5: 'rgba(250, 166, 110, 0.5)',
        colorListRight_1: 'rgba(250, 166, 110, 0.2)',
        colorListTop_0: '#FAA66E',
      },
      "你的": {
        backColorListLeft_0: '#2fffa4',
        backColorListLeft_1: 'rgba(255,255,255,0)',
        backColorListRight_0: 'rgba(49,245,160,.7)',
        backColorListRight_1: 'rgba(255,255,255,0)',
        backColorTop: '#2fffa4',
        colorListLeft_0: 'rgba(49,245,160,.7)',
        colorListRight_0: 'rgba(49,245,160,.5)',
        colorListRight_0_5: 'rgba(49,245,160,.5)',
        colorListRight_1: 'rgba(49,245,160,.7)',
        colorListTop_0: '#2fffa4',
      },
      "大家的": {
        backColorListLeft_0: '#0078FF',
        backColorListLeft_1: 'rgba(255,255,255,0)',
        backColorListRight_0: '#258AF2',
        backColorListRight_1: 'rgba(255,255,255,0)',
        backColorTop: '#199EF1',
        colorListLeft_0: '#71E1F7',
        colorListRight_0: 'rgba(25, 158, 241, 1)',
        colorListRight_0_5: 'rgba(25, 158, 241, 0.5)',
        colorListRight_1: 'rgba(25, 158, 241, 0.2)',
        colorListTop_0: '#21A4F2',
      },
    }

    let legendData = []
    for (let i = 0; i < lengendArr.length; i++) {
      legendData.push({
        name: lengendArr[i],
        itemStyle: {
          color: colorObj[lengendArr[i]]['colorListTop_0'],
        }
      })
    }

    var myChart = echarts.init(document.getElementById(idName));

    let seriseData = []
    for (let i = 0; i < DataArr.length; i++) {
      // 柱体位置,支持4-根柱子,可继续扩展,如果柱子太多挤在一起缩小滚动条endValue参数
      let position = [0, 0]
      if (DataArr.length === 4){
        position = i === 0 ? [-75, 10] : i === 1 ? [-25, 10] : i === 2 ? [25, 10] : [75, 10]
      } else if (DataArr.length === 3){
        position = i === 0 ? [-50, 10] : i === 1 ? [0, 10] : [50, 10]
      } else if (DataArr.length === 2){
        position = i === 0 ? [-25, 10] : [25, 10]
      } else if (DataArr.length === 1){
        position = [0, 10]
      }
      seriseData.push(
        {
          type: 'custom',
          renderItem: function (params, api) {
            const location = api.coord([api.value(0), api.value(1)])
            return {
              type: 'group',
              children: [{
                // 左背景
                type: 'CubeLeft',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
                    offset: 0,
                    color: colorObj[DataArr[i].YEAR_ID]['backColorListLeft_1'] // 底部
                  }, {
                    offset: 1,
                    color: colorObj[DataArr[i].YEAR_ID]['backColorListLeft_0']// 顶部
                  }])
                }
              }, {
                // 右侧边
                type: 'CubeRight',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
                    offset: 0,
                    color: colorObj[DataArr[i].YEAR_ID]['backColorListRight_1'] // 底部
                  }, {
                    offset: 1,
                    color: colorObj[DataArr[i].YEAR_ID]['backColorListRight_0']// 顶部
                  }])
                }
              }, {
                type: 'CubeTop',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: colorObj[DataArr[i].YEAR_ID]['backColorTop'] // 底部
                }
              }]
            }
          },
          data: maxData
        },
        {
          type: 'custom',
          name: lengendArr[i],
          renderItem: (params, api) => {
            const location = api.coord([api.value(0), api.value(1)])
            return {
              type: 'group',
              children: [{
                type: 'CubeLeft',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: colorObj[DataArr[i].YEAR_ID]['colorListLeft_0']
                }
              }, {
                type: 'CubeRight',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: new echarts.graphic.LinearGradient(1, 0, 0, 0, [{
                    offset: 0,
                    color: colorObj[DataArr[i].YEAR_ID]['colorListRight_1'] // 底部
                  }, {
                    offset: 0.25,
                    color: colorObj[DataArr[i].YEAR_ID]['colorListRight_0_5']// 顶部
                  }, {
                    offset: 1,
                    color: colorObj[DataArr[i].YEAR_ID]['colorListRight_0']// 顶部
                  }])
                }
              }, {
                type: 'CubeTop',
                position: position,
                shape: {
                  api,
                  xValue: api.value(0),
                  yValue: api.value(1),
                  x: location[0],
                  y: location[1],
                  xAxisPoint: api.coord([api.value(0), 0])
                },
                style: {
                  fill: colorObj[DataArr[i].YEAR_ID]['colorListTop_0']
                }
              }]
            }
          },
          data: DataArr[i].DATA
        },
        {
          type: 'bar',
          name: lengendArr[i],
          label: {
            normal: {
              show: false,
              position: 'top',
              fontSize: 16,
              color: '#fff',
              offset: [2, -25]
            }
          },
          itemStyle: {
            color: 'transparent',
          },
          data: DataArr[i].DATA
        }
      )
    }
    // 绘制左侧面
    const CubeLeft = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0
      },
      buildPath: function (ctx, shape) {
        // 会canvas的应该都能看得懂,shape是从custom传入的
        const xAxisPoint = shape.xAxisPoint;
        const c0 = [shape.x, shape.y];
        const c1 = [shape.x - 18, shape.y - 10];
        const c2 = [xAxisPoint[0] - 18, xAxisPoint[1] - 9];
        const c3 = [xAxisPoint[0], xAxisPoint[1]];
        ctx.moveTo(c0[0], c0[1]).lineTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).closePath();
      }
    })
    // 绘制右侧面
    const CubeRight = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0
      },
      buildPath: function (ctx, shape) {
        const xAxisPoint = shape.xAxisPoint;
        const c1 = [shape.x, shape.y];
        const c2 = [xAxisPoint[0], xAxisPoint[1]];
        const c3 = [xAxisPoint[0] + 18, xAxisPoint[1] - 9];
        const c4 = [shape.x + 18, shape.y - 9];
        ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath();
      }
    })
    // 绘制顶面
    const CubeTop = echarts.graphic.extendShape({
      shape: {
        x: 0,
        y: 0
      },
      buildPath: function (ctx, shape) {
        const c1 = [shape.x, shape.y];
        const c2 = [shape.x + 18, shape.y - 9];
        const c3 = [shape.x, shape.y - 18];
        const c4 = [shape.x - 18, shape.y - 10];
        ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath();
      }
    })
    // 注册三个面图形
    echarts.graphic.registerShape('CubeLeft', CubeLeft)
    echarts.graphic.registerShape('CubeRight', CubeRight)
    echarts.graphic.registerShape('CubeTop', CubeTop)

    var option = {
      legend: {
        data: legendData,
        textStyle: {
          color: '#CADCFE',
          fontSize: 16
        },
        right: 0,
        top: 12,
        itemWidth: 31,
        itemHeight: 15,
        itemGap: 30
      },
      tooltip: {
        trigger: 'axis',
        padding: 0,
        borderWidth: 0,
        backgroundColor: 'rgba(255,255,255,0.3)',
        axisPointer: {
          type: 'shadow'
        },
        formatter: function (params) {
          let val = `<div style="font-size: 15px;padding:6px;font-family: AlibabaPuHuiTiR;font-weight: 400;color: #FFFFFF;">${params[0].name}</div>`
          $(params).each(function (idx, itm) {
            if (itm.seriesType == "bar") {
              if (itm.seriesName == "我的") {
                val += `<div class="echarts_modal">${itm.seriesName}<span>${itm.value}&nbsp;万</span></div>`
              }
              if (itm.seriesName == "你的") {
                val += `<div class="echarts_modal">${itm.seriesName}<span style="color: #FAA66E">${itm.value}&nbsp;万</span></div>`
              }
              if (itm.seriesName == "他的") {
                val += `<div class="echarts_modal">${itm.seriesName}<span style="color: #2fffa4">${itm.value}&nbsp;万</span></div>`
              }
            }
          });
          return val;
        }
      },
      grid: {
        top: "22%",
        left: "0%",
        bottom: "2%",
        right: "0%",
        containLabel: true
      },
      xAxis: {
        type: 'category',
        data: xData,
        axisLine: {
          show: true,
          lineStyle: {
            color: 'rgba(252, 252, 252, 0.6)',
            width: 1
          }
        },
        axisTick: {
          show: false,
        },
        axisLabel: {
          fontSize: 16,
          margin: 16,
          color: '#CADCFE',
        }
      },
      yAxis: {
        name: unit,
        type: 'value',
        nameTextStyle: {
          padding: [0, 28, 0, 0],
          color: '#CADCFE',
          fontSize: 16,
          lineHeight: -8,
        },
        axisLine: {
          show: false,
          lineStyle: {
            color: 'rgba(252, 252, 252, 0.3)',
            type: 'solid', // 坐标轴的分割线类型还有其他关于轴线的样式自行开发吧
            width: 2
          },
        },
        splitLine: {
          lineStyle: {
            type: "dashed", //设置网格线类型 dotted:虚线   solid:实线
            width: 1,
            color: 'rgba(252, 252, 252, 0.1)'
          },
          show: true
        },
        axiosTick: {
          show: false
        },
        axisLabel: {
          fontSize: 16,
          interval: 0,
          color: '#CADCFE'
        },
        nameGap: 40
      },
      dataZoom: [{
        xAxisIndex: [0],
        height: 6,
        type: 'slider',
        startValue: 0,//默认为0
        endValue: 1,//默认为100
        showDataShadow: false,
        show: true,
        bottom: '0px',
        borderColor: 'transparent',
        backgroundColor: 'rgba(9, 58, 139, 1)',
        fillerColor: 'rgba(95, 218, 255, 1)',
        moveHandleSize: 0,
        moveHandleStyle: {
          color: 'rgba(0,0,0,0.0)',
          shadowColor: 'rgba(0,0,0,0)',
          borderCap: 'round',
        },
        showDetail: false
      }],
      series: seriseData
    }
    myChart.clear();
    myChart.setOption(option);
    window.addEventListener("resize", function (ev) {
      myChart.resize();
    })
  }


饼图

3d动态饼图

样图


const data = [
                    {
                        itemStyle: {color: "#398BF1"},
                        name : "指标一",
                        value : 4380
                    },
                    {
                        itemStyle: {color: "#27FF78"},
                        name : "指标二",
                        value : 1123
                    },
                    {
                        itemStyle: {color: "#F29052"},
                        name : "指标三",
                        value : 21
                    },
                    {
                        itemStyle: {color: "#cc338b"},
                        name : "指标四",
                        value : 31
                    },
                    {
                        itemStyle: {color: "#80341f"},
                        name : "指标五",
                        value : 11
                    },
                    {
                        itemStyle: {color: "#161d10"},
                        name : "指标六",
                        value : 31
                    }
                ]
 				// 绑定div的id属性,显示数据
                PieThreeD('pieLoopChart',data);//默认政治面貌

js:

function PieThreeD(idName,pieOtionData) {
    console.log(pieOtionData)
    var option,
        optionData = pieOtionData;
    let hoveredIndex = "";
    let curIndex = 0;
    echarts4.init(document.getElementById(idName)).dispose();
    //构建3d饼状图
    let myChart = echarts4.init(document.getElementById(idName));

    // 传入数据生成 option
    option = getPie3D(optionData, 0.8);
    myChart.clear();
    myChart.setOption(option);
    //是否需要label指引线,如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐,并再次setOption
    option.series.push({
        name: 'pie2d',
        type: 'pie',
        labelLine: {
            length: 10,
            length2: 15
        },
        label: {
            normal: {
                textStyle: {
                    color: '#595959',	// 提示文字颜色
                    fontSize: 18		// 提示文字大小
                }
            }
        },
        startAngle: -20, //起始角度,支持范围[0, 360]。
        clockwise: false,//饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
        minAngle: 5,              //最小的扇区角度(0 ~ 360),用于防止某个值过小导致扇区太小影响交互
        avoidLabelOverlap: true,   //是否启用防止标签重叠策略
        radius: ['30%', '40%'],
        center: ['50%', '50%'],
        data: optionData,
        itemStyle: {
            opacity: 0
        }
    });
    // myChart.clear();
    // myChart.setOption(option);
    const highLight = (params) => {
        let isSelected;
        let isHovered;
        let startRatio;
        let endRatio;
        let k;

        // 如果触发 mouseover 的扇形当前已高亮,则不做操作
        if (hoveredIndex === params.seriesIndex) {
            return;

            // 否则进行高亮及必要的取消高亮操作
        } else {
            // 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
            if (hoveredIndex !== "") {
                // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
                isSelected = option.series[hoveredIndex].pieStatus.selected;
                isHovered = false;
                startRatio = Number((option.series[hoveredIndex].pieData.startRatio).toFixed(2));
                endRatio = Number((option.series[hoveredIndex].pieData.endRatio).toFixed(2));
                k = option.series[hoveredIndex].pieStatus.k;
                // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
                option.series[hoveredIndex].parametricEquation =
                    getParametricEquation(
                        startRatio,
                        endRatio,
                        isSelected,
                        isHovered,
                        k,
                        30
                    );
                option.series[hoveredIndex].pieStatus.hovered = isHovered;

                // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
                hoveredIndex = "";
            }

            // 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
            if (params.seriesName !== "mouseoutSeries") {
                // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
                if (option.series[params.seriesIndex].pieStatus != undefined) {
                    isSelected = option.series[params.seriesIndex].pieStatus.selected;
                    // isHovered = true;
                    startRatio = Number((option.series[params.seriesIndex].pieData.startRatio).toFixed(2));
                    endRatio = Number((option.series[params.seriesIndex].pieData.endRatio).toFixed(2));
                    k = option.series[params.seriesIndex].pieStatus.k;
                    // 对当前点击的扇形,执行高亮操作(对 option 更新)
                    option.series[params.seriesIndex].parametricEquation =
                        getParametricEquation(
                            startRatio,
                            endRatio,
                            isSelected,
                            isHovered,
                            k,
                            80
                        );
                    option.series[params.seriesIndex].pieStatus.hovered = isHovered;

                    // 记录上次高亮的扇形对应的系列号 seriesIndex
                    hoveredIndex = params.seriesIndex;
                }
            }

            // 使用更新后的 option,渲染图表
            myChart.setOption(option);
        }
    }
    let timer = null;
    const pipeAnimation = async () => {
        timer = setInterval(() => {
            curIndex = curIndex + 1
            if (curIndex === pieOtionData.length) curIndex = 0
            highLight({
                seriesIndex: curIndex,
                seriesName: optionData[curIndex].name
            })
        }, 2000);
    };
    pipeAnimation()
    myChart.clear();
    myChart.setOption(option);
    bindListen(myChart);

    function bindListen(myChart) {
        // 监听鼠标事件,实现饼图选中效果(单选),近似实现高亮(放大)效果。
        let selectedIndex = '';
        let hoveredIndex = '';
        // 监听 mouseover,近似实现高亮(放大)效果
        myChart.on('mouseover', function (params) {
            clearTimeout(timer);
            highLight(params)
        });
        myChart.on('mouseout', function (params) {
            clearTimeout(timer);
            pipeAnimation();
        });
        // 修正取消高亮失败的 bug
        myChart.on('globalout', function () {
            // 准备重新渲染扇形所需的参数
            let isSelected;
            let isHovered;
            let startRatio;
            let endRatio;
            let k;
            if (hoveredIndex !== '') {
                // 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
                isSelected = option.series[hoveredIndex].pieStatus.selected;
                isHovered = false;
                k = option.series[hoveredIndex].pieStatus.k;
                startRatio = Number((option.series[params.seriesIndex].pieData.startRatio).toFixed(2));
                endRatio = Number((option.series[params.seriesIndex].pieData.endRatio).toFixed(2));
                // 对当前点击的扇形,执行取消高亮操作(对 option 更新)
                option.series[hoveredIndex].parametricEquation = getParametricEquation(startRatio, endRatio,
                    isSelected,
                    isHovered, k, option.series[hoveredIndex].pieData.value);
                option.series[hoveredIndex].pieStatus.hovered = isHovered;
                // 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
                hoveredIndex = '';
            }
            // 使用更新后的 option,渲染图表
            myChart.setOption(option);
        });
    }

    function 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 @typescript-eslint/no-unused-expressions
                typeof pieData[i].itemStyle.color !== "undefined"
                    ? (itemStyle.color = pieData[i].itemStyle.color)
                    : null;
                // eslint-disable-next-line @typescript-eslint/no-unused-expressions
                typeof pieData[i].itemStyle.opacity !== "undefined"
                    ? (itemStyle.opacity = pieData[i].itemStyle.opacity)
                    : null;

                seriesItem.itemStyle = itemStyle;
            }
            series.push(seriesItem);
        }
        // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数,
        // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。
        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 = getParametricEquation(
                series[i].pieData.startRatio,
                series[i].pieData.endRatio,
                false,
                false,
                k,
                // 我这里做了一个处理,使除了第一个之外的值都是10
                30
            );

            startValue = endValue;

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

        // 准备待返回的配置项,把准备好的 legendData、series 传入。
        const option = {
            // animation: false,
            label: {
                show: true,
                position: 'outside',
                rich: {
                    b: {
                        color: 'rgba(240, 247, 255, 1)',
                        fontSize: 14,
                        lineHeight: 24
                    },
                    c: {
                        color: 'rgba(240, 247, 255, 1)',
                        fontSize: 16,
                    },
                },
                formatter: '{b|{b} \n}{c|{c}}',
            },
            tooltip: {
                formatter: params => {
                    if (params.seriesName !== 'mouseoutSeries' && params.seriesName !== 'pie2d') {
                        let val = option.series[params.seriesIndex].pieData.value;
                        let bfb = ((option.series[params.seriesIndex].pieData.endRatio - option.series[params.seriesIndex].pieData.startRatio) *
                            100).toFixed(2);
                        return `${params.seriesName}<br/>` +
                            `<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${params.color};"></span>` +
                            `${val} `+`(${bfb}%)`;
                    }
                }
            },
            xAxis3D: {
                min: -1,
                max: 1,
            },
            yAxis3D: {
                min: -1,
                max: 1,
            },
            zAxis3D: {
                min: -1,
                max: 1,
            },
            grid3D: {
                show: false,
                viewControl: { //3d效果可以放大、旋转等,请自己去查看官方配置
                    alpha: 40, //角度
                    distance: 280,//调整视角到主体的距离,类似调整zoom
                    rotateSensitivity: 0, //设置为0无法旋转
                    zoomSensitivity: 0, //设置为0无法缩放
                    panSensitivity: 0, //设置为0无法平移
                    autoRotate: false //自动旋转
                },
                boxHeight: 5,
                // top: "-20%",
                // 后处理特效可以为画面添加高光、景深、环境光遮蔽(SSAO)、调色等效果。可以让整个画面更富有质感。
                postEffect: {
                    // 配置这项会出现锯齿,请自己去查看官方配置有办法解决
                    enable: false,
                    bloom: {
                        enable: true,
                        bloomIntensity: 0.1,
                    },
                    SSAO: {
                        enable: true,
                        quality: "medium",
                        radius: 2,
                    },
                    // temporalSuperSampling: {
                    //   enable: true,
                    // },
                },
            },
            series,
        };
        return option;
    }

    // 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
    function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
        // 计算
        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) * h * .1;
                }
                return Math.sin(v) > 0 ? 1 * h * .1 : -1;
            }
        };
    }

    function fomatFloat(num, n) {
        var f = parseFloat(num);
        if (isNaN(f)) {
            return false;
        }
        f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂
        var s = f.toString();
        var rs = s.indexOf('.');
        //判定如果是整数,增加小数点再补0
        if (rs < 0) {
            rs = s.length;
            s += '.';
        }
        while (s.length <= rs + n) {
            s += '0';
        }
        return s;
    }
}

。。。 持续更新

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值