java实现SVG图创建全过程

 更新时间:2025年10月22日 08:45:58   作者:有女孩说要娶我  
本文介绍了如何在Java中操作和生成SVG矢量图,包括SVG的基本概念、图形和面板类的设计、SVG DOM的创建与元素添加,以及如何将SVG保存为文件,最后指出实际应用中还有更多复杂操作可实现

前言

svg作为矢量图,如何进行结构分析重构,是很重要的一环,在web开发中也是比较常见。本文开始介绍如何使用java操作svg图。

一、SVG是什么?

svg是一种矢量图,其不会随着大小变化而失真。

在开发环境下,其可以看作一个xml文件,每一个图形都是可以操作的单位,可以设置位置、大小、颜色等等。

二、生成一个svg图

1. 引入依赖

<dependency>
    <groupId>org.apache.xmlgraphics</groupId>
    <artifactId>batik-all</artifactId>
    <version>1.14</version>
</dependency>

2. 图形配置类

2.1 svg图形基类

@Data
public abstract class ShapeConfig {
    protected String id;
    protected String type;
    protected Map<String, String> attributes;

    public ShapeConfig(String type, String id) {
        this.type = type;
        this.id = id;
    }
}

attributes主要存一些定义完成属性之外的一些属性,后面再具体介绍。

2.2 矩形子类

@Setter
@Getter
public class RectConfig extends ShapeConfig{
    private int x;
    private int y;
    private int width;
    private int height;
    private String fill = "black";
    private String stroke = "none";
    private String strokeWidth = "1";
    private int rx = 0;
    private int ry = 0;
    
    public RectConfig(String id) {
        super("rect", id);
    }
}

父类的attributes则可以存当前矩形定义的属性之外的属性,例如设置透明度:

attributes.put("opacity", "0.8");

2.3 文本子类

@Setter
@Getter
public class TextConfig extends ShapeConfig{
    private int x;
    private int y;
    private String content;
    private String fill = "black";
    private String fontFamily = "Arial";
    private String fontSize = "16";

    public TextConfig(String id) {
        super("text", id);
    }
}

也可以定义很多其他的子类,比如线条、圆等,这里就两个举例。

3. svg面板类

面板可以添加多个形状

@Data
public class SvgConfig {
    private int width = 400;
    private int height = 300;
    private String backgroundColor = "white";
    private List<ShapeConfig> shapes = new ArrayList<>();

    public void addShape(ShapeConfig shape)
    {
        shapes.add(shape);
    }
}

4. 创建svg图

4.1 定义属性

创建svg面板、矩形、文本,然后创建svg。

public static void main(String[] args) {
        try {
            // 创建SVG面板配置
            SvgConfig config = new SvgConfig();
            config.setWidth(500);
            config.setHeight(400);
            config.setBackgroundColor("#f0f8ff");

            // 添加矩形
            RectConfig rect1 = new RectConfig("rect1");
            rect1.setX(200);
            rect1.setY(50);
            rect1.setWidth(100);
            rect1.setHeight(80);
            rect1.setFill("#4ecdc4");
            rect1.setStroke("#333");
            rect1.setStrokeWidth("2");
            rect1.setRx(10);
            rect1.setRy(10);
            config.addShape(rect1);

            // 添加文本
            TextConfig text1 = new TextConfig("text1");
            text1.setX(100);
            text1.setY(300);
            text1.setContent("Hello SVG!");
            text1.setFill("#1a936f");
            text1.setFontFamily("Arial");
            text1.setFontSize("20");
            config.addShape(text1);

            // 生成SVG文件
            generateSvg(config, "generated.svg");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4.2 初始化svg的dom

通过DocumentBuilderFactory工厂类创建DocumentBuilder实例,然后创建一个空的svg文档,进行文档的配置以及添加元素,将所有元素添加到文档中。

  • 根元素:所有元素的顶层父元素
  • 背景:子元素
  • 图形:子元素
public static void generateSvg(SvgConfig config, String filename) throws Exception {
        // 创建空的SVG文档
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.newDocument();

        // 创建SVG根元素
        Element svg = doc.createElement("svg");
        svg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
        svg.setAttribute("width", String.valueOf(config.getWidth()));
        svg.setAttribute("height", String.valueOf(config.getHeight()));
        svg.setAttribute("viewBox", "0 0 " + config.getWidth() + " " + config.getHeight());
        doc.appendChild(svg);

        // 添加背景
        if (config.getBackgroundColor() != null && !config.getBackgroundColor().equals("white")) {
            Element background = doc.createElement("rect");
            background.setAttribute("x", "0");
            background.setAttribute("y", "0");
            background.setAttribute("width", String.valueOf(config.getWidth()));
            background.setAttribute("height", String.valueOf(config.getHeight()));
            background.setAttribute("fill", config.getBackgroundColor());
            svg.appendChild(background);
        }

        // 添加图形元素
        for (ShapeConfig shapeConfig : config.getShapes()) {
            Element shapeElement = createShapeElement(doc, shapeConfig);
            if (shapeElement != null) {
                svg.appendChild(shapeElement);
            }
        }

        // 保存SVG文件
        saveSvgFile(doc, filename);
        System.out.println("SVG文件已生成: " + filename);
    }

4.3 添加图形元素

通过config获取到图形类,判断type创建相应的元素对象,然后将元素对象添加到根元素中。

private static Element createShapeElement(Document doc, ShapeConfig config) {
        Element element = null;
        switch (config.getType()) {
            case "rect":
                element = createRectElement(doc, (RectConfig) config);
                break;
            case "text":
                element = createTextElement(doc, (TextConfig) config);
                break;
            default:
                System.out.println("不支持的图形类型: " + config.getType());
                return null;
        }
        return element;
    }

4.4 创建元素对象

矩形元素

private static Element createRectElement(Document doc, RectConfig config) {
        Element rect = doc.createElement("rect");
        rect.setAttribute("id", config.getId());
        rect.setAttribute("x", String.valueOf(config.getX()));
        rect.setAttribute("y", String.valueOf(config.getY()));
        rect.setAttribute("width", String.valueOf(config.getWidth()));
        rect.setAttribute("height", String.valueOf(config.getHeight()));
        rect.setAttribute("fill", config.getFill());

        if (config.getRx() > 0) {
            rect.setAttribute("rx", String.valueOf(config.getRx()));
        }
        if (config.getRy() > 0) {
            rect.setAttribute("ry", String.valueOf(config.getRy()));
        }
        if (!"none".equals(config.getStroke())) {
            rect.setAttribute("stroke", config.getStroke());
            rect.setAttribute("stroke-width", config.getStrokeWidth());
        }
        return rect;
    }

文本元素

private static Element createTextElement(Document doc, TextConfig config) {
        Element text = doc.createElement("text");
        text.setAttribute("id", config.getId());
        text.setAttribute("x", String.valueOf(config.getX()));
        text.setAttribute("y", String.valueOf(config.getY()));
        text.setAttribute("fill", config.getFill());
        text.setAttribute("font-family", config.getFontFamily());
        text.setAttribute("font-size", config.getFontSize());
        text.setTextContent(config.getContent());
        return text;
    }

4.5 保存svg文件

通过XML转换器工厂,配置输出属性(启用xml缩进、保留xml声明等),将svg的dom对象输出到文件中,完成dom到xml文件的转换。

private static void saveSvgFile(Document doc, String filename) throws Exception {
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();

        // 设置输出属性
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

        // 写入文件
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(new File(filename));
        transformer.transform(source, result);
    }

总结

本文仅仅介绍了如何生成一个简单的svg图,而Apache的Batik还有很多操作svg图的操作,例如解析一个已有的svg图,然后进行修改等操作,实际应用中不会如此简单的操作。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java处理科学计数法数字方式

    Java处理科学计数法数字方式

    这篇文章主要介绍了Java处理科学计数法数字方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Java多线Condition条件变量正确使用方法详解

    Java多线Condition条件变量正确使用方法详解

    这篇文章主要为大家,介绍了Java多线Condition条件变量正确使用方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Maven dependencies与dependencyManagement的区别详解

    Maven dependencies与dependencyManagement的区别详解

    这篇文章主要介绍了Maven dependencies与dependencyManagement的区别详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • java图片验证码实现示例分享

    java图片验证码实现示例分享

    这篇文章主要介绍了java实现图片验证码示例,需要的朋友可以参考下
    2014-02-02
  • IDEA中的.iml文件和.idea文件夹

    IDEA中的.iml文件和.idea文件夹

    这篇文章主要介绍了IDEA中的.iml文件和.idea文件夹,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • SpringBoot的跨域注解@CrossOrigin解析

    SpringBoot的跨域注解@CrossOrigin解析

    这篇文章主要介绍了SpringBoot的跨域注解@CrossOrigin解析,Spring Framework 4.2 GA为CORS提供了第一类支持,使您比通常的基于过滤器的解决方案更容易和更强大地配置它,所以springMVC的版本要在4.2或以上版本才支持@CrossOrigin,需要的朋友可以参考下
    2023-12-12
  • BeanUtils.copyProperties()拷贝id属性失败的原因及解决

    BeanUtils.copyProperties()拷贝id属性失败的原因及解决

    这篇文章主要介绍了BeanUtils.copyProperties()拷贝id属性失败的原因及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java Boolean 初始化方式详解

    Java Boolean 初始化方式详解

    这篇文章主要介绍了Java Boolean 初始化方式详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • Java递归如何正确输出树形菜单

    Java递归如何正确输出树形菜单

    这篇文章主要为大家详细介绍了Java递归如何正确输出树形菜单,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Mybatis实现分页查询的详细流程

    Mybatis实现分页查询的详细流程

    这篇文章主要给大家介绍了关于Mybatis实现分页查询的详细流程,MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架,需要的朋友可以参考下
    2023-08-08

最新评论