首页 > 其他分享 >金子塔图,自定义图表,伪漏斗图

金子塔图,自定义图表,伪漏斗图

时间:2023-01-10 10:55:22浏览次数:59  
标签:塔图 index resultOption 自定义 item triangleHeightLayerOne let 漏斗 slanted

金子塔图,自定义图表,伪漏斗图

简易的金字塔图,设置不太灵活,可供使用者参考,需要使用者根据页面的需求复杂度等再做修改。

另附链接地址:https://www.isqqw.com/pcenter?userid=6427

// 原始数据
let data = [
   { name: '测试数据', value: 4 },
   { name: '测试原理', value: 2 },
   { name: '测试功能', value: 8 },
]
// 将数据根据从小到大排序
let newdata = sortObject(data);
// 图例数据
let lengthData = [];
// 返回数据
let resultData = data.map((item, index) => {
   let graw = item.value > 9 ? 78 : 83;
   lengthData.push({
      type: 'group',
      top: index * 25,
      scale: [1, 1],
      children: [
         {
            type: 'circle',
            shape: {
               cx: 0,
               cy: 7,
               r: 5
            },
            style: {
               fill:
                  index === 0 ? '#07a9ab' : index === 1 ? '#008CD2' : '#0847e7'
            }
         },
         {
            type: 'text',
            style: {
               text: item.name,
               fill: '#fff',
               fontSize: 14,
               x: 10,
               y: 2
            }
         },
         {
            type: 'text',
            name: item.name,
            style: {
               text: item.value,
               fill: '#fff',
               fontSize: 17,
               x: 70,
               y: 0
            }
         },
         {
            type: 'text',
            style: {
               text: '个',
               fill: '#fff',
               fontSize: 14,
               x: graw,
               y: 2
            }
         }
      ]
   });
   if (index === 0) {
      return {
         style: {
            fill: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
               { offset: 0, color: '#07a9ab' },
               { offset: 1, color: '#09fffb' }
            ])
         },
         ...item
      };
   } else if (index === 1) {
      return {
         style: {
            fill: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
               { offset: 0, color: '#025279' },
               { offset: 1, color: '#16a7ef' }
            ])
         },
         ...item
      };
   } else {
      return {
         style: {
            fill: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
               { offset: 0, color: '#0332a9' },
               { offset: 1, color: '#0847e7' }
            ])
         },
         ...item
      };
   }
});
// 获取计算的数据
let getData = pyramidChart(
   resultData,
   document.getElementById('container')
);
option = {
   backgroundColor: '#022c32',
   graphic: [
      {
         type: 'group',
         left: '5%',
         top: 'center',
         scale: [1, 1],
         onclick: function (params) {

         },
         children: getData
      },
      {
         type: 'group',
         left: '55%',
         top: 'center',
         scale: [1, 1],
         onclick: function (params) {

         },
         children: lengthData
      }
   ],
   series: []
};
// 排序
function sortObject(arr) {
   return arr.sort(function (a, b) {
      return a['value'] - b['value'];
   });
}
// 数据处理
function pyramidChart(data = [], dom, option = {}) {
   let domHeight = dom ? dom.clientHeight : 0;
   let domWidth = dom ? dom.clientWidth : 0;
   // 默认获取一个正方形空间
   let maxDistance = domHeight > domWidth / 2 ? domWidth / 2 : domHeight;
   // 合并设置
   let resultOption = Object.assign(
      {
         slanted: 1, // 每层底部的倾斜度
         maxWidth: maxDistance, // 金字塔最大宽度
         maxHeight: maxDistance, // 金字塔最大高度
         offset: 35 //偏差
      },
      option
   );
   if (data.length === 1) {
      resultOption.slanted = 50;
   }
   if (data.length === 2) {
      resultOption.slanted = 25;
   }
   if (data.length === 3) {
      resultOption.slanted = 10;
   }
   // 减去多余的误差边距
   resultOption.maxHeight = resultOption.maxHeight - resultOption.offset;
   // 一半最大宽度,用于计算左右边距
   let halfMaxWidth = resultOption.maxWidth / 2;
   // 数据最终
   let resultData = [];
   // 数据值 数组
   let dataNums = data.map(item => item.value || 0);
   // 计算数据总和
   let dataNumSum =
      dataNums.length > 0 &&
      dataNums.reduce(function (prev, curr) {
         return Number(prev || 0) + Number(curr || 0);
      });
   // 中间数据点坐标数组 根据长度比值算出
   let midlinePoint = [];
   let multipleLayer = [0.6];
   // 计算倍数等基础数据
   dataNums.forEach((item, index, arr) => {
      let itemNext = arr[index + 1];
      if (itemNext) {
         multipleLayer.push(itemNext / dataNums[0]); // 计算倍数
      }
      // 计算点坐标 长度
      let point =
         Math.round((item / dataNumSum) * resultOption.maxHeight * 1000) / 1000;
      midlinePoint.push(point);
   });
   // 三角形的高度
   let triangleHeight = 0;
   let triangleHeightLayer = [];
   // 三角形tan角度
   let triangleRatio = halfMaxWidth / resultOption.maxHeight;
   midlinePoint.forEach(item => {
      triangleHeight = triangleHeight + item;
      triangleHeightLayer.push(triangleHeight);
   });
   // 中间数据点 最后的数据长度
   let midlinePointFinally =
      triangleHeightLayer[triangleHeightLayer.length - 1] || 0;
   // 开始拼接数据
   data.forEach((item, index) => {
      let arrObj = [];
      let triangleHeightLayerOne = triangleHeightLayer[index];
      let triangleHeightLayerOneLast = triangleHeightLayer[index - 1] || 0;
      let multipleLayerOne = multipleLayer[index];
      let multipleLayerOneLast = multipleLayer[index - 1] || 0;
      // 第一层数据单独处理
      if (index === 0) {
         arrObj.push(
            [0, 0],
            [
               -triangleRatio *
               (triangleHeightLayerOne - resultOption.slanted * multipleLayerOne),
               triangleHeightLayerOne - resultOption.slanted * multipleLayerOne
            ],
            [0, triangleHeightLayerOne],
            [
               triangleRatio *
               (triangleHeightLayerOne - resultOption.slanted * multipleLayerOne),
               triangleHeightLayerOne - resultOption.slanted * multipleLayerOne
            ]
         );
      } else {
         arrObj.push(
            [0, triangleHeightLayerOneLast],
            [
               -triangleRatio *
               (triangleHeightLayerOneLast -
                  resultOption.slanted * multipleLayerOneLast),
               triangleHeightLayerOneLast -
               resultOption.slanted * multipleLayerOneLast
            ],
            [
               -triangleRatio *
               (triangleHeightLayerOne - resultOption.slanted * multipleLayerOne),
               triangleHeightLayerOne - resultOption.slanted * multipleLayerOne
            ],
            [0, triangleHeightLayerOne],
            [
               triangleRatio *
               (triangleHeightLayerOne - resultOption.slanted * multipleLayerOne),
               triangleHeightLayerOne - resultOption.slanted * multipleLayerOne
            ],
            [
               triangleRatio *
               (triangleHeightLayerOneLast -
                  resultOption.slanted * multipleLayerOneLast),
               triangleHeightLayerOneLast -
               resultOption.slanted * multipleLayerOneLast
            ]
         );
      }
      resultData.push({
         type: 'polygon',
         z: 1,
         shape: {
            points: arrObj
         },
         name: item.name,
         style: item.style
      });
   });
   // 添加线
   resultData.push({
      type: 'polyline',
      shape: {
         points: [
            [0, 0],
            [0, midlinePointFinally]
         ]
      },
      style: {
         stroke: '#f2f2f2',
         opacity: 0.2,
         lineWidth: 1
      },
      z: 2
   });
   // 返回
   return resultData;
};

  

 

标签:塔图,index,resultOption,自定义,item,triangleHeightLayerOne,let,漏斗,slanted
From: https://www.cnblogs.com/wangyongping/p/17039499.html

相关文章

  • es自定义分词,拼音分词、手机号分词
    一、需求描述本文针对在工作中遇到的需求:通过es来实现模糊查询来进行总结;模糊查询的具体需求是:查询基金/A股/港股等金融数据,要求可以根据字段,拼音首字母,部分拼音全称进行......
  • Vue + Element 自定义上传封面组件
    前一段时间做项目,频繁使用到上传图片组件,而且只上传一个封面,于是想着自定义一个图片封面上传组件。先来看一下效果:            第一张图片是上传......
  • C++核心知识回顾(自定义数据类型)
    复习C++类自定义数据类型最灵活的方式就是使用C++的类结构现在定义一个货币类型Currency:enumsignType{PLUS,MINUS};classCurrency{public:Currency(signTy......
  • DRF之过滤,排序,自定义异常和分页
    DRF数据的过滤参考网址https://www.cnblogs.com/songhaixing/p/14687072.htmldrf内置的过滤组件SearchFilter###modelsclassBookInfo(models.Model):ti......
  • 实现自定义 Spring AOP 注解
    实现自定义SpringAOP注解翻译原文链接ImplementingaCustomSpringAOPAnnotation1.介绍在本文中,我们将使用Spring中的AOP支持来实现自定义AOP注解。Int......
  • NoneBot2聊天机器人自定义聊天内容
    1、按照上一篇文章所介绍的方法新建一个机器人,进入所对应的文件夹,会发现里面有一个和自己所创建的机器人名称一样的文件夹   2、进入该文件夹,会发现一个名叫plugins......
  • 当你自定义一个删除的delete方法时,不加事务注解,报错
    报错:cannotreliablyprocess'remove'call要用的注解:@Modifying@TransactionalintdeleteUserByUserName(Stringusername); 参考:jpa报错:NoEntityM......
  • 39、商品服务--品牌管理--JSR303自定义校验注解
    假若SpringMvc提供的校验注解不能满足我们的要求,我们就自己写一个1、编写一个自定义校验注解(即编写一个注解类--Annotation类)参考其他的注解,来编写我们自己的注解我......
  • 图文并茂strapi 4.5.5自定义搭建指南以及数据库字段名接口返回mapping分析
    strapi是什么?基于Nodejs的开源免费CMS框架为什么选择它?基于nodejs,100%JavaScript,上手迅速可轻松创建功能强大且可自定义的API可以使用任何喜欢的数据库先决条件首......
  • 4.2JS中自定义对象
    ​ JS中自定义对象JS除了一些常用方法和类以外,允许我们自己定义对象,在JS中自定义对象有三种可用的语法格式,分别为:1调用系统的构造函数创建对象2自定义构造函数创......