找回密码
 立即注册

QQ登录

只需一步,快速开始

Richard.Huang SpreadJS 开发认证
超级版主   /  发表于:2023-12-29 11:19  /   查看:591  /  回复:0
本帖最后由 Richard.Huang 于 2024-1-3 15:39 编辑

背景
大家为了让数据可视化程度更高,往往会通过插入图表的方式来将数据可视化,在有些行业领域,例如房地产企业,他们对于楼盘数据往往会要求数据和图表中的数据形状一一对应,从而方便阅读者更加容易理解,如下图,我们会要求成交面积和前面的楼盘一一对应。
v2-d43045b673dd26927a1c98692a5bf0e8_b.jpg475270995.png

存在问题
但是我们发现,通过图表中的条状图实现的图表会存在和数据不对应的情况,例如上图中成交面积和成交套数后面几条数据和前面的楼盘完全错位了,因此为了能够完美对应,我们需要不停的去调整整个图表的大小,系列的大小。这个过程是费时费力的。因此为了避免这个问题,更好地解决办法是使用“横向条状迷你图”。但是该迷你图是没有label信息的,如果大家可以接受,那么完全可以使用原生的横向条状迷你图。如果还想精益求精,建议使用我们的“自定义迷你图”功能。在单元格内添加条状图的同时还在后面添加label

实现方法
1. 构建迷你图函数
  1. function Rectangle() {
  2.     spreadNS.Sparklines.SparklineEx.call(this);
  3. }
  4. Rectangle.prototype = new spreadNS.Sparklines.SparklineEx();
  5. Rectangle.prototype.createFunction = function () {
  6.     function RectangleFunction() {
  7.         this.name = "RECTANGLE";// 函数名
  8.         this.maxArgs = 2;// 参数最多2个
  9.         this.minArgs = 2;// 参数最少2个
  10.     }
  11.     RectangleFunction.prototype = new GC.Spread.CalcEngine.Functions.Function();

  12.     RectangleFunction.prototype.acceptsReference = function () {
  13.         return true;//函数的参数接受引用单元格区域
  14.     }

  15.     RectangleFunction.prototype.isContextSensitive = function () {
  16.         return true;
  17.     }

  18.     RectangleFunction.prototype.evaluate = function (arg) {
  19.         let arg1;
  20.         let arg2;
  21.         let result = 0;
  22.         if (!isNaN(parseInt(arg[1]))) {// 判断参数是引用范围还是一个给定的值
  23.             arg1 = arg[1];
  24.         } else {
  25.             arg1 = arg[1].getValueByIndex(0);
  26.         }

  27.         if (!isNaN(parseInt(arg[2]))) {
  28.             result = arg[2];
  29.         } else {
  30.             let sheet = arg[2].getSource();
  31.             let startRow = arg[2].getRow();
  32.             let startCol = arg[2].getColumn()
  33.             let rowCount = arg[2].getRowCount();
  34.             let colCount = arg[2].getColumnCount();
  35.             for (let i = startRow; i < startRow + rowCount; i++) {
  36.                 for (let j = startCol; j < startCol + colCount; j++) {
  37.                     result += sheet.getValue(i, j);
  38.                 }
  39.             }
  40.         }
  41.         arg2 = arg1 / result;

  42.         return {
  43.             arg1,
  44.             arg2
  45.         };
  46.     };
  47.     return new RectangleFunction();
  48. };
  49. Rectangle.prototype._drawRect = function (context, value, x, y, width, height) {
  50.     var rectX = x;
  51.     var rectY = y + height * 0.1;// 矩形上下留空隙更加美观
  52.     var rectWidth = width;
  53.     var rectHeight = height * 0.8;
  54.     var backgroundColor = '#3498db';// 矩形背景色
  55.     context.fillStyle = backgroundColor;
  56.     context.fillRect(rectX, rectY, rectWidth, rectHeight);// 画矩形

  57.     // 设置文本的属性
  58.     var textColor = '#000000'; // 文本颜色
  59.     var fontSize = '13px'; // 字体大小
  60.     var fontFamily = 'Arial'; // 字体
  61.     var text = "空"
  62.     if (value) {
  63.         text = value.toString(); // 长方形宽度转换为字符串表示
  64.     }
  65.     // 设置文本样式
  66.     context.fillStyle = textColor;
  67.     context.font = fontSize + ' ' + fontFamily;
  68.     // 计算文本的x和y位置,确保文本显示在长方形右侧
  69.     var textX = rectX + rectWidth + 10; // 在长方形的宽度后留出一点间隔
  70.     var textY = (2 * rectY + rectHeight) / 2 - 5; // 文本与长方形垂直居中
  71.     context.textBaseline = "top";
  72.     context.textAlign = "left"
  73.     // 画文本
  74.     context.fillText(text, textX, textY);
  75. };

  76. Rectangle.prototype.paint = function (context, value, x, y, width, height) {
  77.     context.save();
  78.     this._drawRect(context, value.arg1, x, y, width * value.arg2, height);
  79.     context.restore();
  80. };
复制代码
2. 注册自定义迷你图函数
  1. spread.addSparklineEx(new Rectangle());
复制代码

实现效果
132ade59-6e4c-4d73-8441-e7e6dfb410d8.png843741454.png
而对于使用者来说,更加方便,只需要和插入普通公式一样,在单元格中通过自定义的迷你图函数即可实现,而不用插入图表调整图标大小形状等
ad3156e9-4edc-4e03-a210-fd5a5a49f9aa.png959847717.png

0 个回复

您需要登录后才可以回帖 登录 | 立即注册
返回顶部