立体柱状 堆叠图 可点击图例切换!

先看图!  

 点击图例之后  如下图所示 :

两个、三个、四个堆叠都可如此.......

用vue + echarts 做

上代码!!!

get3dEchartsData(){

      const _this = this;

      let backArr = [];       // 背景色数据

      let yMax = 100;         // 遍历data找到最大值赋予特殊符号

      let data = [];          // 柱状图所有数据平坦化

      var barWidth = 29;      // 柱体宽度

      var serierData = [];

      let lengedData = [];    // 图例颜色

      let sumData = [];       // 求和数据

      let xAxisData = [];     // X轴数据

      let topData = [];       // 顶盖数据(位置)

      this.titleArr.forEach((e, i) => {

        // 阶梯求和 用于立体图绘制

        if (i === 0) {

          sumData.push(

            this.initData[i][e.indicatorName]?.map((m, n) => m.value || "")

          );

        } else {

          let arr = this.initData[i][e.indicatorName]?.map((m, n) => {

            return Number(m.value || 0) + Number(sumData[i - 1][n] || 0);

          });

          sumData.push(arr);

        }

        lengedData.push({

          icon: "rect",

          name: e.indicatorName,

          itemStyle: {

            color: e.color,

          },

        });

        // 处理y轴数据 使用求和后数据计算y轴最大值

        sumData.forEach((e) => {

          e?.forEach((c) => {

            data.push(c);

          });

        });

        xAxisData = this.initData[i][e.indicatorName]?.map((e) => {

          return e.statisticsTime;

        });

        topData = this.initData[i][e.indicatorName]?.map((e, num) => {

          if (e.value !== "") {

            return sumData[i][num];

          } else {

            return "";

          }

        });

        let bottomData = this.initData[i][e.indicatorName]?.map((e, num) => {

          if (e.value !== "") {

            if (i > 0) {

              return sumData[i - 1][num] || 0;

            } else {

              return 0;

            }

          } else {

            return "";

          }

        });

        serierData.push(        

          // 三面数据

          {

            z: i + 1,

            name: e.indicatorName || "",

            stack: "stack",

            type: "bar",

            barWidth: barWidth,

            data: this.initData[i][e.indicatorName],

            itemStyle: {

              normal: {

                color: {

                  type: "linear",

                  x: 0,

                  x2: 1,

                  y: 0,

                  y2: 0,

                  colorStops: [

                    { offset: 0, color: this.colorArr[i][e.indicatorName][0] },

                    {

                      offset: 0.5,

                      color: this.colorArr[i][e.indicatorName][1],

                    },

                    {

                      offset: 0.5,

                      color: this.colorArr[i][e.indicatorName][2],

                    },

                    { offset: 1, color: this.colorArr[i][e.indicatorName][3] },

                  ],

                },

              },

            },

          },

          {

            z: 4 + i,

            type: "pictorialBar",

            symbolPosition: "end",

            data: topData,

            symbol: "diamond",

            symbolOffset: ["0%", "-50%"],

            symbolSize: [barWidth, barWidth * 0.5],

            itemStyle: {

              normal: {

                color: this.colorArr[i][e.indicatorName][2],

              },

            },

            tooltip: {

              show: false,

            },

          },

          {

            z: 3 + i,

            type: "pictorialBar",

            symbolPosition: "end",

            data: bottomData,

            symbol: "diamond",

            symbolOffset: ["0%", "-50%"],

            symbolSize: [barWidth, barWidth * 0.5],

            itemStyle: {

              normal: {

                color: {

                  type: "linear",

                  x: 0,

                  x2: 1,

                  y: 0,

                  y2: 0,

                  colorStops: [

                    { offset: 0, color: this.colorArr[i][e.indicatorName][0] },

                    {

                      offset: 0.5,

                      color: this.colorArr[i][e.indicatorName][1],

                    },

                    {

                      offset: 0.5,

                      color: this.colorArr[i][e.indicatorName][2],

                    },

                    { offset: 1, color: this.colorArr[i][e.indicatorName][3] },

                  ],

                },

              },

            },

            tooltip: {

              show: false,

            },

          }

        );

      });

      // 计算数据(展示数据)最大值

      var maxVal = Math.max.apply(Math, data);

      if (maxVal < 1) {

        // 最大值小于1 设置阴影1

        yMax = 1;

      } else if (maxVal < 10) {

        // 最大值小于10 设置阴影10

        yMax = 10;

      } else if (maxVal < 50) {

        // 最大值小于50 设置阴影50

        yMax = 50;

      } else if (maxVal < 100) {

        // 最大值小于100 设置阴影100

        yMax = 100;

      } else {

        // 最大值大于100 按前两位数+1取整计算阴影

        let maxvalue = Number(`${Math.ceil(maxVal)}`.slice(0, 2)) + 1;

        let i = `${Math.ceil(maxVal)}`.length - 2;

        for (let e = 0; e < i; e++) {

          maxvalue = maxvalue * 10;

        }

        yMax = maxvalue;

      }

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

        backArr.push(yMax);

      }

      function showGrid() {

        let object = {

          left: "2%", //图表距边框的距离

          right: "2%",

          top: "10%",

          bottom: _this.isrotate ? "15px" : "40px",

          containLabel: true,

        };

        return object;

      }

      function showLegend() {

        let object = {

          selectedMode: true,

          bottom: "0",

          data: lengedData,

          itemWidth: 10,

          itemHeight: 10,

        };

        return object;

      }

      // 追加最上方累加数据

      serierData.push({

        z: 1,

        name: "",

        type: "bar",

        stack: "",

        barGap: "-100%", // 左移100%,stack不再与上面两个在一列

        barWidth: 29,

        label: {

          normal: {

            show: true,

            distance: 10,

            position: "top", //  位置设为top

            textStyle: { color: "#000" },

            formatter: function (item) {

              if (item.value) {

                return item.value;

              } else {

                return "";

              }

            },

          },

        },

        tooltip: {

          show: false,

        },

        itemStyle: {

          normal: {

            color: "rgba(128, 128, 128, 0)", // 仍为透明

          },

        },

        data: sumData[sumData.length - 1]?.map((e) => {

          return e ? e.toFixed(2) : e;

        }),

      });

      //  柱体背影数据

      //  serierData.push({

      //   name: "",

      //   type: "bar",

      //   stack: "data",

      //   data: backArr,

      //   barWidth: 30,

      //   itemStyle: {

      //     normal: {

      //       color: "#376DDB",

      //       opacity: 0.1,

      //       label: {

      //         show: false,

      //       },

      //     },

      //   },

      //   label: {

      //     show: false,

      //   },

      // });

      return {

        tooltip: {

          trigger: "axis",

          backgroundColor: "rgba(0,0,0,0.55)",

          boxShadow: "3px 3px 9px 0px rgba(106,106,106,0.3)",

          backdropFilter: "blur(4px)",

          borderWidth: 0,

          className: "tooltips-box",

          textStyle: {

            fontSize: "12",

            color: "#ffffff",

          },

          axisPointer: {

            type: "shadow",

            shadowStyle: {

              opacity: 0,

            },

          },

          // 鼠标悬浮显示的数据样式

          formatter: function (params) {

            var str = params[0].data.statisticsTime;

            // 排序

            let seriesIndex = params.sort((a, b) => a.seriesIndex - b.seriesIndex );

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

              str += `

                <div style="display: flex; justify-content: space-between">

                <div style=" margin-right: 12px">

                  <span style="display:inline-block;margin-right:4px;width:10px;height:10px;border:1px solid #FFFFFF;background-color:${

                    params[i]?.color?.colorStops?.[0]?.color

                  }"></span>

                   ${params?.[i]?.seriesName}

                </div>

               <div>${

                 params[i]?.value != ""

                   ? handleQfNumberStr(params[i]?.value, 2)

                   : "--"

               } ${_this.indicatorUnit}</div>

               </div>`;

            }

            return str;

          },

        },

        legend: showLegend(),

        grid: showGrid(),

        xAxis: {

          axisLine: {

            show: false, //不显示坐标轴轴线

          },

          axisTick: {

            show: false, //不显示坐标轴刻度

          },

          data: xAxisData,

          axisLabel: {

            show: true,

            interval: 0,

            color: "#232323",

            margin: _this.isrotate ? 30 : 25,

            rotate: _this.isrotate ? 30 : 0, //横坐标是否倾斜

            align: "center",

          },

          type: "category",

        },

        yAxis: {

          max: yMax,

          interval: yMax / 5,

          axisTick: {

            show: false,

          },

          axisLine: {

            show: false,

          },

          axisLabel: {

            show: true,

          },

        },

        series: serierData,

      };

}

代码里面重点关注 serierData的加参数、sumData的计算逻辑

  setOption() 配置项的第二个参数  可以自己百度查一下什么意思

------------------------------------------------------------------------------------------------------

最关键的代码来了!!!

 给echarts 实例绑定图例点击事件、每次点击都要修改initData 的数据

注意的是copy_data 是页面第一次传值过来时 initData的备份数据,一定不能漏掉

大致意思就是,

被点击的图例对应的数据会进行置空,反之则赋原来最开始的值

(这就是copy_data的作用!!!)

最后,传进来的值,initData,titleArr,colorArr 都有严格的数据格式要求(这个可以各位大佬再细细研究)

例如我上面图例所示的数据格式就是:

initData:[

{ 研究分仓业务收:[value:123,statisticsTime:202301]},

{ 研究服务现金收入:[value:123,statisticsTime:202301]}

]        

其中:value 是柱体数据,statisticsTime 是X轴的数据

--------------------------------------------------------------

titleArr:[

{indicatorName:研究分仓业务收,color:''},

{indicatorName:研究服务现金收入,color:''}

]

titleArr是图例信息,其中:中文名字要和initData完全匹配,color 代表图例的颜色

--------------------------------------------------------------

colorArr:[

        {研究分仓业务收:['颜色1','颜色2','颜色3','颜色4']},

        {研究服务现金收入:['颜色1','颜色2','颜色3','颜色4']}

]

colorArr 是柱状体的颜色  顶盖 下盖 和柱体

这个立体效果是通过颜色差来呈现立体效果的  并不是真正的3D效果

注意的是,中文和数组的顺序都要一一对应  

--------------------------------------------------------------

以上数据之所以用中文进行一一匹配,是因为点击图例那个方法  参数中只有图例信息和图例状态

(其实不用中文一一匹配,用数字或者其他东西也可以,我懒得换了)

大概就这样  研究了一段时间     就封装好了这个公共组件..........

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好!关于echarts立体柱状堆叠和折线的使用,您可以按照以下步骤进行操作: 1. 首先,确保您已经引入了echarts库。可以通过在HTML文件中添加如下代码来引入: ``` <script src="https://cdn.jsdelivr.net/npm/echarts@5.2.0/dist/echarts.min.js"></script> ``` 2. 创建一个具有一定宽度和高度的DOM容器,用于展示表。例如: ``` <div id="chart" style="width: 600px; height: 400px;"></div> ``` 3. 使用JavaScript代码初始化表,并配置数据和表样式。以下是一个简单的示例: ```javascript // 初始化表 var chart = echarts.init(document.getElementById('chart')); // 配置数据 var data = { categories: ['类别1', '类别2', '类别3', '类别4'], seriesData1: [120, 200, 150, 80], seriesData2: [80, 120, 100, 60], seriesData3: [60, 80, 70, 50], lineData: [50, 60, 80, 70] }; // 配置表样式 var option = { tooltip: {}, legend: { data: ['系列1', '系列2', '系列3', '折线'] }, xAxis: { data: data.categories }, yAxis: {}, series: [ { name: '系列1', type: 'bar', stack: '堆叠', data: data.seriesData1 }, { name: '系列2', type: 'bar', stack: '堆叠', data: data.seriesData2 }, { name: '系列3', type: 'bar', stack: '堆叠', data: data.seriesData3 }, { name: '折线', type: 'line', data: data.lineData } ] }; // 渲染表 chart.setOption(option); ``` 以上代码示例创建了一个包含立体柱状堆叠和折线echarts表。您可以根据自己的数据和需求进行配置和调整。 希望能对您有所帮助!如果还有其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值