@antv/x6 自定义节点Safari兼容问题处理

背景

  1. 为什么选择@antv/x6?
    由于x6提供了一套强大友好的流程图API,并且支持使用 React、Vue 组件来渲染节点。这样可以使用组件开发的方式去快速完成卡片开发,并实现更加复杂的业务逻辑。
  2. 遇到了Safari的兼容问题
    由于x6自定义节点基于SVG foreignObject节点去实现的,但是Safari对foreignObject的实现不够完整,这就出现了在safari上出现了无法设置节点的位置,有些内容展示不出来的问题。
    以下是x6官网上Vue使用案例在Chrome和Safari上的展示对比:
    Chrome 效果

    Safari 效果

    卡片跑到了左上角位置,设置的卡片位置完成无效了

参考:

Safari上SVG foreignObject中<video>元素的位置错误

解决Safari浏览器使用SVG foreignObject 不生效,错位的问题

解决方式

一开始想的是有没有对应的polyfill去解决foreignObject的兼容问题,但是没有找到。后面发现了x6-html-shape这个库,采用了html节点的方式,避开了foreignObject。

x6-html-shape原理解析

  1. 节点绘制
    x6-html-shape通过创建一个html容器节点覆盖在svg画布的上层,使用绝对定位+transform将自定义节点绘制到这个html容器内,在每个节点的下层会对应相关的svg空节点。这样避免了使用Svg foreignObject的方式。
  2. 事件处理
    对于画布上的事件通过添加pointer-events:none样式,使事件透传。卡片上事件通过监听直接转发到下层的svg节点。核心代码如下:
ts 复制代码
Dom.css(htmlContainer, {
    position: "absolute",
    width: "100%",
    height: "100%",
    "touch-action": "none",
    "user-select": "none",
    "pointer-events": "none",
    'z-index': 0,
    'transform-origin': 'left top',
});
htmlContainer.classList.add("x6-html-shape-container");
ts 复制代码
Dom.css(container, {
    "pointer-events": "auto",
    "touch-action": "none",
    "user-select": "none",
    "transform-origin": "center",
    position: "absolute",
})
container.classList.add("x6-html-shape-node");
      // forward events
const events = "click,dblclick,contextmenu,mousedown,mousemove,mouseup,mouseover,mouseout,mouseenter,mouseleave".split(",");
events.forEach((eventType) =>
    forwardEvent(eventType, container, this.container)
);
this.graph.htmlContainer.append(container);

container 就是自定义的卡片容器,卡片内容将放在里面, this.container能获取到对应的svg节点。这里container的pointer-events设置成了auto保证了卡片上的事件能正常触发。

ts 复制代码
export function forwardEvent(eventType, fromElement, toElement) {
  fromElement.addEventListener(eventType, function (event) {
    toElement.dispatchEvent(new event.constructor(event.type, event));
    event.preventDefault();
    event.stopPropagation();
  });
}

通过调用forwardEvent将自定义卡片上的事件转发到svg节点上。

使用中的问题

可能由于这个库,使用的人并不多,很多问题没有被发现,我在实际使用的时候也遇到了以下的问题:

  1. 缩放后节点错位,节点并没有合理缩放
  2. 卡片上不能滚动问题
  3. 节点删除后,下层对应的svg节点未删除
  4. 无法显示或隐藏节点问题
  5. 节点较多时缩放失效问题
  6. 卡片上点击功能按钮el-popover不展示问题(开发卡片时阻止按钮的事件冒泡行为即可)
    由于原作者精力有限,忙于其他事情。我就自己主动提交了PR,参与到了这个项目的贡献。后续作者也给开通了github代码提交权限和npm包的发布权限,以上问题都得到了解决。

总结

总体来说,x6-html-shape很好的解决了x6使用SVG foreignObject绘制自定义节点在Safari上的兼容问题。这个库的解决思路非常不错,希望能帮助到更多的人。当然如果Safari能把foreignObject的功能给完善一下就更好了。

相关推荐
keyipatience2 小时前
JS学习笔记(2)数组,函数,作用域,对象
前端·javascript·笔记·学习·html
2603_965148112 小时前
商品价格监控 API 接口:从原理到实战的完整指南
java·前端·数据库·python·生活
酷虎软件2 小时前
视频加字幕怎么制作
java·前端·音视频
Geoffwo2 小时前
robotjs0.6.0鼠标中轴滚动失效修复方案
前端·javascript
彭亚川Allen3 小时前
从零手搓 RAG 之文档解析技术
前端·后端·架构
oicola3 小时前
Ant Design v5 vs Tailwind CSS:组件库与样式框架的终极对决
前端·css
溪语流沙3 小时前
【Web全栈进阶】Vue Router + Pinia:SPA路由与全局状态
前端·javascript·vue.js
ManageEngineITSM3 小时前
工单优先级怎么定?影响×紧急度矩阵的设计与落地方法
java·大数据·运维·前端·数据库·变更管理
智商网输送线配件3 小时前
电子制造零散耗材补货实战:小批量混批采购平台怎么选才不停机?
大数据·服务器·前端·数据库·自动化
梦帮科技3 小时前
Web 漏洞攻防深度:WAF 规则逃逸技术(畸形分块传输、双重编码)与对抗加固
linux·前端·网络安全·ssl·web