Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将JavaFX节点导出到SVG图像?_Java_Svg_Javafx_Vector Graphics - Fatal编程技术网

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

如何将JavaFX节点导出到SVG图像?,java,svg,javafx,vector-graphics,Java,Svg,Javafx,Vector Graphics,换句话说,我正在尝试用JavaFX做一些事情,比如什么 我希望能够在JavaFXUI中捕获任意节点的外观,就像这样,只是我需要SVG等矢量格式的图像,而不是光栅图像。(将我的节点的光栅快照插入SVG图像还不够好;它需要是一个适当的、可伸缩的矢量图像。) 这是一个长期项目,所以我甚至愿意实现我自己的,或者JavaFX的保留模式API中的任何等价物 有人知道有没有办法做到这一点吗?我希望在JavaFX中做的事情可能吗?有一个简单的方法,它只转换基本形状而不应用css,而不是任意节点,但这可能就是您所

换句话说,我正在尝试用JavaFX做一些事情,比如什么

我希望能够在JavaFXUI中捕获任意节点的外观,就像这样,只是我需要SVG等矢量格式的图像,而不是光栅图像。(将我的节点的光栅快照插入SVG图像还不够好;它需要是一个适当的、可伸缩的矢量图像。)

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


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

有一个简单的方法,它只转换基本形状而不应用css,而不是任意节点,但这可能就是您所需要的全部。

在JFX JIRA中有一个打开的错误请求

(需要注册;您可以投票支持该问题)。它现在说

考虑将来的版本


并标记为版本9。

我开始编写JavaFx节点到SVG转换器,它从Gerrit Grunwald“扩展”了ShapeConverter,Gerrit Grunwald只转换形状几何:

。。。在经历了一定程度的挫折后停止了

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

转换器适用于简单的节点示例,但对于高级示例(如图表)则失败。我失败的转换器可以作为一个起点。下图说明了当前状态。左侧显示原始JavaFx节点,右侧显示生成的svg输出

简单节点示例(有效):

图表示例(不起作用):

此处提供了相应的svg文件:

一些进一步的注释

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

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图表的转换工作正常,我会非常高兴,这样我就可以在我的一个项目中使用带有SVG导出的JavaFx绘图

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

编辑
使用d3.js进行绘图效果非常好,我决定不使用JavaFx进行绘图/svg创建

这个想法是,如果您能够将JavaFX节点树结构转换为一系列Graphics2D命令,那么您可以使用具有Graphics2D驱动程序的Batik

问题是,将JavaFX树结构转换为Graphics2D顺序并不像您想象的那么困难(即使您处理节点的CSS属性)

您应该从新的空SVGDocument创建SVGGraphics2D,例如:

Document doc = SVGDOMImplementation.getDOMImplementation().createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
SVGGraphics2D g2D = new SVGGraphics2D(doc);
g2D.drawLine((int) line.getStartX(), (int) line.getStartY(), (int) line.getEndX(), (int) line.getEndY());
然后获得要转换的场景的根节点,对于该节点,获得节点的类型,可以是形状、控件、区域、ImageView、组、子场景、Shape3D

根据每个节点,可以获得节点的特征。例如,对于形状,如果它是一条线,则可以在SVGGraphics2D中绘制该线。例如:

Document doc = SVGDOMImplementation.getDOMImplementation().createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
SVGGraphics2D g2D = new SVGGraphics2D(doc);
g2D.drawLine((int) line.getStartX(), (int) line.getStartY(), (int) line.getEndX(), (int) line.getEndY());
请注意,还需要注意应用于节点的变换以及节点的填充或绘制

然后在节点子节点上迭代,并递归地执行相同的操作


最后,您应该能够将文档保存在SVG中,因为Batik允许以本机方式保存文档。

这个想法是,如果您能够将JavaFX节点树结构转换为一系列Graphics2D顺序,那么您可以使用具有Graphics2D驱动程序的Batik

问题是,将JavaFX树结构转换为Graphics2D顺序并不像您想象的那么困难(即使您处理节点的CSS属性)

一些读者建议我应该包括一些代码,而不仅仅是指向库的链接和它工作的图片。这不是那么容易做到,因为即使它不是那么难做到,它仍然有5000行代码

如何执行转换:

  • 必须有一个Graphics2D才能转换为SVG(例如Batik SVGGraphics2D类)
  • 迭代JavaFX结构
  • 对于结构中的每个节点,首先将该节点上的当前javaFX转换转换为AffineTransform,并将转换应用于该节点(必须在堆栈中进行转换,以确保还原为initi)