基于 OpenHarmony 鸿蒙开发的表格渲染引擎

2022-06-15 08:11:14 浏览数 (1)

OpenHarmonySheet

基于 Canvas 实现的高性能 Excel 表格引擎组件 OpenHarmonySheet。

由于大部分前端项目渲染层是使用框架根据排版模型树结构逐层渲染的,整棵渲染树也是与排版模型树一一对应。因此,整个渲染的节点也非常多。项目较大时,性能会受到较大的影响。

为了提升渲染性能,提供更优质的编辑体验从 DOM 更换成 Canvas 渲染,方便开发者构建重前端大型在线文档项目,在国内外实现类似引擎的公司仅仅只有几家,如:腾讯文档,金山文档和谷歌文档等。

在项目中引入 <Sheet></Sheet> 组件即可,使用方法如下:

代码语言:javascript复制
<element name="Sheet" src="../../components/index.hml"></element>

<Sheet
  sheet="{{sheet}}"
  @sheet-show="sheetShow"
  @sheet-hide="sheetHide"
  @click-cell-start="clickCellStart"
  @click-cell-end="clickCellEnd"
  @click-cell-longpress="clickCellLongpress"
  @change="change"
></Sheet>

生命周期和事件

  • sheet 表格数据
  • @sheet-show 表格显示
  • @sheet-hide 表格隐藏
  • @click-cell-start 单元格点击前
  • @click-cell-end 单元格点击后
  • @click-cell-longpress 长按表格
  • @change 修改单元格数据

比如,我们在示例中可以监听 长按 事件,当用户 长按 的时候弹出 对话框,示例代码如下:

代码语言:javascript复制
clickCellLongpress(evt) {
    prompt.showDialog({
        buttons: [{
            text: '测试',
            color: '#666666',
        }],
    });
}

以上所有的接口都会返回一个详细的 sheet 对象,里面含有以下信息:

  • el 表格的节点
  • textarea 单元格输入框节点
  • viewport 单元格高亮选框
  • table 单元格操作对象
代码语言:javascript复制
sheetShow(sheet) {
    this.el = sheet.detail.el;
    this.textarea = sheet.detail.textarea;
    this.viewport = sheet.detail.viewport;
    this.table = sheet.detail.table;
}

API 接口

渲染引擎封装好了常用的表格数据操作等接口。

  • this.table.xxx

用于帮助你操作单元格的所有数据和格式,也极大方便你自定义一个功能完整的工具栏:

  • this.viewport.xxx

用于帮助你操作单元格上层的高亮选框。

  • this.textarea.xxx

this.textarea 是对鸿蒙的原生 <textarea> 组件的封装接口,用于帮助你接受用户在界面中的输入,然后配合 this.table.xx 将数据层的数据渲染到表格渲染层,这里的输入需要真机调试,因为真机有自带输入法,实测 Previewer 无效。

初始化表格渲染层

代码语言:javascript复制
import Table from "./sheet/";
this.el = this.$refs.canvas;
this.table = Table.create(this.el, 850, 800).render();

初始化选区层

viewport 用于创建和控制单元格高亮选框,绘制在单元格上层,输入框下层,支持列选择,行选择和范围选择。

代码语言:javascript复制
this.viewport = new Viewport(this.table).render();

初始化表格数据

在任何情况,你都可以使用 .cell 方法全局更新任一位置的数据。

代码语言:javascript复制
this.table.cell((ri, ci) => `${ri}-${ci}`).render();

合并单元格

在表格中这是一个常用的方法,我们可以打碎局部单元格做合并操作。

代码语言:javascript复制
this.table.merges(["G9:H11", "B9:D11"]).render();

设置列表行头

可以设置你的列表行头和其高度。

代码语言:javascript复制
this.table.colHeader({ height: 50, rows: 2 }).render();

冻结区域

某些情况,我们在查阅表格的时候,我们可能需要固定某些行和某些列的单元格来提高表格阅读性,此时 .freeze 就可以派上用场。

代码语言:javascript复制
this.table.freeze("C6").render();

滚动区域

一般配合冻结区域使用,让冻结区域以外的选区可以做滚动操作。

代码语言:javascript复制
this.table.scrollRows(2).scrollCols(1).render();

设置选区

非特殊情况你不需要花费时间去操作单元格选框,正常情况选框接受你单元格的相对位置来绘制。

代码语言:javascript复制
const range = this.viewport.range(
  evt.changedTouches[0].localX,
  evt.changedTouches[0].localY
);
this.table.selection(range);
this.viewport.render(this.table.$draw);

单元格,行和列接口

单元格,行和列表格结构如下:

col 列

col 列

row 行

cell 单元格

cell 单元格

row 行

cell 单元格

cell 单元格

我们可以使用以下方法更新单元格第二行第二列的数据为 8848,颜色为红色:

代码语言:javascript复制
this.table
  .cell((ri, ci) => {
    if (ri === 2 && ci === 2) {
      return {
        text: "8848",
        style: {
          color: "red",
        },
      };
    }
    return this.sheet?.[ri]?.[ci] || "";
  })
  .render();

当然你可以精心定制每一个单元格的数据,这些数据可以来自于你的后端服务器,也可以来自于客户端的输入,配合客户端和服务端的存储能力,将数据持久化保存。

代码语言:javascript复制
this.sheet = [
  ["


	

0 人点赞