图形编辑器在多个行业中扮演着至关重要的角色,其应用范围广泛且影响深远。
以 Figma 为典范的 Web 图形设计工具,为人们提供了一个自由发挥创造力的平台,随着 Web 平台的发展壮大,技术如 WebGL 和 WebGPU 的涌现与成熟,为传统的 OpenGL 图形编辑系统迁移到 Web 环境带来了新的可能性,极大地拓展了创新的边界。
开发一个图形编辑器是一个涉及多个层面的复杂工程任务,Graphix 的诞生来源于宝贵的 2d/3d 图形编辑器业务经历,期望 Graphix 能够为那些正在或即将着手开发图形编辑器的开发者提供一些微小的实质性帮助。
Graphix 是一个轻量级、可插拔、OOP 式图形编辑器开发引擎,旨在解决图形编辑器开发的基础架构设计问题。
名词 | 说明 |
---|---|
骨架(Skeleton) | Topbar,Toolbar,MainArea, LeftArea,RightArea |
插件(Plugin) | 通常用于扩展编辑器各面板展示 |
原型(Prototype) | 节点原型配置,用于描述编辑器不同类型图形节点的 视图、属性设置器、默认属性值等等 |
设置器(Setting) | 用于描述图形节点的属性如何配置 |
图形渲染引擎 | 用于中心区域的图形画布渲染,常见 2d/3d 渲染库:Three.js, Babylon.js,Antv 系列,D3 等等 |
Graphix 与图形渲染无关,可以根据场景使用任意需要的图形渲染引擎。
GraphView = GraphRender(GraphixModel)
Graphix 的设计来源于响应式数据驱动框架,确保模型的变化能够直接引导图形视图的渲染过程。简而言之,图形视图(GraphView)是由图形渲染器(GraphRender)根据 Graphix 模型的状态动态生成的。这种模型与渲染之间的绑定一旦确立,图形交互的逻辑就变得纯粹而高效——无需再涉足繁杂的渲染逻辑,只需专注于模型本身的操作。例如,要更新节点名称,开发者仅需调整 Graphix 节点的属性值即可。在这个协作环境中,即便是不熟悉图形渲染的开发者也能轻松参与。
其核心理念在于把复杂的图形渲染逻辑问题转化成简单的模型数据结构问题,从而围绕模型提供一套编辑器的基础架构设计方法。
Graphix 的编辑器模型是基于节点(node-based)构建的,无论是 2d 场景下的 节点/边,还是 3d 下的 Mesh 之类的 Object3D,在 Graphix 中统一都被抽象描述成一个节点,Graphix 节点的数据结构描述本身也很简单:Id,类型以及对应节点属性 Props 构成一个节点。
interface NodeData {
id?: string;
type: string;
props?: PropsData;
[key: string]: any;
}
当 node-based 这个设计基调确定之后,Graphix 模型层便可以提供很多基于节点的能力:
大多数编辑器的整体 UI 设计基本相同,都会有对应的 Topbar 顶部栏,Toolbar 工具栏,MainArea 中心画布 ,RightArea 右侧设置面板等等,Graphix Skeleton 视图是响应式可扩展的,可以通过 skeleton 单例添加需要扩展的面板。
import { skeleton } from 'graphix-engine';
skeleton.add({
area: 'topbar',
content: <div>一个很帅的标题</div>
});
插件的设计非常轻量化,插件的作用更多的是提供一种更好的组织代码的方式。当基于 Graphix 开发的编辑器产品本身需要面向 三方 提供扩展能力,那么使用插件去封装会很实用。
import { pluginRegistry } from 'graphix-engine';
pluginRegistry.register(() => {
return {
name: 'haha-plugin',
init() {
console.log('haha')
}
}
});
图形编辑器的本质就是通过可视化的方式编辑 JSON Schema Graphix 的默认 Schema 如下,可以根据业务场景转成需要的结构。
{
id: 'd94bc0d46131c',
type: 'Demo',
version: '1.0.0',
// 全局属性
props: {},
// 节点集合
nodes: [
{
id: '1',
type: 'mesh',
props: {
position: { x: -20, y: 0, z: 20 },
size: { width: 10, height: 10, depth: 10 },
},
},
],
}
Graphix 初始化启动的逻辑只有三步:
import { init } from 'graphix-engine';
init({
schema: {
id: 'd94bc0d46131c',
type: 'Demo',
version: '1.0.0',
// 全局属性
props: {},
// 节点集合
nodes: [
{
id: '1',
type: 'mesh',
props: {
position: { x: -20, y: 0, z: 20 },
size: { width: 10, height: 10, depth: 10 },
},
},
],
}
});
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8