ShowMeBug 黑科技丨一招快速实现架构绘图之鼠标同步
根据工作习惯与经验了解,思维导图和多支线流程图一直面临一个最大的问题:只有作者才能从头到尾全部看懂。
出现这种问题的原因在于,接收者不能跟上创作者从头到尾的思考创作过程。
架构绘图就是在这样一个基础问题下产生,绘图库 mxgraph 加上 showmebug 的多端同步黑科技,诞生了 showmebug 独家的架构绘图板块,创作者可以从头到尾展示思考过程给接收者,最大程度突出创作者的特点。
图层介绍
mxgraph 含有四个图层,background pane,draw pane,overlay pane,decorator pane,这四个图层分别是四个 <g> 标签。mxgraph 在 mxGraphView 类上提供了获取这四个图层的方法:
Background Pane
背景图层,可以自定义背景图。
draw pane
所有的图形组件都是绘制在这一图层上。
overlay pane
本图层上绘制大部分的工具类元素,例如选中高亮元素,改变图形大小旋转的元素,还有本篇文章中介绍的同步鼠标这一元素。
decorator pane
当鼠标 hover 在组件上的时候,会看到出现了数个可以拉出连线的圆点,这些圆点就是绘制在该层图层上的。
坐标处理
坐标发送
mxgraph 封装了白板内部的鼠标事件,通过配置传入
mouseDown , mouseMove , mouseUp 三个回调函数来调用。回调函数的两个参数分别是事件产生的 mxGraph 和封装后相应事件的 mxMouseEvent 。
节流发送
Mouse Move 事件是典型的极高触发频率事件,所以在进行处理的时候,最好使用节流函数进行封装发送,这一点很简单,借用 lodash.throttle 即可实现。
坐标转换
mxgraph 的尺寸在不同尺寸屏幕下是适配的,反而导致鼠标的坐标在不同终端存在映射关系而不会完全相同。对应坐标需要进行下面这样一段映射算法:
因为每一端白板大小都不同,translate 可以看目前端鼠标位置的矫正位移,去除矫正位移 graphX(Y) - translate.x(y) 之后剩下鼠标在白板上的绝对位置,传递至 remote 端之后,加上本端的矫正位移 x(y) + translate.x(y) ,就能获得鼠标的正确位置。
鼠标绘制
任务队列
只有节流发送的话,remote 端可能因为网络波动的原因,可能会在某段时间内收到拥堵的大量信息,这些信息不分先后的执行,导致同步鼠标产生胡乱跳动的现象。因此在 remote 端,使用任务队列的思想来解决这个问题。
通过 next() 函数控制执行顺序,把异步发送事件触发的任务,强制变为同步任务执行。这种思想在一些 NodeJS 框架里被广泛应用,例如:ExpressJs 中间件等。
平滑滑动
鼠移动事件是节流后的数据发送到 remote 端,导致 remote 端接收到的坐标信息是跳跃式的,如果只是按照发送事件触发同步鼠标绘制,那绘制出来的动画效果也是跳跃式的,给人十分卡顿的感觉。同事讨论和查找资料后选用
window.requestAnimationFrame 进行平滑处理。
原因在于 svg 画布里的 transform: translate(x, y) 与 css 的表现略有不同,svg 内部元素的 transform: translate 会根据最近祖先 svg 元素的 x,y 属性,作为开始位移起始点。
据此特性,将鼠标图形包裹在一个 svg 标签内部(如上段代码所示),通过设置 pointer-wrapper 的 x/y 属性,确定同步鼠标的绝对位移;一个事件中,同步鼠标产生移动过程中,对 pointer-wrapper 的两个子元素的 transform: translate 属性进行操作,作为相对位移;当这次移动事件结束,再对 pointer-wrapper 设置 x/y 属性为最终坐标,同时对 pointer-wrapper 的两个子元素设置 transform: translate(0, 0),作为最终的绝对位置。
作者:史翊
ShowMeBug 是一款数字化驱动的可记录、可分析、可复盘的技术评估与在线 Coding 面试平台。
版权声明: 本文为 InfoQ 作者【ShowMeBug】的原创文章。
原文链接:【http://xie.infoq.cn/article/b1882bf7aac06e5e8e12dc008】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论