前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简单介绍一下我在做的图形编辑器

简单介绍一下我在做的图形编辑器

作者头像
前端西瓜哥
发布2023-09-11 08:42:27
4030
发布2023-09-11 08:42:27
举报
文章被收录于专栏:前端西瓜哥的前端文章

我写的一系列图形编辑器的文章,是基于我一个叫做 suika 的个人项目总结抽象而来的。

毕竟不落地,我写的文章就不真实。当然落地了你去看代码,有些细节大概也不太能看懂,文章为了方便理解,是做了简化的,细枝末节都丢掉。

最近有人在研究我的个人项目的源码,看不懂,问我一些问题,问我有没有开发文档。

但是没有,因为项目还很简陋,可能还要做不少改动,要足够完善才会考虑写开发文档和介绍项目结构。

但我暂且在这里稍微 简单介绍一下这个项目

项目起源

suika 是我在持续开发的一款开源图形编辑器项目,基本上是模仿 Figma。

的初级功能。

编辑器 github 地址: https://github.com/F-star/suika 线上体验: https://blog.fstars.wang/app/suika/

当时做这个项目是为了 研究 figma 的底层是怎么设计和实现的。顺带一提,目前我主业也是做图形编辑器,但领域不一样,差别很大。

该项目创建于今年年初(准确来说是上年 12 月 28 日),陆陆续续加了一些功能,一直做到现在算是打了个还能用的毛胚

它其实是有前身的,那是我的另一个开源个人项目 svg editor,两三年前写的了,代码实现挺有问题的,很多东西没整明白。

这个 svg editor 是基于 SVG 的图形编辑器,产品行为上模仿 Adobe Illustrator。

主要是因为 SVG 性能不好,换成了 Canvas 方案,顺便产品形态对照行业头部 Figma。

技术栈

React + pnpm + TypeScript + Canvas 2D + husky。

TypeScript 是必须的,因为这是一个复杂项目,现在已经有点复杂了,以后会更复杂。随着功能变多,小重构是常态。

介绍一个小技巧,选中变量按 F2 改名字,项目中所有用到这个变量的地方都会被同步修改,实属重构变量名的利器,前提你得是 TypeScript 而不是 JavaScript。

编辑器内核使用 面向对象的风格。面向对象很重要,应用一些设计模式会很丝滑,比如模板模式,需要用到抽象类。

不要有单例,即在一个文件里直接声明一个对象,然后 export 出来。因为要考虑一个页面有多个编辑器的场景,两个编辑器公用一个对象会打架。

每加一个功能就要加一个类,虽然你将会看到一大堆的类,但真的很内聚,维护性很好。

UI 层倒没必要用面向对象,跟着主流走,也就是用 React 的函数组件搭配 Hook。

开始没做 monorepo,后面倒是做了 monorepo,但我并没有把项目的分层分到每个包里,只是创建了两个 React 组件相关的包,一个组件库,一个图标库。分包了但没完全分。

渲染方案

渲染方案选择了原生的 Canvas 2D。

没有使用流行的图形库,比如 pixijs、konva 这些,我只是简单封装了一些图形对象,比如 sence/rect,自己实现了一个图形场景树。

更新图形的时候,会遍历图形树,将所有图形 全量重绘,所以图形多的时候性能差。优化没做太多,只做了剔除的方案:视口外的图形不绘制。

目前更多心思花在架构上,渲染这方面也是一个大课题,精力问题,以后再说。

未来考虑换成 Canvaskit。Canvas 的易用性,搭配 wasm 的优秀性能,还是很香的。

图形拾取

图形拾取方案,是基于几何算法的。

为了提高效率,图形的点击区域只是图形的包围盒区域。这很不精细。

分层

所以分层没有体现在 packages 上,实际上它们全都在 @suika/suika 这个包里。

  1. 渲染底层技术用 Canvas 2D(未来考虑换成 Canvaskit),本身提供了易用性不错的 API(相比 WebGL)。
  2. 图形库简单封装,在 scene 目录里。
  3. 然后编辑器内核,管理所有的编辑器线管逻辑,对应 editor 文件夹。
  4. 最后是 UI 层在 components 文件夹。

模块

编辑器的模块(类)其实也不多,每个类对应一个功能,组织起来就能实现一个维护性很好的项目。

关于模块之间的关系,我画了个思维导图,会比较直观。

可以看上面的大图,也贴一个思维导图地址,不时更新。

https://f5b8b9lm1y.feishu.cn/mindnotes/DgJRb2GpGmdGdKnfl3rcJzw6n5e#mindmap

类要尽量符合单一职责原则,如果你发现一个类有点庞大了,就可以考虑做拆分。

比如选择工具类,因为子操作太多了,我就把它拆成移动图形类、绘制选区类、旋转图形类等等。

图标

编辑器的一些图标是用 Figma 绘制的,然后复制为 SVG,放到 icon 包的 Rect 组件里。

https://www.figma.com/file/g70i8aAv9qC51B948bDEj2/suika-editor-icons

计划

我并没有太多的规划,基本是拍脑子去做哪一个功能。

时常是做着做着发现太复杂,暂且搁置了。

一些比较复杂的功能还要去学习一些前置相关知识,研究竞品的交互逻辑,实现出来,然后写一篇文章,周期并不短。

话说可以做的功能很多,什么标尺线、滚动条、编组、贝塞尔曲线,我还挺纠结优先级的问题。

想来想去决定先做下面两个大功能:

  1. 编组
  2. 钢笔工具

关于写文

虽然我的图形编辑器相关的文章很短,但我写一篇文章花费的时间长啊。

图形编辑器相关的文章很慢,要学的东西太多了,同时需要花费精力在项目中落地,另外也会穿插一些图形编辑器具体实现 之外的文章,比如一些渲染引擎的底层实现,各位见谅。

目前文章还是单独成篇,不能很好地形成体系。我本打算写一个系列专栏的,但我发现我还是缺一些知识广度的,看来短期是出不了了,得好好去补补功课。

结尾

编辑器会持续开发下去,解锁更多新功能,未来可期,目前 star 也已经 95 了,欢迎 star。

相关阅读,

图形编辑器开发:最基础但却复杂的选择工具

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

图形编辑器开发:模块间如何通信?

图形编辑器:工具管理和切换

图形编辑器:底层设计

图形编辑器:防误操作之拖拽阻塞

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端西瓜哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目起源
  • 技术栈
  • 渲染方案
  • 图形拾取
  • 分层
  • 模块
  • 图标
  • 计划
  • 关于写文
  • 结尾
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档