web pdf 图片拖动图片合成

web pdf 图片拖动图片合成

先看效果
前端

在这里插入图片描述
合成后

在这里插入图片描述

1.原理

以前写过相关的帖子,使用的是 canva
但是这次换了一个思路使用的是图片
1.先把pdf转成图片
2.把pdf图片和目标图片传到浏览器
3.原理就和图片合成一样了。见上一篇帖子
4.后端也一样只不过这次是将位置和pdf进行合并

2. 前端

这里要注意pdf的比例是和图片不一样的,转换的时候要把比例传过来
目标图片的比例要保持一致
这样才能保证浏览器图片的大小和pdf中图片大小一致

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <style>

        body{
            margin: 0;
        }

        #pdfContent {
            width: 100%;
        }
        #pdf-page{

        }
        .tool{
            text-align: center;
            padding: 5rem 0 0 0;
            font-size: 30px;
            line-height: 2;
            background-color: aliceblue;

        }
        #btn-list{
            padding: 2rem;
        }
        .btn-list{
            padding: 0.5rem;
            margin: 0.2rem;
        }
    </style>
</head>
<body>
<div id="pdfContent">
    <div id="pdf-left" class="tool">
        <div>
            当前页:<span id="now-page"></span>
        </div>
        <div>
            总页数:<span id="total"></span>
        </div>
        <div id="btn-list"></div>
    </div>
    <div id="pdf-page" >
        <img id="img">
    </div>
    <div id="pdf-right" class="tool ">
        <button class="btn-list" onclick="downFile()">合成并下载</button>
    </div>
</div>
<script th:src="@{/imgView/pdfIndex.js}"></script>
</body>
</html>
var w_width,w_height,g_total,l_width
var result_x,result_y
var g_scale_x,g_scale_y
var pageWidth,pageHeight
var g_pdfName = 'pdf.pdf'
window.onload = function(){
    w_width = window.innerWidth
    w_height = window.innerHeight
    source(0)

}

function downFile(){
    var page = parseInt(document.getElementById('now-page').innerHTML) -1
    http('/img/action/submitPdf',
        {
            'page': page,
            'result_x':result_x,
            'result_y':result_y,
            'targetName':'b.png',
            'pdfName':g_pdfName,
            'scale_x':g_scale_x,
            'scale_y':g_scale_y,
            'pageWidth':pageWidth,
            'pageHeight':pageHeight
        })
        .then(function(){
            alert('生成成功')
        })

}

function setTarget(){
    http('/img/action/getSrc', {'name': 'b.png'})
        .then(function (res) {
            var ret = res.data.data
            var imgSrc = 'data:image/jpeg;base64,' + ret.baseStr
            var img = document.getElementById('target-img')
            if(img){
                img.remove();
            }
            img = document.createElement('img')
            img.id='target-img'
            img.setAttribute('src',imgSrc)
            img.style.width = ret.width + 'px'
            img.style.height = ret.height + 'px'
            img.style.position = 'absolute'
            img.style.top = '0px'
            img.style.left = l_width + 'px'
            var source = document.getElementById('pdf-page')
            source.append(img)
            var moveFlag = false
            img.onmousedown = function (ev){
                moveFlag = !moveFlag
                result_x = ev.pageX - l_width
                result_y = ev.pageY

                if(moveFlag){
                    img.style.opacity = 0.8
                    img.style.filter = 'alpha(opacity=80)'
                }else{
                    img.style.opacity = 1
                    img.style.filter = 'alpha(opacity=100)'
                }
            }

            source.onmousemove = function (ev){
                if(!moveFlag){
                    return
                }
                var sourceWidth = source.offsetWidth
                var sourceHeight = source.offsetHeight

                var imgHeight2 = ret.height/2
                var imgTop = ev.pageY  - imgHeight2
                var imgLeft = ev.pageX - ret.width/2

                if(imgLeft < l_width){
                    imgLeft = l_width
                }

                g_scale_x = ret.width/sourceWidth
                g_scale_y = ret.height/sourceHeight
                if(imgLeft - l_width > sourceWidth - ret.width){
                    imgLeft =  sourceWidth + l_width  - ret.width
                }

                if(imgTop  <= 0){
                    imgTop = 0
                }

                if(imgTop > sourceHeight - imgHeight2){
                    imgTop = sourceHeight - ret.height
                }
                img.style.top =   imgTop + 'px'
                img.style.left = imgLeft + 'px'
            }
        })
}

function setPage(){
    var div = document.getElementById('btn-list')
    div.innerHTML = ''
    for(var i=0;i<g_total;i++){
        var btn = document.createElement('button')
        btn.innerHTML = i+1
        btn.className = 'btn-list'
        btn.setAttribute('data-number',i)
        btn.onclick=clickPage
        div.appendChild(btn)
    }
}

function clickPage(){
    source(parseInt(this.innerHTML)-1)
}

function source(page){
    http('/img/action/pdf/img', {'name': g_pdfName,'page':page})
        .then(function(res){
            var ret = res.data.data
            g_total = ret.size
            var img = document.getElementById('img')
            img.setAttribute('src','data:image/jpeg;base64,' + ret.baseStr)
            var source = document.getElementById('pdf-page')
            img.style.width = ret.width + 'px'
            img.style.height = ret.height + 'px'
            document.getElementById('pdfContent').style.height = ret.width + 'px'
            pageWidth = ret.width
            pageHeight = ret.height
            source.style.width = ret.width
            source.style.height = ret.height
            source.style.float = 'left'
            var left = document.getElementById('pdf-left')
            var right = document.getElementById('pdf-right')
            console.log(left.getBoundingClientRect())
            l_width = (w_width - ret.width)/2
            left.style.width = l_width + 'px'
            right.style.width = (l_width-20) + 'px'
            left.style.height = ret.height + 'px'
            right.style.height = ret.height + 'px'
            left.style.float = 'left'
            right.style.float = 'left'
            document.getElementById('now-page').innerHTML = ret.page+1
            document.getElementById('total').innerHTML = ret.size
            setPage()
            setTarget()
        })
}


function http(path, data) {
    return axios.post(path, data)
}

3.后端

public void submitPdf(JSONObject body) throws IOException {
        int pageNum = body.getInteger("page");
        float result_x = body.getFloat("result_x");
        float result_y = body.getFloat("result_y");
        float scale_x = body.getFloat("scale_x");
        float scale_y = body.getFloat("scale_y");
        File tarImg = getFile(body.getString("targetName"));
        File pdfFile = new File(ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX).getPath() + body.getString("pdfName"));
        PDDocument document = PDDocument.load(pdfFile);

        PDPage page = document.getPage(pageNum);
        PDPageContentStream contentStream = new PDPageContentStream(document,page,PDPageContentStream.AppendMode.APPEND,false,false);
        PDImageXObject image = PDImageXObject.createFromByteArray(document, Files.readAllBytes(tarImg.toPath()),"插入图片");

        float pageWidth = page.getMediaBox().getWidth();
        float pageHeight = page.getMediaBox().getHeight();

        float imageWidth = pageWidth * scale_x;
        float imageHeight = pageHeight *scale_y;


        BufferedImage bufferedImage = ImageIO.read(tarImg);
        image.setWidth(bufferedImage.getWidth());
        image.setHeight(bufferedImage.getHeight());
        float x = result_x/scale - imageWidth/2;
        float y = result_y/scale;

        contentStream.drawImage(image,x,pageHeight-y- imageHeight/2,imageWidth,imageHeight);
        contentStream.close();
        new File("new.pdf").delete();
        document.save(new FileOutputStream("new.pdf"));
        document.close();

4.最后

我这里使用的是pdfbox 当然pdf相关的类库很多,可以用其他的

5.需要源码的可以私信我或者留下邮箱

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/899575.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IntelliJ IDEA 常用快捷键详解与自定义修改方法

目录 前言1. IntelliJ IDEA 常用快捷键1.1 代码编辑快捷键1.2 代码导航快捷键1.3 重构快捷键1.4 调试快捷键 2. 如何修改 IntelliJ IDEA 快捷键2.1 打开快捷键设置界面2.2 查找和修改快捷键2.3 导入和导出快捷键配置 结语 前言 IntelliJ IDEA 是一款广受开发者欢迎的集成开发环…

vue2之混入(mixin)

Vue 2 的混入&#xff08;Mixin&#xff09;是一种在 Vue 组件中分发可复用功能的方式。通过混入&#xff0c;你可以将一些通用的组件选项&#xff08;如数据、方法、计算属性、生命周期钩子等&#xff09;提取到一个混入对象中&#xff0c;并在多个组件中重用这些选项&#xf…

基于Python大数据的招聘数据分析及大屏可视化系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

2024软考-《软件设计师》-易混淆知识点总结(1~6章)

一、计算机组成与体系结构 1.1、原码、反码、补码、移码的运算 原码&#xff1a;最高位表示符号位&#xff0c;其余低位表示数值的绝对值&#xff08;0表示正数&#xff0c;1表示负数&#xff09; 反码&#xff1a;正数的反码与原码相同&#xff0c;负数的反码是其绝对值按位…

基于ESP32的RGB便携式视频灯

基于ESP32的RGB便携式视频灯 拥有一套能够满足个人需求的灯光设备至关重要。市面上的RGB视频灯虽然功能强大&#xff0c;但往往价格不菲。我制作的这款灯是20W RGB便携式视频灯不仅满足了我的需求&#xff0c;而且成本仅为市售产品的三分之一。接下来&#xff0c;我将详细介绍这…

大模型开发实战1-QuickStart

0. 关于大模型和模型选择 由于OpenAI的ChatGPT流行&#xff0c;AI技术在大模型技术的赋能下高速发展&#xff0c;特别是2023年至今&#xff0c;国内的AI技术发展更是前所未有的景象&#xff0c;各大公司争相发布自己的大模型&#xff0c;包括百度文心一言&#xff0c;阿里同义…

正版CST电磁仿真软件:保障创新与合规的基石

在当今快速发展的科技时代&#xff0c;电磁仿真技术对于电子产品的设计、测试和优化至关重要。CST电磁仿真软件以其强大的功能和广泛的应用领域&#xff0c;成为众多企业和研究机构不可或缺的工具。然而&#xff0c;在选择使用CST软件时&#xff0c;确保使用正版软件不仅是对知…

【C++】红黑树的底层原理以及实现

#1024程序员节 | 征文# 个人主页&#xff1a;夜晚中的人海 文章目录 ⭐前言&#x1f686;一、红黑树的概念&#x1f3e0;二、红黑树的规则&#x1f384;三、红黑树的效率&#x1f3a1;四、红黑树的实现1. 基本框架2. 插入操作• 变色• 单旋 变色• 双旋 变色 3. 查找操作4. …

玄机平台-应急响应-webshell查杀

首先xshell连接 然后进入/var/www/html目录中&#xff0c;将文件变成压缩包 cd /var/www/html tar -czvf web.tar.gz ./* 开启一个http.server服务&#xff0c;将文件下载到本地 python3 -m http.server 放在D盾中检测 基本可以确认木马文件就是这四个 /var/www/html/shell.p…

高效实现聚水潭数据集成MySQL的技术案例

聚水潭奇门数据集成到MySQL的技术案例分享 在现代企业的数据管理中&#xff0c;如何高效、准确地实现不同系统之间的数据对接是一个关键问题。本文将聚焦于一个实际的系统对接集成案例&#xff1a;将聚水潭奇门平台的售后单数据集成到MySQL数据库中&#xff0c;具体方案名称为…

JVM—类的生命周期

目录 类的生命周期 加载阶段 连接阶段 验证阶段 准备阶段 解析阶段 初始化阶段 面试题1 面试题2 类的生命周期 类的生命周期描述了一个类加载、使用、卸载的整个过程&#xff0c;整体可以分为以下五个阶段。 1. 加载 2. 连接&#xff0c;其中又分为验证、准备、解析三…

Python学习的自我理解和想法(21)

学的是b站的课程&#xff08;千锋教育&#xff09;&#xff0c;跟老师写程序&#xff0c;不是自创的代码&#xff01; 今天是学Python的第21天&#xff0c;学的内容是文件的操作。开学了&#xff0c;时间不多&#xff0c;写得不多&#xff0c;见谅。 目录 1.文件 (1).参数…

Tcp_Sever(线程池版本的 TCP 服务器)

Tcp_Sever&#xff08;线程池版本的 TCP 服务器&#xff09; 前言1. 功能介绍及展示1.1 服务端连接1.2 客户端连接&#xff08;可多个用户同时在线连接服务端&#xff09;1.3 功能服务1.3.1 defaultService&#xff08;默认服务&#xff09;1.3.2 transform&#xff08;大小写转…

Rust与Javascript的使用对比

一、常量 RustJavascriptletconst 二、变量 RustJavascriptlet mutlet / var 三、常用打印 RustJavascriptprintln!(“换行”);console.log(‘hello’);print!(“不换行”);console.info(‘信息’);-console.error(‘错误’);-console.warn(‘警告’); 四、定义字符串 R…

开放式耳机哪个品牌音质好?高评分爆款开放式耳机推荐!

一直活跃在蓝牙耳机圈子里的我&#xff0c;对各种类型的耳机多少都有自己的看法&#xff0c;完全可以说是个耳机狂热者。近几年&#xff0c;开放式蓝牙耳机愈发火爆。开放式耳机不是任何品牌都能轻松做好的产品&#xff0c;特别是音质&#xff0c;它涵盖了核心单元技术等诸多方…

负载均衡服务器攻击怎么解决最有效?

负载均衡服务器攻击怎么解决最有效&#xff1f;常见的有效解决方法包括&#xff1a;使用SYNCookie机制、限制ICMP包速率、基于源IP的连接速率限制、检测并丢弃异常IP包、配置访问控制列表&#xff08;ACL&#xff09;、设置虚拟服务器/服务器连接数量限制、设置HTTP并发请求限制…

ABAQUS应用11——支座弹簧

文章目录 0、背景1、ABAQUS中几类弹簧的简介2、SPRING1的性质初探 0、背景 1、ABAQUS中几类弹簧的简介 先说参考来源&#xff0c;ABAQUS2016的帮助文档里第4卷&#xff0c;32.1.1节&#xff0c;有三种弹簧&#xff08;SPRING1 、SPRING2 以及SPRINGA&#xff09;。 三种弹簧里…

C for Graphic:视差渲染(一)

记录一下最近优化场景的做法&#xff1a;视差渲染 原理&#xff1a;通过视口坐标的变化&#xff0c;观察不同采样画面的功能&#xff0c;画面的载体为低模平面 我早期工作&#xff0c;在小作坊全栈的时候&#xff0c;做过一段时间web开发&#xff0c;做了一个古董藏…

【传知代码】机器学习在情绪预测中的应用(论文复现)

在科技迅猛发展的今天&#xff0c;我们不仅在追求更强大的计算能力和更高的精度&#xff0c;还希望我们的机器能够理解和回应我们复杂的情感世界。设想一下&#xff0c;当你面对挫折时&#xff0c;设备不仅能识别你的情绪&#xff0c;还能以一种富有同情心和洞察力的方式作出反…

开放式耳机哪个牌子好?开放式蓝牙耳机排行榜分享

​耳机已经成为我们日常生活中的必需品&#xff0c;但长时间佩戴传统入耳式耳机可能会导致耳朵不适&#xff0c;甚至影响健康。为了应对这一挑战&#xff0c;开放式耳机应运而生。这类耳机不侵入耳道&#xff0c;有效减轻了耳朵的压力&#xff0c;同时减少了感染风险&#xff0…