首页 > 其他分享 >开源图片编辑器的插件化架构

开源图片编辑器的插件化架构

时间:2024-08-10 14:54:07浏览次数:12  
标签:插件 开源 快捷键 编辑器 API editor 右键

大家好,我是开源图片编辑器的作者,在开发图片编辑器的过程中,因为一些功能无法扩展,出现过一次较大的重构,将整个编辑器改为了插件化的架构,经历过这次重构,规范了编辑器功能的扩展方式,解决了项目里很多重要的问题。

如果你也在做类似的项目,或者对图片编辑器架构比较感兴趣,希望我的经验能给你一点点参考。

大纲

  1. 项目介绍
  2. 为什么要做插件化
  3. 如何实现插件化
  4. 如何开发一个插件

项目介绍

项目中文名称是快图设计,英文名称为技术栈拼接的:vue-fabric-editor,使用 Vue3 + Fabric.js 开发的开源图片编辑器。

Fabric.js 是业界知名的Canvas工具库,它已经12岁了,在业界得到了广泛的应用和认可,可用于开发图片编辑、物联网组态、平面设计工具等场景。

本文以介绍插件架构开发经验为主题,不对Fabric.js 做过多介绍。

项目特点

  1. 插件化架构:可通过插件的形式进行扩展,定义快捷键、右键菜单、复用的API/Event。
  2. 简洁易用:拖拽式设计,让普通人轻松上手操作。
  3. 功能完善:PSD解析、辅助线、历史记录、渐变、自定义字体、裁剪等功能,满足轻量图片编辑需求。

可应用于自媒体/海报设计、平面设计、PPT、价签设计等场景,以下为项目的实际应用截图。






为什么要做插件化

项目最初使用vue2 + Fabric.js 开发,通过使用Vue2的 Provide/Inject 的 API方法,将Fabric.js 的 canvas对象注入到各个子组件当中。

看起来好像组件各司其职,也符合满足单一职责原则,实际上隐藏着很大的问题。

问题说明

如果要实现以下 2 个功能:

  1. 画布功能需要在导入源文件时储存画布尺寸变量,需要尺寸修改的 API 方法,其他组件可订阅尺寸修改事件。
  2. 自定义字体功能需要初始化时生成字体引用的 CSS 代码,需要在导入源文件前获取到所有使用的字体名称,并进行加载,加载完成后再进行源文件的的渲染。

在没有扩展规范的情况下,很有可能出现的情况是:

  1. 导入逻辑出现过多业务处理代码。
  2. 多个组件的订阅事件出现相互依赖。

一个功能的代码散落在各个组件中,扩展功能无规范,很多逻辑相互缠绕。

如果按照硬编码的方式实现,那么组件将会错综复杂,相互紧密耦合,修改一个微小功能都要梳理众多组件的影响范围。

根本原因

图片编辑器不同于Canvas库,需要有自己的生命周期Hook方法、API复用方法、事件订阅、快捷键/右键菜单绑定等功能,编辑器需要有明确的扩展规范

Fabric.js是一个典型的 Canvas库,不满足也不应该处理这些需求,需要有一个原则来明确定义Canvas库与图片编辑器的关系

如何实现插件化

要实现插件化,需要先明确关系与扩展规范,最后再按照设计去实现功能即可。

抽象分层

要解决扩展规范的问题,首先要明确编辑器与 Canvas 库的关系,用汽车来类比。

  • Canvas库为引擎:有很强的驱动能力,是汽车的核心,就像Fabric.js有很完善的绘制图像能力,是编辑器的核心。
  • Editor编辑器为底盘:围绕引擎在为汽车行驶提供更多功能和接口,比如方向盘驱动、轮子、减震、钥匙启动等,就像图片编辑器必要的辅助线、历史记录、右键菜单、快捷键等。
  • UI 框架为车壳:React/Vue + UI 组件就像车壳,只需要调用底盘提供的功能接口即可完成驱动。

这样的分层关系,能够让我们在开发时,更清晰的拆分功能应该放在哪里更合适,绘制能力给 Fabric.js,集成复用能力给底盘,而不是将所有逻辑一股脑的塞在组件里。

扩展规范

通过对历史逻辑的梳理,对编辑器做扩展需要生命周期Hook、API挂载、事件订阅、右键菜单扩展、快捷键绑定,一个编辑器的扩展功能应该内聚在一个文件中,而插件化架构更为合适,扩展规范也就明晰了。

  1. 生命周期
    • 导入前
    • 导入后
    • 保存前
    • 保存后
  2. 挂载 API
  3. 事件订阅
  4. 右键菜单扩展
  5. 快捷键绑定

引用插件:

  const canvas = new fabric.Canvas('canvas');
  // 编辑器初始化
  canvasEditor.init(canvas);
  // 引用插件
  canvasEditor.use(DringPlugin, { repoSrc: 'https://api.kuaitu.cc' });

插件化实现

接下来终于进入编码的环节,已经有很多成熟的库可以满足我们的功能需求,以下是我们用到的依赖库。

1. Editor对象

负责编辑器、插件、Hook的初始化,监听右键菜单并渲染所有插件内的menu方法,监听快捷键方法并所有插件内的绑定事件,主要逻辑见截图,详细实现逻辑见代码:
https://github.com/ikuaitu/vue-fabric-editor/blob/main/packages/core/Editor.ts


2. 主流程插件

ServersPlugin与其他插件不同,是作为主流程插件存在,与Editor对象同等重要,提供了Hook的顺序控制和基础API。

Hook控制:
https://github.com/ikuaitu/vue-fabric-editor/blob/main/packages/core/ServersPlugin.ts

3. 其他插件

编辑器其他插件可按需单独引入,统一放置在 plugin目录下:
https://github.com/ikuaitu/vue-fabric-editor/tree/main/packages/core/plugin

以上就是插件化的主要实现思路,具体细节逻辑可参见源码。

如何开发一个插件

插件以类的形式初始化,采用声明式编程的方式对外部暴露 API、事件、快捷键,所有需要使用的 API、事件、快捷键都需要在apis、events、hotkeys里声明。

Hook方法直接在插件内部按规范命名即可:

  • hookImportBefore
  • hookImportAfter
  • hookSaveBefore
  • hookSaveAfter

右键菜单可根据选中的元素类型进行判断,可增加分割线、二级菜单嵌套。

快捷键的扩展可根据点击事件的 keyCode、up/down 绑定对应的方法即可。

插件代码实例:

import Editor from './Editor';
type IEditor = Editor;

class FontPlugin {
  public canvas: fabric.Canvas;
  public editor: IEditor;
  // 插件名称
  static pluginName = 'FontPlugin';
  // 挂载API名称
  static apis = ['downFontByJSON'];
  // 发布事件
  static events = ['textEvent1', 'textEvent2'];
  // 快捷键 keyCode hotkeys-js
  public hotkeys: string[] = ['backspace', 'space'];
  // 私有属性
  repoSrc: string;

  constructor(canvas: fabric.Canvas, editor: IEditor, config: { repoSrc: string }) {
    // 初始化
    this.canvas = canvas;
    this.editor = editor;
    // 可插入外部配置
    this.repoSrc = config.repoSrc;
  }

  // 钩子函数 hookImportAfter/hookSaveBefore/hookSaveAfter Promise
  hookImportBefore(json: string) {
    return this.downFontByJSON(json);
  }

  // 挂载API方法
  downFontByJSON() {
    //
  }

  // 私有方法 + 发布事件
  _createFontCSS() {
    const params = [];
    this.editor.emit('textEvent1', params);
  }

  // 右键菜单
  contextMenu() {
    const selectedMode = this.editor.getSelectMode();
    if (selectedMode === SelectMode.ONE) {
      return [
        null, // 分割线
        {
          text: '翻转',
          hotkey: '❯',
          subitems: [
            {
              text: t('flip.x'),
              hotkey: '|',
              onclick: () => this.flip('X'),
            },
            {
              text: t('flip.y'),
              hotkey: '-',
              onclick: () => this.flip('Y'),
            },
          ],
        },
      ];
    }
  }

  // 快捷键
  hotkeyEvent(eventName: string, { type }: KeyboardEvent) {
    // eventName:hotkeys中的属性 backspace、space
    // type:keyUp keyDown
    // code:hotkeys-js Code
    if (eventName === 'backspace' && type === 'keydown') {
      this.del();
    }
  }

  // 注销
  destroy() {
    console.log('pluginDestroy');
  }
}

export default FontPlugin;

总结

开头简单介绍了项目及应用场景,重点说明图片编辑器不同于Canvas库,需要有自己的生命周期Hook方法、API复用方法、事件订阅、快捷键/右键菜单绑定等功能,硬编码会导致代码复杂度增高,编辑器需要有明确的扩展规范

之后用汽车的引擎、底盘、车壳来类比图片编辑的 Canvas库、Editor、UI 框架之间的关系,并梳理出一个插件需要的Hook/API/Event/右键菜单/快捷键扩展能力,并将插件化实现思路代码做了展示,最后展示了插件 API 的用法,并提供了示例。

以上就是开源图片编辑器vue-fabric-editor项目的插件化架构实现,笔记多有疏漏,还望见谅,分享出来希望能够给大家一些参考,如果有收获希望,大家帮忙点赞收藏,评论区一起交流。

如果你对这个开源项目感兴趣,欢迎你能加入我们一起维护。

标签:插件,开源,快捷键,编辑器,API,editor,右键
From: https://www.cnblogs.com/nihaojob/p/18352282

相关文章

  • Github 2024-08-10开源项目日报 Top10
    根据GithubTrendings的统计,今日(2024-08-10统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下:开发语言项目数量Python项目4JavaScript项目2TypeScript项目2C#项目1Dockerfile项目1RichTextFormat项目1Swift项目1Jupyt......
  • 『SD』Stable Diffusion WebUI 安装插件(以汉化为例)
    前言本文简介StableDiffusionWebUI是允许用户自行安装插件的,插件的种类有很多,有将页面翻译成中文的插件,也有提示词补全插件,也有精细控制出图的插件。以汉化为例,StableDiffusionWebUI默认是英文的,我们只需装个汉化插件然后重启一下项目就能把页面变成中文了。安装......
  • 开源的一键AI去除视频水印和字幕!
    【大华轻创】大家好,我是大华!我们做网创的,多多少少会去下载很多视频素材,但很多素材自己觉得非常好,但有那该死的水印和字幕就让人非常不爽,要么在剪辑的时候放大把字幕拉出屏幕外,又或者是用黑框该掉字幕,这着实影响美观!有什么办法可以直接去掉字幕和水印吗?答案是有的!今天就......
  • 谷粒商城实战笔记-145-性能压测-性能监控-jvisualvm使用-解决插件不能安装
    文章目录jvisualvm的作用安装查看gc相关信息的插件解决jvisualvm不能正常安装插件的问题1,查看java版本2,打开网址3,修改jvisualvm的设置jvisualvm的作用JVisualVM是一个集成在JavaDevelopmentKit(JDK)中的多功能工具,它提供了一种可视化的方式来监控和分析Java应用......
  • 《开源大模型食用指南》发布,7个小时,一杯奶茶速通大模型!
    前言《开源大模型食用指南》是一个围绕开源大模型、针对国内初学者、基于AutoDL平台的中国宝宝专属大模型教程,针对各类开源大模型提供包括环境配置、本地部署、高效微调等技能在内的全流程指导,简化开源大模型的部署、使用和应用流程,**让更多的普通学生、研究者更好地使......
  • Cacti安装插件之thold
    Cacti安装插件之thold 基本环境os:rhel5.5i386rpm:lampcacti:0.8.8arrdtool:1.4.5 1,安装settings插件#wgethttp://docs.cacti.net/_media/plugin:settings-v0.7-1.tgz#mvplugin\:settings-v0.7-1.tgzsettings-v0.7-1.tgz#tar zxvfsettings-v0.7-1.tgz-......
  • Git和GitHub:开启你的开源之旅(入门级干货教程)
    Git及GitHub使用教程Git部分Git概述Git是一个免费的开源的分布式版本控制系统。版本控制系统版本控制系统是一种记录文件历史修改记录,以便将来查阅特定版本修订情况的系统。集中式版本控制工具VS分布式版本控制工具集中式版本控制工具:特点:所有文件版本和历史......
  • 【VSCode】《VSCode安装本地历史记录插件并配置搜索忽略》
    前言VSCode本地会记录修改和保存的历史文件信息,当没有使用git管理的时候,就可以通过本地历史搜索快速比对还原历史代码。插件安装目前最新版本停留在1.8.1更新时间为2020/3/4号;估计作者后续也没有更新计划了。安装后会在左下角和左上角出现LOCALHISTORY和./history两个......
  • Qwen2-Math 开源 AI 模型发布;阿里云推出首个域名 AI 大模型应用丨 RTE 开发者日报
       开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(Real-TimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但......
  • UEDITOR编辑器+粘贴WORD
    昨天晚上有一个网友给我发私信,也是遇到了word内容复制粘贴的问题,想了解一下这块的技术,看看有没有好的解决方法,或者代码,或者插件,主要是想交流一下技术问题。这位老哥说他也是第一次接触这个,也是刚开始学习,很多基础知识都不太熟悉,首先花了半个小时左右的时间给他讲解了一下基础知......