你不知道的 Canvas 表格交互

背景

S2 是 AntV 在多维交叉分析表格领域的解决方案,主要用于看数分析, S2 采用 canvas 来进行表格绘制 (基于 易用、高效、强大的 2D 可视化渲染引擎 G ) , 同时内置大量的交互能力来辅助用户看数, 如 行列联动高亮 单选/多选高亮 刷选高亮 行高列宽动态调整 列头隐藏 等, 同时还支持 自定义交互, 本文主要介绍 S2 是如何实现这些交互的。

DOM 交互和 Canvas 交互的区别

以单元格点击为例, 得益于强大的 CSS3选择器, 我们可以准确的监听任意 dom 元素的点击事件

<ul class="cell">
  <li id="cell1">我是第一个单元格</li>
  <li id="cell2">我是第二个单元格</li>
</ul>
const cell = document.querySelector('.cell > li:first-child');

cell.addEventListener('click', () => {
  console.log('第一个单元格: 别点我!');
})

但是 canvas 就只有一个 <canvas/> dom 元素

<canvas />

如何准确的知道点击的是哪个单元格呢? 答案是 事件委托+ 鼠标坐标

const canvas = document.querySelector('canvas');

canvas.addEventListener('click', () => {
  console.log('我点的是哪个单元格?');
})

在 dom 中, 有一个很经典的事件冒泡应用场景, 那就是 事件委托, 还是以上面的例子, 我们可以只监听父级的 ul元素, 根据当前的 event.target 来判断当前点击的是哪一个单元格

const cell = document.querySelector('.cell');

cell.addEventListener('click', (event) => {
  const CELL_ID = 'cell1'
  if (event.target?.id === CELL_ID) {
    console.log('我是第一个单元格');
  }
});

所以在 canvas中, 我们也可以依葫芦画瓢, 不同点是, 单元格不再是一个个的 dom 节点, 而是一个个 canvas 图形 对应的数据结构, 类似于虚拟dom

const cell = new Shape({ type: 'rect' })
public getCell<T extends S2CellType = S2CellType>(event): T {
  let parent = event.target;
  // 判断当前 target 属于哪一个实例
  while (parent && !(parent instanceof Canvas)) {
    if (parent instanceof BaseCell) {
      // 在单元格中,返回true
      return parent as T;
    }
    parent = parent.get?.('parent');
  }
  return null;
}

// antv/g 提供的 Canvas 构造器
const canvas = new Canvas()

canvas.on('click', (event) => {
  const cell = this.getCell(event)
})

事件分类

通过事件委托, 能够获取到具体触发事件的单元格 ( 具体实现 )

  • 角头单元格点击: S2Event.CORNER_CELL_CLICK
  • 列头单元格点击: S2Event.COL_CELL_CLICK
  • 行头单元格点击: S2Event.ROW_CELL_CLICK
  • 数据单元格点击: S2Event.DATA_CELL_CLICK
  • 单元格双击
  • 单元格右键
  • ...

在监听到对应事件后, 通过内部的 event emitter 分发出去, 从而触发对应的单元格事件

 private onCanvasMousedown = (event: CanvasEvent) => {
    const cellType = this.spreadsheet.getCellType(event.target);
    switch (cellType) {
      case CellTypes.DATA_CELL:
        this.spreadsheet.emit(S2Event.DATA_CELL_MOUSE_DOWN, event);
        break;
      case CellTypes.ROW_CELL:
        this.spreadsheet.emit(S2Event.ROW_CELL_MOUSE_DOWN, event);
        break;
      case CellTypes.COL_CELL:
        this.spreadsheet.emit(S2Event.COL_CELL_MOUSE_DOWN, event);
        break;
      case CellTypes.CORNER_CELL:
        this.spreadsheet.emit(S2Event.CORNER_CELL_MOUSE_DOWN, event);
        break;
      case CellTypes.MERGED_CELL:
        this.spreadsheet.emit(S2Event.MERGED_CELLS_MOUSE_DOWN, event);
        break;
      default:
        break;
    }
  };

this.spreadsheet.on(S2event.DATA_CELL_MOUSE_DOWN, (event) => {
  console.log('数值单元格点击')
})

交互分类

有了分好类的单元格事件, 我们就可以将其排列组合。 比如刷选高亮, 就对应 数值单元格的 mousedown+ mousemove+ mouseup 事件, 再将获取到的单元格 meta 信息存储在状态机, 最后根据交互状态进行 canvas 重绘

交互类型

名称

适用场景

全选

ALL_SELECTED

复制

选中

SELECTED

单选/多选/行列批量选中

未选中

UNSELECTED</

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity-UGUI是Unity游戏引擎中的一个UI系统,可以用来创建和管理用户界面。它提供了丰富的功能和工具,使得开发者能够轻松地制作各种表格。 使用Unity-UGUI制作表格的步骤如下: 1. 创建Canvas对象:在Unity中,首先需要创建一个Canvas对象,作为UI渲染的容器。选择GameObject -> UI -> Canvas,即可创建一个Canvas对象。 2. 添加Table组件:选择Canvas对象,在Inspector面板中点击"Add Component"按钮,然后在搜索栏中输入"Table",选择适合的Table组件,点击添加。 3. 设置表格的行列数:在Table组件的Inspector面板中,设置表格所需的行数和列数。 4. 设置表格样式:可以在Inspector面板中设置表格的颜色、大小等属性,以满足具体需求。 5. 添加表格内容:可以通过代码或者拖拽方式,向表格中添加所需的文本或图片。可以通过操作表格的行列索引,将内容放置在特定的位置。 6. 设置表格交互性:可以为表格中的每个单元格添加点击事件或其他交互效果,提升用户体验。 7. 调整表格布局:可以通过调整Canvas的大小、位置,或者改变组件之间的层次关系,来调整表格的布局。 8. 完善表格功能:可以根据具体需求,添加更多表格的功能,比如排序、过滤、搜索等。 9. 测试和优化:在表格制作完成后,可以进行测试,查看表格的显示效果和交互效果,并进行优化。 总之,使用Unity-UGUI制作表格,只需简单的操作和设置,就能够创建出各种样式、功能丰富的表格,满足游戏或应用程序的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值