G6 icon indicating copy to clipboard operation
G6 copied to clipboard

feat: add scroll-canvas behavior

Open k644606347 opened this issue 10 months ago • 10 comments

任务

  • https://github.com/antvis/G6/issues/5548

改动

  • feat: 迁移v5_old behavior: scroll-canvas to v5
  • chore: 增加demo和测试用例

breakingchanges

  • 删除enableOptimize/optimizeZoom,因为graph缺少隐藏node keyShape的等相关api,无法实现此功能,看后续是否需要再开发,而且通过隐藏keyShape来提升性能是否是一个好的方案;
  • 删除zoomKey / zoomRatio, 因为zoom-canvas基本覆盖此功能,没必要在scroll-canvas再次处理缩放;
  • 删除scalableRange,drag相关的功能,没必要在scroll-canvas内实现,不过目前drag-canvas也没有此功能,看后续是否追加;
  • 删除allowDragOnItem,冗余的配置项,可通过enable实现相同能力,故删除;
Checklist
  • [x] npm test passes
  • [ ] tests and/or benchmarks are included
  • [ ] commit message follows commit guidelines
Description of change

k644606347 avatar Apr 02 '24 06:04 k644606347

再探讨下,对于大数据量下(node+edge的图元超过1w+),滚动和拖拽等交互的性能优化方向:

  • 是否可以借鉴类似```虚拟列表```的原理,仅渲染和处理canvas区域内的节点/边,但如果图元高度密集,估计也收效甚微;

我之前在v4的```scroll-canvas```, 实现过类似的demo:https://codesandbox.io/p/github/k644606347/g6-dagre-scroll-perf/main

  • 还是说可以迁移到WebGL/WebGpu来彻底解决交互性能问题;

k644606347 avatar Apr 02 '24 07:04 k644606347

再探讨下,对于大数据量下(node+edge的图元超过1w+),滚动和拖拽等交互的性能优化方向:

  • 是否可以借鉴类似虚拟列表的原理,仅渲染和处理canvas区域内的节点/边,但如果图元高度密集,估计也收效甚微;

我之前在v4的scroll-canvas, 实现过类似的demo:https://codesandbox.io/p/github/k644606347/g6-dagre-scroll-perf/main

  • 还是说可以迁移到WebGL/WebGpu来彻底解决交互性能问题;

大数据量下推荐迁移到 WebGL 渲染器,此时相机是真实的, 对于滚动、缩放等操作其实是通过调整相机实现的。而对于拖拽操作,后续会完善分层绘制机制,将交互的元素放置在交互层。

Aarebecca avatar Apr 02 '24 07:04 Aarebecca

@Aarebecca 你好,在测试scroll-canvas时发现了一个现象,就是将容器div#app的height设置为2000px,让其带有滚动条后,滚动canvas时,div容器也会跟着滚动; 预期: 只有canvas内容滚动才对; 现状: 上层div和canvas都会滚动;

测试环境:

  • 设备:Apple M3 Pro
  • 浏览器:chrome 123.0.6312.59(正式版本) (arm64) / safari 17.2.1 (19617.1.17.11.12) / firefox 121.0.1 (64 位)

示例: Large GIF (1726x1022)

原因分析:

  1. 首先尝试禁用wheel事件默认行为,在scroll-canvas下调用ev.nativeEvent.preventDefault();,但是报错:
image
  1. debug发现DOMInteractionPlugin有设置passive: true https://github.com/antvis/G/blob/037f76e73dfcd47843fcda2e2151139c65ac2934/packages/g-plugin-dom-interaction/src/DOMInteractionPlugin.ts#L155
image
  1. 改为passive: false后,滚动行为符合预期:

因为改动的是G库的代码,辛苦看下这是否是bug,如果是该如何修复;

k644606347 avatar Apr 05 '24 02:04 k644606347

这里存在一个误解,滚动 Canvas 并非是指将容器设置得足够高以出现滚动条,而是画布内元素呈纵向排布且超出了视口高度。因此这个组件的实现逻辑应该与 drag-canvas 基本一致,只是 trigger 支持 wheel 或者 up/down ,方向只支持纵向调整。

Aarebecca avatar Apr 07 '24 04:04 Aarebecca

这里存在一个误解,滚动 Canvas 并非是指将容器设置得足够高以出现滚动条,而是画布内元素呈纵向排布且超出了视口高度。因此这个组件的实现逻辑应该与 drag-canvas 基本一致,只是 trigger 支持 wheel 或者 up/down ,方向只支持纵向调整。

@Aarebecca 我其是指antv封装的`wheel`事件,底层实现是否有欠缺,我的环境下,在滚动G6的画布时,外层的其他带有滚动条的div也跟着滚动了(div是外部系统生成的且决定是否可滚动,不是G6库生成的),这种交互效果可能会被使用G6v5的用户吐槽,比如只是想看G6的非视口区域数据,结果滚动后,整个外层div都跟着滚动,导致G6整体都滚出了div的视口;

且无法通过wheel事件给出的`event.nativeEvent.preventDefault`阻止div滚动,因为底层代码在绑定原生wheel时设置了passive: true,(如有更优解决方案请指出);

可以在我这个分支下,将div#app的height改大一些,运行下demo上下滚动看看效果就明白了;

k644606347 avatar Apr 07 '24 07:04 k644606347

之前我简单研究过 passive 滚动的问题,也可以一起讨论下:

https://g.antv.antgroup.com/api/event/faq#%E5%9C%A8-chrome-%E4%B8%AD%E7%A6%81%E6%AD%A2%E9%A1%B5%E9%9D%A2%E9%BB%98%E8%AE%A4%E6%BB%9A%E5%8A%A8%E8%A1%8C%E4%B8%BA

或者我把它做成开关,创建 Canvas 时可以指定:

new Canvas({ enablePassiveScrolling: false });

xiaoiver avatar Apr 09 '24 07:04 xiaoiver

之前我简单研究过 passive 滚动的问题,也可以一起讨论下:

https://g.antv.antgroup.com/api/event/faq#%E5%9C%A8-chrome-%E4%B8%AD%E7%A6%81%E6%AD%A2%E9%A1%B5%E9%9D%A2%E9%BB%98%E8%AE%A4%E6%BB%9A%E5%8A%A8%E8%A1%8C%E4%B8%BA

或者我把它做成开关,创建 Canvas 时可以指定:

new Canvas({ enablePassiveScrolling: false });

@xiaoiver 其实我在想底层还是默认不启用passive较好吧,然后G6库提供配置并透传给G,让用户侧分场景去决定是否启用;既然这是G的实现,估计以后其他依赖G的库也会有类似的问题;总之感谢回复;目前还没时间细看,等忙完这两天的

k644606347 avatar Apr 10 '24 09:04 k644606347

之前我简单研究过 passive 滚动的问题,也可以一起讨论下:
https://g.antv.antgroup.com/api/event/faq#%E5%9C%A8-chrome-%E4%B8%AD%E7%A6%81%E6%AD%A2%E9%A1%B5%E9%9D%A2%E9%BB%98%E8%AE%A4%E6%BB%9A%E5%8A%A8%E8%A1%8C%E4%B8%BA
或者我把它做成开关,创建 Canvas 时可以指定:

new Canvas({ enablePassiveScrolling: false });

@xiaoiver 其实我在想底层还是默认不启用passive较好吧,然后G6库提供配置并透传给G,让用户侧分场景去决定是否启用;既然这是G的实现,估计以后其他依赖G的库也会有类似的问题;总之感谢回复;目前还没时间细看,等忙完这两天的

@xiaoiver 想了下 enablePassiveScrolling 方案是个不错的方案,比如可以G库底层保持逻辑不变,G6库提供配置项默认enablePassiveScrolling: false,文档告知用户可开启来提升特定场景性能;不过具体怎么做还是得你们官方决定;

k644606347 avatar Apr 10 '24 09:04 k644606347

之前我简单研究过 passive 滚动的问题,也可以一起讨论下:

https://g.antv.antgroup.com/api/event/faq#%E5%9C%A8-chrome-%E4%B8%AD%E7%A6%81%E6%AD%A2%E9%A1%B5%E9%9D%A2%E9%BB%98%E8%AE%A4%E6%BB%9A%E5%8A%A8%E8%A1%8C%E4%B8%BA

或者我把它做成开关,创建 Canvas 时可以指定:

new Canvas({ enablePassiveScrolling: false });

@Aarebecca 我已经使用 @xiaoiver 提供的链接教程,把g6封装的`wheel`替换为原生dom的`wheel`,已经修复了因无法执行preventDefault导致外层容器意外滚动的问题,请看下最新代码

k644606347 avatar Apr 21 '24 07:04 k644606347

@Aarebecca 抱歉,之前没注意ci build faild,已fix

k644606347 avatar Apr 22 '24 13:04 k644606347