【AntV】canvas表格s2完全封装手册

前言

由于我们业务中有很多地方需要有纵向复制,刷选等操作,一般的传统表格并不支持。

目前支持度较好的葡萄城表格与handsontable都需要收费,而s2作为一款轻量级开源表单较为符合我们的需求,但是由于s2仍然不够成熟,有非常多的功能需要自定义。

我在公司对s2做了大量封装,对里面代码基本上算比较熟悉了。本篇结合我们业务中的需求,带大家看看s2可以做到什么地步,需要进行怎样的改动。

引入方式与注意点

传统引入方式就是npm与umd的这里就不说了,值得说一下的就是模块联邦引入。

正常情况使用模块联邦打包share出去
【AntV】canvas表格s2完全封装手册_第1张图片

需要引入的项目里同样需要配上share,否则全局变量部分就会有问题,如果s2的表格的hover效果刷选效果全都消失可能是这个原因导致的(我们遇到2个项目出现这问题,加上就好)。

s2前置知识

官网:https://s2.antv.antgroup.com/

对于完全没接触过s2的同学来说,有些概念需要先了解下,便于后面更快地对s2进行改造。

s2表格从大类上分明细表与透视表,其他表都是2个表的延伸:

【AntV】canvas表格s2完全封装手册_第2张图片

透视表比明细表多了角头与行头,它只有列头与数据。

一般业务需求基本都是明细表,只有少部分需求会用到多维表。多维表的行头可以转换成树结构,可以做要求较低的树状表格。

s2是基于图引擎g做的,目前2版本使用的是4版本的g:https://g.antv.vision/zh/docs/guide/introduce

如果需要对单元格等进行自定义,一般会需要使用g进行绘制。

s2的自定义扩展基本都是需要继承之前的类。比如列头就要继承colCell,单元格就要继承DataCell。所以你需要改什么就去继承重写就可以了。

比如下面这个例子就是全部改写单元格(datacell)的效果:
【AntV】canvas表格s2完全封装手册_第3张图片

主题修改

我觉得官网文档上主题修改讲的挺详细的了,就是修改themeCfg

默认色板可以通过getPalette获取,如果只想改主题色,换掉brandColor即可。

const palette = getPalette("default");
const color = generatePalette({
   
	...palette,
	brandColor: "#ff6f00",
});

直接看官网这部分即可https://s2.antv.antgroup.com/zh/examples/theme/custom/#custom-manual-palette

由于s2-react使用了antd4做组件,所以当你改了颜色后,antd的主题色最好也需要更改,否则会比较突兀:

@import "~antd/es/style/themes/default.less";
@import "~antd/dist/antd.less"; 
@primary-color: #ff6f00; // 全局主色
@link-color: #ff6f00; // 链接色

导入less换变量即可。如果编译报错,可以开启lessOption:

{
   
        loader: "less-loader",
        options: {
   
                lessOptions: {
   
                        javascriptEnabled: true,
                },
        },
},

svgIcon

s2的svg引入稍微有点坑,所以这里抽出来写一下。

一般我们使用的icon需要注册到headerActionIcons中进行使用。s2会将你配置的图标以及名称放到全局变量上,等需要的时候拿取。

在列头行头等地方需要拿取icon时,s2有个icon类会去修改fill(如果使用网络图片就不会受影响),具体代码是这么写的:

/**
 * 使用 iconfont 上的 svg 来创建 Icon
 */
export class GuiIcon extends Group {
   
  static type = '__GUI_ICON__';

  // icon 对应的 GImage 对象
  public iconImageShape: Shape.Image;

  constructor(cfg: GuiIconCfg) {
   
    super(cfg);
    this.render();
  }

  // 获取 Image 实例,使用缓存,以避免滚动时因重复的 new Image() 耗时导致的闪烁问题
  /* 异步获取 image 实例 */
  public getImage(
    name: string,
    cacheKey: string,
    fill?: string,
  ): Promise<HTMLImageElement> {
   
    return new Promise<HTMLImageElement>((resolve, reject): void => {
   
      let svg = getIcon(name);
      if (!svg) {
   
        return;
      }

      const img = new Image();
      img.onload = () => {
   
        ImageCache[cacheKey] = img;
        resolve(img);
      };
      img.onerror = reject;

      // 兼容三种情况
      // 1、base 64
      // 2、svg本地文件(兼容老方式,可以改颜色)
      // 3、线上支持的图片地址
      if (svg.includes(SVG_CONTENT_TYPE) || this.isOnlineLink(svg)) {
   
        img.src = svg;
      } else {
   
        // 传入 svg 字符串(支持颜色fill)
        if (fill) {
   
          // 如果有fill,移除原来的 fill
          // 这里有一个潜在的问题,不同的svg里面的schema不尽相同,导致这个正则考虑不全
          // 1、fill='' 2、fill 3、fill-***(不需要处理)
          // eslint-disable-next-line no-useless-escape
          svg = svg.replace(/fill=[\'\"]#?\w+[\'\"]/g, ''); // 移除 fill="red|#fff"
          svg = svg.replace(/fill>/g, '>'); // fill> 替换为 >
        }
        svg = svg.replace(
          STYLE_PLACEHOLDER,
          `${
     STYLE_PLACEHOLDER} fill="${
     fill}"`,
        );
        // 兼容 Firefox: https://github.com/antvis/S2/issues/1571 https://stackoverflow.com/questions/30733607/svg-data-image-not-working-as-a-background-image-in-a-pseudo-element/30733736#30733736
        // https://www.chromestatus.com/features/5656049583390720
        img.src = `${
     SVG_CONTENT_TYPE};utf-8,${
     encodeURIComponent(svg)}`;
      }
    });
  }

  /**
   * 1. https://xxx.svg
   * 2. http://xxx.svg
   * 3. //xxx.svg
   */
  public isOnlineLink = (src: string) => {
   
    return /^(https?:)?(\/\/)/.test(src);
  };

  private render() {
   
    const {
    name, fill } = this.cfg;
    const attrs = clone(this.cfg);
    const imageShapeAttrs: ShapeAttrs = {
   
      ...omit(attrs, 'fill'),
      type: GuiIcon.type,
    

你可能感兴趣的:(javascript,前端)