当前位置:网站首页>在线文档Sheet技术解析
在线文档Sheet技术解析
2022-08-02 17:33:00 【LVMING】
开源项目simple-sheet,各位读者感兴趣可以一起参与进来!
什么是在线文档
一般来说,我们在PC端使用的微软Excel即是一个很强大的本地文档软件,而所谓“在线”,就是把这些功能移植到浏览器端,当然也包括移动web,小程序,Android或者iOS应用中,和本地最大的不同是在线文档除了基本的文档编辑操作之外,还加入了“协同”功能,能够同时多人编辑,这也就更能体现出在线文档的优势。 目前来说,比较流行的在线文档包括了Google Doc,钉钉文档,飞书文档,腾讯文档以及石墨文档等等,这些文档包括了Word,Excel,PPT等常用的模块,本文主要就Excel模块即Sheet文档进行技术解析。
协同
正如上文所述,协同是在线文档的一大特色,其主要功能场景如下:
多个用户在浏览器同时访问一个网页链接,并且可以实时同步到多方的修改内容。 每个用户都可以对自己的修改进行保存,并且分享给任何人编辑和查看。 可以看到用户每次修改的历史记录。
为了实现这些功能场景,就需要解决以下的技术问题:
实时通信问题:目前比较流行的方案是WebSocket,借助于WebSocket的长连接特性,可以实时将本地一些较为频繁的改动同步到后端,同时广播给其他正在编辑的用户。 冲突处理问题:一个比较直接的解决方案是-编辑锁,即当超过1用户在编辑同一个文件时,另外一个用户无法编辑,但这并不是一个很好的解决方案,所以针对于Sheet文档而言,当多个用户编辑同一个文件时,可能会修改到同一个单元格的内容,样式等,这时就会产生冲突问题。
处理冲突问题,常用的算法是OT算法,全称是Operation Transformation,是在线协作系统中经常使用的操作合并算法。其核心是一种操作合并指导思想,在不同的应用场景下有不同实现,这里不过多解释,感兴趣的同学可以看下ot.js。关于协同这块,由于涉及到很多WebSocket和后端的交互,我们主要讲一下纯前端的在线编辑交互这块。
在线编辑
对于Sheet文档的在线编辑,可以看作是一个传统的前端单页应用,其包括了较为复杂的DOM交互,鼠标事件交互,样式,滚动处理等等,一般来说会采用纯DOM或者DOM和Canvas并配合Vue,React结合数据状态管理库Redux或者Vue来实现。
以DOM+Canvas+React+Redux为例子,其主要实现思路如下:
每个单元格,可称为单个对象Cell,其主要属性包括了:内容,位置,长宽,样式等等,如下代码所示:
export type CellAttrs = {
x: number // x坐标
y: number // y坐标
width: number // 宽度
height: number // 高度度
value?: string // 值
ownKey: string // key
fill?: string // 背景颜色
borderStyle?: BorderStyle // 边框属性
fontWeight?: string | boolean // 加粗
textColor?: string // 字体颜色
verticalAlign?: string // 垂直居中
align?: string // 水平居中
fontFamily?: string // 字体
fontSize?: number // 字号
fontItalic?: string | boolean // 斜体
textDecoration?: string | boolean // 下划线
...
}
对于单个Sheet文档来说,包括了若干个Cell,并将这些Cell存储在Redux中进行管理。 通过事件交互,修改单元格的属性会通过Redux同步到对应绑定的DOM中。 不同的操作会有自己独立的层,这些操作改动最终会落到最底层的Canvas层单元格上面。
其页面结构如下图所示:
这些层,除了Canvas之外,一般设为pointer-events:none
并且z-index
高于Canvas。
Canvas层
首先,使用Canvas一般是来渲染最底层的单元格,相对于DOM来实现,主要有以下好处:
对于单个Sheet来说,一般会有上百个Cell,每个Cell会有单独的属性,采用DOM会占用内存会比Canvas稍大,在体验上会卡顿一些。 Canvas对于不同浏览器来说,其行为和表现较为统一(字体,颜色,形状等等),会减少一定的兼容性问题。 对于Sheet来说,如果需要一些导出或者转换成图片之类的功能,可以采用Canvas原生的API实现,较为方便。
借助react-konva库,可以很方便的将React组件和Canvas结合起来,实现最原子的Cell操作。
Dom选择区域层
这层主要实现的鼠标选择交互相关的UI展示,如下所示蓝色区域:
其包括了选择区域(透明蓝色背景)和当前激活单元格Cell(实现蓝色框)两部分,相关技术点主要有:
结合Canvas点击时获取的坐标,设置当前激活Cell的位置和样式。 结合鼠标mouseup,mousemove,mousedown事件和Canvas坐标,动态绘制选择区域的位置和样式。 在选择区域的同时,结合Redux里面的Cell数据,方便获取到Cell列表原数据。
Dom编辑器层
这层主要包括的是双击单个Cell单元格时,实时渲染出编辑器的逻辑,如下图所示:
简单来说,由一个文本输入框<textarea>
实现,相关技术点主要有:
结合Canvas点击时获取的坐标,设置编辑器的位置和样式。 <textarea>
输入文字时,需要实时修改其width
和height
,来适配不同内容的展示。除了 <textarea>
之外,还可以有<select>
,<datepicker>
等等复杂的编辑器。
Dom滚动条层
这层主要目的是为了模拟出Canvas的真实宽度和高度,从而通过overflow:auto
来模拟出滚动条及其相关交互,从而使Canvas看起来是可以滚动的,其原理如下图:
其他层
这些层主要包括了一些其他逻辑,主要有:
插入浮动图片层。 右键菜单层。 工具栏层。 其他...
合并单元格
合并单元格相对于原子的修改Cell属性操作会比较复杂一些,这里可以将合并单元格看作是一个样式加属性调整的操作,相关技术点主要有:
所选区域的单元格进行合并时,保留区域右下角的Cell属性,其他单元格样式置空,包括边框,使其成为完全没有样式的Cell。 修改右下角单元格大小为所选区域大小,并绑定上左上角和右下角的key值,这样当点击时就可以确定合并的区域。 将上面绑定的key值复制给区域内其他没有样式的Cell,这样当点击任一Cell时,都可以确定合并的区域。
key值的属性,如下所示:
export type CellAttrs = {
...
isMerge:[first:key,last:key] // 左上角和右下角的坐标key
}
修改Cell大小
由于修改列或者行的Cell的大小会影响之后的所有Cell位置,所以这是一个很消耗性能的操作,在mousemove
时,可以采用节流_.throttle
函数来减少一些高频操作,或者直接在mouseup
的那一刻去做修改操作。
总结
对于Sheet文档来说,最重要的技术点还是对Cell数据的操作,如何管理好Cell,使其变换出不同的效果和样式是实现好Sheet功能的关键,而React以及Redux和Canvas则是提供了数据->界面
的工具。快开始你的在线文档之旅吧。
我准备了一个开源项目simple-sheet,各位读者感兴趣可以一起参与进来!
边栏推荐
- 图解LeetCode——622. 设计循环队列(难度:中等)
- Security First: Tools You Need to Know to Implement DevSecOps Best Practices
- npm install 时,卡住不动,五种解决方法
- ES: Promise的基本用法
- golang源码分析(12)martini源码分析
- 年轻人接棒大妈,金价跌回“4字头”,七夕迎黄金消费小热潮
- MySQL常见面试题汇总(建议收藏!!!)
- H5网页播放器EasyPlayer.js播放器界面的加载效果无法消失是什么原因?
- golang 计算器实现
- Several common cross-domain solutions
猜你喜欢
LeetCode·76.最小覆盖子串·滑动窗口
Mysql——字符串函数
golang学习之七:并发编程基础(goroutine、channel、select)
The days of patching are more difficult than the days of writing code
潮玩的“第二春”,在哪?
攻防世界-favorite_number
Wechat Gymnasium Appointment Mini Program Graduation Design Finished Works (7) Mid-term Inspection Report
织梦自定义表单添加全选和全不选功能按钮
灵动微电子发布低功耗 MM32L0130 系列 MCU 产品
npm install报gyp info it worked if it ends with ok
随机推荐
Mysql开启binlog
Local broadcast MSE fragments mp4 service
一些与开发者体验有关的话题
一朵“云“如何带来产业新变革
玩转云端 | 天翼云对象存储ZOS高可用的关键技术揭秘
golang源码阅读(11)GO中各个目录的功能
ES: export 的用法
golang源码分析(13)gorpc源码分析
发挥云网融合优势,天翼云为政企铺设数字化转型跑道
小程序毕设作品之微信体育馆预约小程序毕业设计成品(5)任务书
npm install报错Fix the upstream dependency conflict, or retry
Smart Contract Security - delegatecall (1)
MySQL常见函数
故障分析 | 一条 SELECT 语句跑崩了 MySQL ,怎么回事?
[300+ selected big factory interview questions continue to share] Big data operation and maintenance sharp knife interview questions column (10)
方法的使用
Flink SQL builds real-time data warehouse DWD layer
NeRF:火爆科研圈的三维重建技术大揭秘
Since September, China has granted zero-tariff treatment to 98% of tax items from 16 countries including Togo
罗敏背后是抖音