如何将 JavaFX 节点导出到 SVG 图像?

2022-09-04 22:55:58

换句话说,我正在尝试用JavaFX做一些事情,就像Batik允许你用Swing做的那样。

我希望能够在我的JavaFX UI中捕获任意节点的外观,就像Node.snapshot()一样,除了我需要像SVG这样的矢量格式的图像,而不是光栅图像。(将我的节点的光栅快照插入到SVG图像中是不够的;它需要是一个适当的,可扩展的矢量图像。

这是一个长期项目,所以我甚至愿意实现我自己的GraphicsContext,或者JavaFX的保留模式API中的任何等效物。

有谁知道是否有办法做到这一点?我希望在JavaFX中做的事情是可能的吗?


答案 1

我开始编写一个JavaFx Node到SVG转换器,该转换器“扩展”了Gerrit Grunwald的ShapeConverter,它只转换Shape几何形状:

https://github.com/stefaneidelloth/JavaFxNodeToSvg

...并在一定程度的挫败感后停止了它。

请随时改进它,添加功能并修复错误。

该转换器适用于简单的 Node 示例,但不适用于图表等高级示例。我失败的转换器可能会作为您的起点。下图说明了当前状态。左侧显示原始 JavaFx 节点,右侧显示生成的 svg 输出。

简单节点示例(作品): enter image description here

图表示例(不起作用): enter image description here

相应的 svg 文件可在此处找到:

https://github.com/stefaneidelloth/JavaFxNodeToSvg/tree/master/output

一些进一步的注意事项

除了上面的图表示例所说明的定位问题之外,还必须考虑一些其他问题:

JavaFx 提供了比 SVG 标准元素更多的 css 功能。例如,(矩形)JavaFx 区域可以为每个四条边框线中的每条线提供单独的线条样式。这样的区域不能简单地转换为 SVG 矩形。相反,该区域的四条边界线需要单独划定。此外,这种边界线的每一端可以有两个单独的边半径:垂直半径和水平半径。为了将“四”边界线转换为相应的SVG线...可能有必要进一步拆分边界线:为四条边界线中的每条绘制两个圆角部分和一个直线部分。因此,在某些情况下,可能有 12 个 SVG 路径元素来绘制单个 JavaFx 区域的边框。此外,区域的背景填充可以具有与区域边界不同的半径。绘制区域的背景可能需要更多的 SVG 元素。因此,即使是“矩形区域”的转换也会变得非常复杂。

另请注意,JavaFx 节点可能会进行动画处理。例如,一条线的不透明度在开始时为 0,并在几毫秒后淡入另一个值。

FadeTransition ft = new FadeTransition(Duration.millis(250), borderline);
                    ft.setToValue(0);                       
                    ft.play();

因此,只有转换禁用动画的节点或等到节点处于稳定状态才有意义。

如果有一天JavaFx Charts的转换工作正常,我会非常高兴,这样我就可以在我的一个项目中使用JavaFx绘图和SVG导出。

我决定暂时停止转换器的开发,而是使用JavaScript库(d3)研究绘图和SVG导出。如果这种策略变得更糟,我可能会回到JavaFxNodeToSvgConverter。

编辑使用d3.js绘图效果很好,我决定不使用JavaFx来创建绘图/ svg。https://github.com/stefaneidelloth/javafx-d3


答案 2

有一个简单的JavaFX形状到SVG字符串转换器,它只会转换基本形状而不应用css,而不是任意节点,但也许这就是你所需要的。