@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的功能给完善一下就更好了。

相关推荐
安得权16 分钟前
Ubuntu 20.04 部署 NET8 Web - Systemd 的方式 达到外网访问的目的
linux·前端·ubuntu
我是Superman丶42 分钟前
【前端UI框架】VUE ElementUI 离线文档 可不联网打开
前端·vue.js·elementui
sqll5671 小时前
最新简洁大方的自动发卡网站源码/鲸发卡v11.61系统源码/修复版
前端·开源·html
清灵xmf1 小时前
深入解析 JavaScript 事件委托
前端·javascript·html·事件委托
小妖别跑2 小时前
PDA(程序派生地址,Program Derived Address),为什么有这个地址,而不是直接指定地址
前端·智能合约
2301_796982142 小时前
网页打开时,下载的文件text/html/重定向类型有什么作用?
前端·html
重生之我在20年代敲代码2 小时前
HTML讲解(二)head部分
前端·笔记·html·web app
天下无贼!2 小时前
2024年最新版TypeScript学习笔记——泛型、接口、枚举、自定义类型等知识点
前端·javascript·vue.js·笔记·学习·typescript·html
小白小白从不日白3 小时前
react 高阶组件
前端·javascript·react.js
Mingyueyixi3 小时前
Flutter Spacer引发的The ParentDataWidget Expanded(flex: 1) 惨案
前端·flutter