一、项目概述

二、项目架构

三、几何计算难点

四、鼠标事件处理

五、数据保存与导出

六、文本处理

二、项目架构

2.1 系统架构

项目系统架构如下图所示:

  1. UI元素即HTML DOM元素。项目打开时,画面虽然是一片空白的,但实际上UI元素并不空白。一些可复用不需动态创建的元素可预先定义好。例如选择框、对齐线等,出现的时候它们只是位置发生了改变,不需动态创建,可预先定义好,节省开销。

  2. UI元素使用ID标注(Vue里使用ref),然后注册到UI管理器中。后面对UI管理器中相应的对象进行修改时,UI元素就会发生改变。

  3. 对UI元素的所有操作,例如动一下鼠标、点一下按钮、按一下键盘,所有的这些事件都会交给事件处理器处理。事件处理器包括鼠标事件、基本编辑事件、画布事件、图元属性改变事件、分组操作事件、锁定操作事件、层次操作事件等。

  4. 事件处理器不会对UI直接产生作用,它们会调用各种管理器去完成任务。每种元素都会有一个管理器,包括画布、光标、历史记录、整图、选择、状态、选框、文字、变换等。

  5. 管理器中会使用到一些比较复杂的操作或计算,这些功能由工具类提供。例如几何计算、思维导图位置计算、path数据生成等。

  6. 管理器最后会对UI管理器进行操作,达到改变UI的最终效果。

以下,我们以鼠标点击一个矩形为例,说明框架的运行细节。

  1. HTML中定义了一个选择框,包括一个虚线矩形和八个实线小矩形。

  2. 上述图元注册到UI管理器中。

  3. 当鼠标点击矩形时,触发了MouseDown事件,这个事件会调用鼠标事件处理器。

  4. 鼠标事件处理器利用目标工具类,判断当前鼠标点击了什么目标。

  5. 鼠标事件处理器利用状态管理器获取当前状态,继而改变当前状态。

  6. 鼠标事件处理器利用光标管理器修改当前光标。

  7. 鼠标事件处理器利用选框管理器,显示选择框。

  8. 选框管理器调用UI管理器中注册的元素,把选择框显示出来。

2.2 图元数据定义

图元数据描述是本项目开发的一个难点。图元数据的特点包括:

(1)图元种类众多,每种图元有自己独特的属性。

(2)某些种类的图元存在公共的属性。例如矩形、图片的位置都是通过一个矩形来描述的。

(3)管理器对图元有共同的操作。例如把图片数据转化为可视HTML,鼠标拖动时的平移动作等。这些操作在图元内部的实现并不一致。

(4)图元存在一些即使而不需要保存的属性,例如是否选中,这是一个不需要保存,每次打开时都有默认值的属性。

在本项目中,图元具有以下的数据定义:

class Component {public id: string = "";public type: ComponentType = "rect";public props: { [key: string]: string } = {};public connectAnchors: Array<AnchorDirPos> = [];
}

这就是图元的基类。可以看到,属性是相当少的。在这里,需要说明几种跟TypeScript语法相关的设计特性:

(1)图元基类只有属性,没有方法。这是因为图元需要进行复制操作,复制时方法是无法实现的。

(2)很多特有的属性被设计到props属性中,这是一个Object。实际上Map也能实现相同的功能,但因为Map同样不能被复制,所以使用Object。props中只存放字符串类型的属性,其他属性(例如位置)如果使用字符串,还需要转换,浪费资源。

对于存在公共属性的图元,定义了继承Component的新的基类。例如,用矩形去描述位置的图元,都继承于以下的基类:

class RectPositionComponent extends Component {public position: Rect = new Rect(0, 0, 0, 0);public originPosition: Rect = new Rect(0, 0, 0, 0);
​public mindChildren1: Array<MindElement> = [];public mindChildren2: Array<MindElement> = [];
​public constructor() {super();
​this.props[PreDefine.MindType] = PreDefine.DefaultMindType;}
}

在这里,我们可以看到,这个类有一个position属性,它是一个矩形。还有一个originPosition属性,是用在变换图元时标记原始位置的属性。

这个基类还描述了思维导图的数据结构。本项目的思维导图,只能在矩形类型的图元下创建。思维导图存在树在两侧的展示方式,所以有两棵树(mindChildren1和mindChildren2)去描述思维导图的结点。

以下是矩形类的定义:

class RectComponent extends RectPositionComponent {public constructor() {super();
​this.type = "rect";this.id = CommonFunc.GetId();
​this.props[PreDefine.Fill] = PreDefine.DefaultFill;this.props[PreDefine.Stroke] = PreDefine.DefaultStroke;this.props[PreDefine.StrokeWidth] = PreDefine.DefaultStrokeWidth;this.props[PreDefine.StrokeDash] = PreDefine.DefaultStrokeDash;this.props[PreDefine.CornerRadius] = PreDefine.DefaultCornerRadius;
​this.props[PreDefine.TextHorAlign] = PreDefine.DefaultTextHorAlign;this.props[PreDefine.TextVerAlign] = PreDefine.DefaultTextVerAlign;this.props[PreDefine.FontFamily] = PreDefine.DefaultFontFamily;this.props[PreDefine.FontSize] = PreDefine.DefaultFontSize;this.props[PreDefine.FontColor] = PreDefine.DefaultFontColor;this.props[PreDefine.FontBold] = PreDefine.DefaultFontBold;this.props[PreDefine.FontUnderline] = PreDefine.DefaultFontUnderline;}
​public textPos: AnchorPos = new AnchorPos();public textExist: boolean = false;public textHtml: string = "";
}

矩形的样式,需要通过填充颜色、描边宽度等属性去定义。另外,矩形中还有文字,文字又有字体大小、字体颜色等属性。这些属性都在图元初始化时添加到props属性中。而文字的位置等属性,由于其存在一定的数据结构,如果定义在props中,还需要转化,浪费资源,所以独立定义。事实上,这种区分定义还有一个重要原因,就是在菜单中能修改的属性都在props中。

对图元的操作由一个接口去定义。以下是该接口的部分方法:

interface IComponentOperate {ChangeId(): void;Create(obj: unknown): void;
​Html(): string;UpdateHtml(): void;DeleteHtml(): void;
​Move(diagramX: number, diagramY: number): void;MoveOffset(offsetX: number, offsetY: number): void;UpdateInnerPosition(): void;MarkOrigin(): void;ChangeCoordinate(origin: Rect, target: Rect): void;
}

Html()方法是返回图元的HTML内容。例如矩形使用一个<rect>标签定义,形状一般使用<path>标签定义,而图片使用<image>标签定义。又如,UpdateInnerPosition()方法一般是用在组类型的图元上的。一个组进行变换之后,其内部的所有图元都要跟随变换。但矩形这种图形,内容并没有子,也就不需要执行额外的操作。

操作方法跟图元,通过图元的ID和类型进行绑定。图元的类型确定了接口实例化的方法类,而方法类要处理哪个图元,又通过ID去确定。

在线流程图和思维导图开发技术详解(二)相关推荐

  1. 在线流程图和思维导图开发技术详解(三)

    一.项目概述 二.项目架构 三.几何计算难点 四.鼠标事件处理 五.数据保存与导出 六.文本处理 三.几何计算难点 3.1 矩形变换 我们先来看没有旋转的情况.不旋转的情况是比较简单的,只是情况比较多 ...

  2. 在线流程图和思维导图开发技术详解(五)

    一.项目概述 二.项目架构 三.几何计算难点 四.鼠标事件处理 五.数据保存与导出 六.文本处理 五.数据保存与导出 5.1 数据保存 一张流程图,实际是一个图元列表,也就是Array<Comp ...

  3. 在线流程图和思维导图开发技术详解(六)

    一.项目概述 二.项目架构 三.几何计算难点 四.鼠标事件处理 五.数据保存与导出 六.文本处理 六.文本处理 6.1 两种富文本展示方式 本项目显示的文本皆是富文本,也就是在一个框里面,文本有多种样 ...

  4. 在线流程图和思维导图开发技术详解(四)

    一.项目概述 二.项目架构 三.几何计算难点 四.鼠标事件处理 五.数据保存与导出 六.文本处理 四.鼠标事件处理 在所有处理器中,鼠标事件处理器是最为复杂的,因为在整个页面中,基本可以使用鼠标完成所 ...

  5. 推荐一个在线创作流程图、思维导图软件—ProcessOn

    转载自 推荐一个在线创作流程图.思维导图软件-ProcessOn 最近要画流程图,破解了半天Visio2016没搞定,2016的估计都被封了,Visio收费又过贵,又不想折腾低版本的破解,所以找了个在 ...

  6. 推荐一个在线绘图工具ProcessOn----支持流程图、思维导图、UML等

    我们常用来绘制流程图等的工具一版会使用visio等,但是它是一款收费软件,而且不是太易用,今天推荐一款在线绘图工具ProcessOn,不仅功能强大,而且快捷易用,还有大量优秀的模板可供使用. 邀请连接 ...

  7. 免费在线作图,思维导图,流程图,实时协作

    www.processon.com 免费在线作图,思维导图,流程图,实时协作

  8. 流程图、思维导图、网络拓扑图、组织结构图——ProcessOn在线工具及增加文件数方法

    可网页在线画流程图之类的,还有模版可以参考. ProcessOn 支持流程图.思维导图.原型图.UML.网络拓扑图.组织结构图等 ProcessOn在线工具: https://www.processo ...

  9. confluence 制作流程图_「每周开方」 高效制作流程图、思维导图

    提升工作效率,并且可以自成一套职场PPT的导图.流程图! 这周的「每周开方」公子要分享强大的"思维导图"及"流程图"制作网站!在职场中导图的重要性应该不需要公子 ...

最新文章

  1. 1.2 内置异常类,异常方法
  2. zabbix监控oracle缓冲区,Zabbix监控oracle各服务器连接数
  3. Hadoop tutorial - 3 Hello MapReduce- 2015-3-30
  4. Kotlin — 适用于Android 开发
  5. unity shader base pass and additional pass
  6. 单片机编程软件很简单(19),keil单片机编程软件3点介绍
  7. 移动支付的方式有哪些拾方易告诉你
  8. 数据耦合的代码例子c语言,代码耦合的处理
  9. 1.Python基础
  10. Centos7升级OpenSSL 1.0.2k-fips
  11. 解决SVN Can’t open file ‘/XXX/xxx/db/txn-current-lock’错误
  12. python+selenium移动滑块代码【杭州多测师_王sir】【杭州多测师】
  13. Cadence原理图层次化设计
  14. 2.Python-简单数据类型
  15. 【SAP Abap】SAP增强开发总结
  16. 【Cocos Creator 3.x】 Shader 中的 layout(set = N, binding = M) 是什么意思?
  17. 经典俄罗斯方块游戏使用手册
  18. matlab粒子群加约束条件_matlab粒子群编程,等式约束如何加入
  19. 安装智能消费机服务器连接,消费一卡通系统/消费机布线安装方法
  20. reverse(一)——apk逆向

热门文章

  1. python爬虫学习日记(1) scrapy爬取时,报错Filtered offsite request
  2. 二维码简介_二维码基本概念_二维码基本原理
  3. Confluence 6 自定义站点和空间布局
  4. 本地代码如何提交到远程,克隆的和不克隆,两种方法
  5. 快手小程序研发总结页面跳转参数携带需注意
  6. Uint8Array截取,Uint8Array有的手机不支持slice方法,如何截取?
  7. 在线招聘:庞大市场,“渺小”平台
  8. 离线安装wxpython4.0.6_离线安装wxpython
  9. Ansible的安装及使用
  10. 保安日记:前端学习第三篇之CSS选择器