图形编辑器:历史记录设计

这篇具有很好参考价值的文章主要介绍了图形编辑器:历史记录设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,我是前端西瓜哥。今天讲一下图形编辑器如何实现历史记录,做到撤销重做。

其实就是版本号的更替。每个版本保存一个状态。

数据结构

要记录图形编辑器的历史记录,支持撤销重做功能,需要两个栈:撤销(undo)栈和重做(redo)栈

每当用户进行一个操作(比如移动一个图形),就会产生一个新的版本,将这个操作产生的状态保持加入到 undo 栈顶,此外 redo 栈会清空。因为用户可能撤销了几次然后产生了新的操作,无法重做它们了。

当用户撤销,undo 栈出栈,并放到 redo 栈,然后使用 undo 栈顶的状态。当用户重做时,redo 栈出栈,再放到 undo 栈上,并应用 undo 栈顶的状态。

原理大概这样。

浏览器的回退前进的表现其实就是一个很常见的例子。

数据结构还有另一种方案:双向链表加两个指针,一个指针指向当前版本状态,另一个指针指向 redo 最后一次可执行到达的状态。

然后是如果要支持协同的场景,你的撤回不会回到之前的版本,而是将之前的版本的状态拿出来作为一个新的版本。

然后是协同中你不能撤回别人的操作,只能撤回自己的,并且要用协同算法处理和其他协同者的冲突逻辑。

要保存哪些状态

那么我们的状态要保存哪些状态呢?

  1. 图形树数据
  2. 图形树需要的引用
  3. 一些设置

图形树是必要的,我们需要用它渲染画布内容。此外还有游离在图形树之外的被用到的对象,比如图层、被多次引用的图形。你可以也把它们也放到图形树里面去。

最后是一些需要共享的设置,比如表格的行高、筛选条件等。

像是颜色主题、国际化语言设置则不需要历史记录,它是用户自己选择的个性化定制。

我们看具体的几种实现。

全量快照

每次操作的到的新状态,完全拷贝一份保存起来。

因为对象如果只是浅拷贝,其中的引用对象可能会被意外的修改,通常我们会选择 序列化成字符串 保存,即JSON.stringify。撤销重做的时候再解析出来作为当前状态。

优点是实现简单。

缺点是当状态很大的时候,每次生成快照都会比较耗时,且操作很多产生很多版本时,需要大量的内存空间保证这些完整状态。

如果画布上有一万个独立的实体,就意味着每进行一次操作,就要将这个一万个实体深拷贝一份。100 次就是 100w,很恐怖。

仅推荐简单的图形编辑器使用,或者做 demo 用。

补丁(patch)

全量快照让编辑器的上限很低,不是最优解。

一种更好的解法,是 打补丁(patch)。

基于上一个版本 1,打一个补丁,变成下一个版本 2。同时我们记录一个反向的补丁,撤回的时候能通过它从版本 2 回到版本 1。

这个方案对应了设计模式的 命令模式,我们构建 Command 类,这个类有 execute、redo、undo 方法,这些方法会对传入的旧的状态对象打补丁,得到一个新的状态。

比如添加矩形命令,execute 和 redo 时我们会往图形树的末尾加一个矩形对象,undo 就是将这个矩形从图形树中移除。undo 栈和 redo 栈此时记录的就是一个个 command 对象了。

图形编辑器:历史记录设计

纯纯用朴实无华的命令模式去实现,还是有点坑的。因为要实现的命令太多了,比如添加图形、修改图形属性、删除图形、对几个图形做右对齐等,这些都要自己一个个实现 redo 和 undo。复杂一点就要抓瞎,建议找一些轮子。比如 immer、y.js。

使用补丁方案还有一个好处,就方便实现 “动作” 功能。(当然这不是一个优先级很高的功能)

比如我们想要给一个图形先顺时针旋转 45 度,然后向右移动 10 个单位,我们希望记录这两个操作,给其他图形也应用这些操作。

快照的方式就不好搞,或许我们可以对比新旧状态找不同推断出行为,但不好搞。因为属性的变化可能来自不同的操作,比如移动,可以通过移动工具相对位移产生,也可能直接属性面板改 x 值,也可能是通过对齐操作产生的。

patch 就很适合。

什么时候保存状态

我们需要确认一个操作完成的时刻,将它加入到历史记录中。

我们操作图形,会产生一些 中间状态。比如移动一个图形,拖拽的过程中不生产一个历史版本,直到拖拽结束才记录。

一种方式是:操作图形的替身,操作结束后才更新真正的状态

一些编辑器,比如 Adobe Illustrator、AutoCAD,我们在操作图形的时候,会看到一个临时的替身,就是将被选中图形的轮廓线或拷贝做鼠标的跟随,释放后才真正修改图形属性。

还比如颜色的修改,在拾色器中挑选颜色时不会立即修改图形,在点击确认才真正修改图形。

图形编辑器:历史记录设计

另一种方式是:直接操作真正的状态,在操作结束的时候,记录这个时刻的状态。

图形编辑器:历史记录设计

第一种方式的好处是,状态没有中间状态,替身操作完,计算出新状态应用到真正的状态上就好了。

第二种方式就要额外在操作开始时,保存原始状态的快照,因为之后我们会产生中间状态,然后在操作结束后计算 patch。

但第二种方式用户体验会更好些,用户能实时看到一个图形的变化,判断是不是自己需要的效果,而不是看到一个 “通往未来的幻影”。

结尾

我是前端西瓜哥,关注我,学习前端不迷路。文章来源地址https://www.toymoban.com/news/detail-429480.html

到了这里,关于图形编辑器:历史记录设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#时间轴曲线图形编辑器开发1-基本功能

    目录 一、前言 1、简介 2、开发过程 3、工程下载链接 二、基本功能实现 1、绘图面板创建 (1)界面布置 (2)显示面板代码 (3) 面板水平方向、竖直方向移动功能实现 (4)面板放大、缩小、恢复正常显示功能实现 (5)鼠标当前位置坐标值和界面显示 (6)面板实现效果

    2024年02月15日
    浏览(30)
  • 图形编辑器开发:是否要像 Figma 一样上 wasm

    大家好,我是前端西瓜哥。 wasm 拿来做 Web 端的图形编辑器貌似是不错的选择。 因为图形处理会有相当多无法利用到 WebGL GPU 加速的 CPU 密集的计算。比如对一条复杂贝塞尔曲线进行三角化,对多个图形进行复杂图形的布尔运算。 图形编辑器性能天花板 Figma 用了 wasm,我们也

    2024年02月15日
    浏览(29)
  • 图形编辑器开发:最基础但却复杂的选择工具

    大家好,我是前端西瓜哥。 对于一个图形设计软件,它最基础的工具是什么? 选择工具 。 但这个选择工具,却是相当的复杂。这次我来和各位,细说细说选择工具的一些弯弯道道。 我正在开发的图形设计工具的: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/ap

    2024年02月09日
    浏览(55)
  • C#时间轴曲线图形编辑器开发2-核心功能实现

    目录 三、关键帧编辑 1、新建Winform工程 (1)界面布局  (2)全局变量 2、关键帧添加和删除 (1)鼠标在曲线上识别 (2)键盘按键按下捕捉 (3)关键帧添加、删除  (4)修改关键帧值 3、曲线插值 (1)三次样条插值 (2)工程代码下载链接 四、曲线数据导出和读取 1、数

    2024年02月15日
    浏览(32)
  • 记录使用注入的方式为Unity编辑器实现扩展能力

    使用场景 当前项目编辑器中不方便存放或者提交扩展代码 相同的扩展功能需要在多个项目(编辑器)中使用 项目开发中,偶尔临时需要使用一个功能,想随时使用随时卸载 设计思路 使用进程注入,将一个 c/c++ dll 注入到当前运行的unity编辑器中 使用 c/c++ dll 调用 mono 的函数接

    2024年02月15日
    浏览(40)
  • uniapp 微信小程序 editor富文本编辑器 api 使用记录

    这里记录一下自己研究学习的结果 之前一直使用textarea 来进行内容的编辑。但是局限性还是太多,最近发现了editor。觉得很不错 uniapp的官方说明 https://uniapp.dcloud.io/component/editor.html 这里有个例子,看起来很棒。但是自己使用起来的时候, 怎么也没有官方demo上面的工具栏 !

    2024年02月09日
    浏览(36)
  • 电力布局三维编辑器功能设计

    最近和一家公司在谈一个项目合作,他们公司主要是做电力相关的。 项目背景大概是这样的: 国家电网对电网资产需要做到数字化管理,对现有变压器台区内的电表箱电能表做可视化数字孪生管理。 由于涉及到的台区非常多,所以客户希望开发的不是单个项目,而是可以实现

    2023年04月22日
    浏览(31)
  • Vue + 富文本编辑器:打印模板设计

    前言: 有的项目需要用到打印,如果只有少数的地方需要用到打印,一般只需要固定模板进行打印就行了,但是我们的项目总是与众不同,明明只要固定模板就可以完成需求的,非要添加一个灵活的打印模板,而且还涉及到拖拉填充文本,真是脑细胞不知道死掉了多少! ! !

    2024年02月09日
    浏览(35)
  • 5个设计师都在用的在线网页设计编辑器!

    在当今的设计领域,选择一款适合的在线网页设计编辑器对于产设研团队来说至关重要。有许多选择可供考虑,其中包括即时设计、Axure RP、Adobe Illustrator、Sketch 和 Figma 等工具。在这些选择中, 即时设计 是一款备受推荐的在线网页设计编辑器。它不仅具备跨平台协同、免费

    2024年02月09日
    浏览(29)
  • 使用JavaScript实现实时在线协作编辑器:从设计到实现

    随着Web技术的发展,实现在线协作编辑文档已经成为一种常见的需求。通过在线协作,多位用户可以同时编辑同一个文档,并实时看到其他用户的更改。这样的功能需要复杂的技术实现,包括数据同步、冲突解决和实时通信。本篇博客将带您深入了解如何使用JavaScript实现实时

    2024年01月18日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包