V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ShowMeBug2020
V2EX  ›  推广

ShowMeBug 黑科技丨一招快速实现架构绘图之鼠标同步

  •  
  •   ShowMeBug2020 · 2021-09-09 11:23:29 +08:00 · 823 次点击
    这是一个创建于 1200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    根据工作习惯与经验了解,思维导图和多支线流程图一直面临一个最大的问题:只有作者才能从头到尾全部看懂。

    出现这种问题的原因在于,接收者不能跟上创作者从头到尾的思考创作过程。

    架构绘图就是在这样一个基础问题下产生,绘图库 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 面试平台。

    点击试用: https://www.showmebug.com/

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   909 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 19:50 · PVG 03:50 · LAX 11:50 · JFK 14:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.