svg - 使用 Batik 解析 SVG 路径样式

标签 svg java-2d batik

使用 Batik,我将一些 SVG 代码转换为使用 Java2D 命令的直接 Java/Scala 代码。例如,我有以下片段:

<path
  id="path3622"
  transform="translate(0,152.36218)"
  d="m 720,94.5625 c -190.64053,0 -346.23512,150.07433 -355.0625,338.53125 235.63168,-82.12984 472.1202,-97.44221 710.0313,-1.78125 C 1065.2448,243.69491 910.03743,94.5625 720,94.5625 z"
  style="opacity:0.28999999;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
/>

我已经解决了 d= 位,使用 PathHandler 生成正确的 GeneralPath2D。我将如何解析 transformstyle 属性? transform 我可以想象我可以手动管理自己,但是对于样式,如果有一个可以让我直接访问填充和描边值的解析器会很棒.

最佳答案

Batik 的 API 非常笨拙,我也不得不为之苦苦挣扎。这就是我处理类似问题的方式。

import org.apache.batik.anim.dom.SVGStylableElement;

private void fill(SVGStylableElement element, String fillValue) {
    element.getStyle().setProperty("fill", fillValue, "");
}

用法很明显。第一个参数是 SVGStylableElement 的实例(见下文)。第二个是您要设置的颜色值(例如“#FF0000”)。请注意,setProperty() 还有第三个参数 - 它可用于在 CSS 中设置 !important(我不需要它)。

因此,首先您需要获取 SVGStylableElement 的实例。

import org.w3c.dom.Element;
import org.w3c.dom.svg.SVGDocument;

private Optional<SVGStylableElement> getElement(final SVGDocument svg, String id) {
    Element element = svg.getElementById(id);
    if (null == element) {
        return Optional.empty();
    }

    if (!SVGStylableElement.class.isAssignableFrom(element.getClass())) {
        return Optional.empty();
    }

    return Optional.of((SVGStylableElement) element);
}

上面的方法是 Java8+ 风格的,但如果需要可以为旧的 Java 版本重写。您提供 SVGDocument 实例和元素 ID(在您的示例中为“path3622”)。

我假设您已经以某种方式创建了一个 SVGDocument 实例,所以我在这里省略它。 最后但必需的方法是初始化 CSS 引擎。这就是 batik 的魔力。您可以在那里找到更多信息 https://wiki.apache.org/xmlgraphics-batik/BootSvgAndCssDom

import org.apache.batik.bridge.BridgeContext;
import org.apache.batik.bridge.DocumentLoader;
import org.apache.batik.bridge.GVTBuilder;
import org.apache.batik.bridge.UserAgentAdapter;

private void initializeEngine(SVGDocument svg) {
    UserAgentAdapter userAgent = new UserAgentAdapter();
    DocumentLoader loader = new DocumentLoader(userAgent);
    BridgeContext ctx = new BridgeContext(userAgent, loader);
    ctx.setDynamicState(BridgeContext.DYNAMIC);
    GVTBuilder builder = new GVTBuilder();
    builder.build(ctx, svg);
}

因此,请记住在创建 SVGDocument 实例后立即调用此 initializeEngine(...) 方法一次。如果您不这样做,您将在 fill(...) 方法的 element.getStyle() 中获得 NPE。

仅供引用,这些是我使用的 pom.xml 中的条目:

<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-svg-dom</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-anim</artifactId>
    <version>1.9.1</version>
</dependency>
<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-bridge</artifactId>
    <version>1.9.1</version>
</dependency>

关于svg - 使用 Batik 解析 SVG 路径样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21170235/

相关文章:

JAVA - 图形不更新

java - 无法理解读取 svg 文件的连接 URL

d3.js - 如何在强制布局中拖动时将 svg 元素对齐到网格

javascript - SVG 中的 HTML 元素未显示

android - 将 SVG 用于 Android 游戏的优缺点

JPanel 上的 Java Path2D.Double 都画有 'tail'

java - 如何动态更新java Canvas ?

带有 svg 的 css 剪辑路径在 Chrome 中不起作用

java - 如何使用 Apache Batik 库将 Graphics2D 转换为 SVGGraphics2D?

java - 如何将多个矩形合并为一个多边形