前言
本次分享是笔者在实际项目遇见的问题,当时第三方库不提供解决方案,使用的前端控件也无类似情况,社区也没有这种BUG反馈,笔者已经有打算重构的念头了,后来多番尝试下,最终发现了解决方案,同时也发现了一些思路技巧,因此想记录下自己的这一段开发的心路历程,勉励自己。
由于是实际项目,会涉及公司业务,因此会对图案信息做白色涂鸦处理,涉及到业务代码以及第三方库源码,也只能讲浅谈设计思路,不能粘贴代码
背景
大屏主要用于直观展示各项数据指标,而拓扑是有自己一套的展示环境,但是为了能统一管理可视化,拓扑也需要能迁移到大屏内,在迁移过程中,发生了视觉偏差,被拖动的图标跟鼠标不一致
正文
新大屏由于使用了 transform 的 scale,这个属性会使得大屏的布局,整体进行缩放,缩放后,拓扑获取的坐标(内部坐标)与大屏整体坐标(外部坐标)不一致,就会使得,拓扑的浮窗看上去不同步
偏移如下:
要使 拓扑能完全适配大屏,在大屏内保留所有的拓扑操作,需要在 HT 初始化时,增加一句代码(HT提供的方案)
this.graphView.updateDOMAppendMatrix();
增加完之后,就会发现,可以准确点击到节点和线,这就意味着,鼠标点击的坐标,是大屏外部的坐标,这是我们想要的效果。
但是,有奇怪的现象,似乎每个点的浮动框,位置不太一致
之所以会这样,跟HT渲染使用的renderHTML方法有关,通过定义HT矢量JSON的renderHTML函数属性,可实现在GraphView拓扑图上,嵌入任意第三方HTML DOM元素。HT的图纸是Canvas实现,renderHTML的DOM一定在Canvas之上,使用renderHTML的DOM与常规Canvas上绘制的图元不可能有层级控制可能性。
renderHTML 的设计大致如下:
renderHTML: function(data, gv, cache) {
if (!cache.htmlView) {
// 创建 HTML
}
return html;
}
这也解释了为什么会出现坐标偏移,因为这个节点,本身就是一个DOM元素。
既然出现偏移量,那就说明,我们当前鼠标获取到坐标跟我们实际想要的坐标是不一致的。这时候需要通过输出mouse事件的坐标以及偏移坐标来做对比。
offsetX 从中文上理解为X轴偏移量,既然是偏移量自然有一个相对的偏移对象,而 offsetX 和 offsetY 对应的参考系是鼠标事件所在的 DOM 元素。因此,鼠标移动到坐标的时候,偏移对象变成了图标,而不再是外部的布局。
这时候,如果依赖 HT 提供的方案或者想在偏移量上找方案,基本就判死刑了,因为鼠标的偏移量是浏览器设定的,不是开发可以介入的。
解决方案,其实是将坐标换成当前 dom 元素的 top和 left。不管HT环境怎么限制,终究是要挂在到 dom,而且图标返回就是一个 dom 元素,这对我们直接获取,也是一个巨大的优势。
具体实现则是:在图标渲染的方法下,写入id,是为了获取dom元素,然后那到对应的 style.left 和 top,用于坐标
点的写法如下
这样一来就顺利解决了视觉位移的BUG,但是! 会存在一个问题,那就是当同个图标,被多个节点引用时候,拿到的 dom,相同节点的dom,都是同一个,而不是根据点渲染的dom。
正确的渲染方式,应该是:给个icon节点,单独渲染,然后给予单独的标识,从而生成单独的dom节点。 所以,只要确保给每个点给予唯一标识即可,这里不再展开叙述(hash,时间戳等等都能实现),笔者是使用 uuid,到此,BUG处理完毕
感想
此次文章,重点放在了解决问题的思路上,而不是直给解决方案,笔者自己也清楚,这个解决方案并不是算是完美的,因为它直接操作了dom,而 react 是不提倡我们直接去操作dom,毕竟人家当初就是为了避免这个现象才设计虚拟dom,顶多算 '曲线救国' 吧。。。。。。不过呢,笔者认为,这种BUG是现象级的,属于严重类型,会耽误客户的使用以及项目的推广,一定要优先处理,实际开发是不可能让你有那么多时间去考虑技术层面的问题,这种时候,都是先处理后完善,确保项目稳定运行。
笔者事后也找了很多的相关资料,确实找不到其他更完善的方案。不过这次解决问题的过程,让笔者吸取了很多,比如,不要太过依赖社区,有时候,自己的知识点已经足够解决了,只是自己没有把问题的本质看透,解决问题的方式,有很多,哪怕是灵光一现的一个简单UI,当然了,平时也要多积累其他的知识点,多上 github 逛逛,基础才是 '根本'。