当前位置: 首页 > news >正文

基于DeepSeek实现PDF嵌入SVG图片无损放大

1. PDF中效果图

在这里插入图片描述

2. 询问Deepseek进行代码书写,不断优化后结果

/**
 * SVG工具类,用于生成价格趋势的SVG图表
 */
public class SvgUtils {

    // SVG画布尺寸
    private static final int WIDTH = 800;
    private static final int HEIGHT = 500;
    private static final int PADDING = 60;

    // 生成SVG折线图
    public static String generatePriceTrendSvg(List<PriceData> data, String title, String subtitle) {
        if (data.isEmpty()) {
            return "<svg xmlns='http://www.w3.org/2000/svg' width='" + WIDTH + "' height='" + HEIGHT + "'></svg>";
        }

        // 计算价格和时间的范围
        double minPrice = data.stream().mapToDouble(PriceData::getPrice).min().orElse(0) * 0.8;
        double maxPrice = data.stream().mapToDouble(PriceData::getPrice).max().orElse(1) * 1.2;

        // 解析最小和最大日期
        String minYearMonth = data.stream().map(PriceData::getYearmonth).min(String::compareTo).orElse("2024-06");
        String maxYearMonth = data.stream().map(PriceData::getYearmonth).max(String::compareTo).orElse("2025-01");

        // 构建SVG内容
        StringBuilder svg = new StringBuilder();
        svg.append(String.format("<svg xmlns='http://www.w3.org/2000/svg' width='%d' height='%d'>", WIDTH, HEIGHT));

        // 画背景
        svg.append(String.format("<rect width='%d' height='%d' fill='#ffffff'/>", WIDTH, HEIGHT));

        // 添加标题和副标题(居中显示)
        svg.append(String.format("<text x='%d' y='%d' font-size='20' font-family='Arial' fill='#333333' font-weight='bold' text-anchor='middle'>%s</text>",
                WIDTH / 2, 30, title));
        svg.append(String.format("<text x='%d' y='%d' font-size='14' font-family='Arial' fill='#666666' text-anchor='middle'>%s</text>",
                WIDTH / 2, 50, subtitle));

        // 画虚线网格线
        svg.append(drawGrid(minYearMonth, maxYearMonth, minPrice, maxPrice));

        // 画深色坐标轴
        svg.append(drawAxis(minYearMonth, maxYearMonth, minPrice, maxPrice));

        // 画浅色平滑折线
        svg.append(drawSmoothLine(data, minYearMonth, maxYearMonth, minPrice, maxPrice));

        svg.append("</svg>");
        return svg.toString();
    }

    // 画虚线网格线
    private static String drawGrid(String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        StringBuilder grid = new StringBuilder();

        // 水平网格线(价格)
        int numHorizontalLines = 5;
        for (int i = 0; i <= numHorizontalLines; i++) {
            double price = minPrice + (maxPrice - minPrice) * i / numHorizontalLines;
            int y = HEIGHT - PADDING - (int) ((price - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
            grid.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#e0e0e0' stroke-width='1' stroke-dasharray='5,5'/>",
                    PADDING, y, WIDTH - PADDING, y));
        }

        // 垂直网格线(时间)
        List<String> yearMonths = generateYearMonths(minYearMonth, maxYearMonth);
        for (String yearMonth : yearMonths) {
            int x = PADDING + (int) ((getMonthIndex(yearMonth) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (yearMonths.size() - 1));
            grid.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#e0e0e0' stroke-width='1' stroke-dasharray='5,5'/>",
                    x, PADDING, x, HEIGHT - PADDING));
        }

        return grid.toString();
    }

    // 画深色坐标轴
    private static String drawAxis(String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        StringBuilder axis = new StringBuilder();

        // X轴(时间)
        axis.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#333333' stroke-width='2'/>",
                PADDING, HEIGHT - PADDING, WIDTH - PADDING, HEIGHT - PADDING));

        // Y轴(价格)
        axis.append(String.format("<line x1='%d' y1='%d' x2='%d' y2='%d' stroke='#333333' stroke-width='2'/>",
                PADDING, PADDING, PADDING, HEIGHT - PADDING));

        // X轴标签
        List<String> yearMonths = generateYearMonths(minYearMonth, maxYearMonth);
        for (String yearMonth : yearMonths) {
            int x = PADDING + (int) ((getMonthIndex(yearMonth) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (yearMonths.size() - 1));
            axis.append(String.format("<text x='%d' y='%d' font-size='12' font-family='Arial' fill='#000000' text-anchor='middle'>%s</text>",
                    x, HEIGHT - PADDING + 20, yearMonth));
        }

        // Y轴标签
        int numYLabels = 5;
        for (int i = 0; i <= numYLabels; i++) {
            double price = minPrice + (maxPrice - minPrice) * i / numYLabels;
            int y = HEIGHT - PADDING - (int) ((price - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
            axis.append(String.format("<text x='%d' y='%d' font-size='12' font-family='Arial' fill='#000000' text-anchor='end'>%.2f</text>",
                    PADDING - 10, y + 5, price));
        }

        return axis.toString();
    }

    // 画浅色平滑折线
    private static String drawSmoothLine(List<PriceData> data, String minYearMonth, String maxYearMonth, double minPrice, double maxPrice) {
        if (data.size() < 2) {
            return "";
        }

        StringBuilder path = new StringBuilder("<path d='M");

        for (int i = 0; i < data.size(); i++) {
            PriceData point = data.get(i);
            int x = PADDING + (int) ((getMonthIndex(point.getYearmonth()) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (getMonthIndex(maxYearMonth) - getMonthIndex(minYearMonth)));
            int y = HEIGHT - PADDING - (int) ((point.getPrice() - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));

            if (i == 0) {
                path.append(x).append(",").append(y);
            } else {
                // 计算控制点以实现平滑效果
                PriceData prevPoint = data.get(i - 1);
                int prevX = PADDING + (int) ((getMonthIndex(prevPoint.getYearmonth()) - getMonthIndex(minYearMonth)) * (WIDTH - 2 * PADDING) / (getMonthIndex(maxYearMonth) - getMonthIndex(minYearMonth)));
                int prevY = HEIGHT - PADDING - (int) ((prevPoint.getPrice() - minPrice) * (HEIGHT - 2 * PADDING) / (maxPrice - minPrice));
                int ctrlX1 = (prevX + x) / 2;
                int ctrlY1 = prevY;
                int ctrlX2 = (prevX + x) / 2;
                int ctrlY2 = y;

                path.append(" C").append(ctrlX1).append(",").append(ctrlY1)
                        .append(" ").append(ctrlX2).append(",").append(ctrlY2)
                        .append(" ").append(x).append(",").append(y);
            }
        }

        path.append("' fill='none' stroke='#66B3FF' stroke-width='2'/>");
        return path.toString();
    }

    // 生成从 minYearMonth 到 maxYearMonth 的连续月份列表
    private static List<String> generateYearMonths(String minYearMonth, String maxYearMonth) {
        List<String> yearMonths = new ArrayList<>();
        int year = Integer.parseInt(minYearMonth.substring(0, 4));
        int month = Integer.parseInt(minYearMonth.substring(5));

        while (true) {
            yearMonths.add(String.format("%04d-%02d", year, month));
            if (yearMonths.get(yearMonths.size() - 1).equals(maxYearMonth)) {
                break;
            }
            month++;
            if (month > 12) {
                month = 1;
                year++;
            }
        }

        return yearMonths;
    }

    // 将 yearmonth 转换为索引(从 0 开始)
    private static int getMonthIndex(String yearMonth) {
        int year = Integer.parseInt(yearMonth.substring(0, 4));
        int month = Integer.parseInt(yearMonth.substring(5));
        return (year - 2024) * 12 + (month - 1); // 假设最小年份是 2024
    }

    public static void main(String[] args) {
        List<PriceData> data = PriceData.getSampleData();
        String title = "价格走势图";
        String subtitle = "2024-06 至 2025-01";
        String svg = SvgUtils.generatePriceTrendSvg(data, title, subtitle);
        System.out.println(svg);
    }
}
@Data
public class PriceData {
    private String yearmonth;
    private Double price;

    public PriceData() {}

    public PriceData(String yearmonth, Double price) {
        this.yearmonth = yearmonth;
        this.price = price;
    }

    public static List<PriceData> getSampleData() {
        List<PriceData> data = new ArrayList<>();
        data.add(new PriceData("2025-01", 100.0)); // 2023-01-01
        data.add(new PriceData("2025-02", 105.0)); // 2023-01-02
        data.add(new PriceData("2025-03", 102.0)); // 2023-01-03
        data.add(new PriceData("2025-04", 110.0)); // 2023-01-04
        data.add(new PriceData("2025-05", 108.0)); // 2023-01-05
        return data;
    }
}

OK, 生成的SVG嵌入到html网页中进行渲染即可

相关文章:

  • CarPlanner:用于自动驾驶大规模强化学习的一致性自回归轨迹规划
  • 修改jupyter notebook的工作空间
  • HCIA复习拓扑实验
  • 兴业银行的笔试题及答案(2025)
  • 数据安全防线:备份文件的重要性与自动化实践
  • 计算机组成原理:数据表示的基本概念
  • 如何在Ubuntu上直接编译Apache Doris
  • mysql虚拟列
  • 基于SpringBoot的商城管理系统(源码+部署教程)
  • .Net 6 上传文件接口 文件大小报错整体配置
  • ARMv8寄存器的介绍
  • 【十三】Golang 通道
  • 机器始终是一个机器:技术本质与哲学边界
  • l c a
  • 数据安全基石:备份文件的重要性与自动化实践
  • Elasticsearch:使用 BigQuery 提取数据
  • C语言-文件操作 文件的随机读写
  • Ubuntu 下 nginx-1.24.0 源码分析 - cycle->modules[i]->type
  • P8662 [蓝桥杯 2018 省 AB] 全球变暖--DFS
  • Nginx(基础安装+配置文件)
  • 电子商务网站与建设实践报告/什么样的人适合做策划
  • 石家庄市网站建设培训班/整站排名优化公司
  • 做网站游戏需要什么/百度客服人工在线咨询
  • 沈北新区建设局网站/手机怎么建自己的网站
  • 斗鱼网站的实时视频是怎么做的/优化seo设置
  • 园林景观设计公司需要什么资质/长沙 建站优化