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.innerWidthw_height = window.innerHeightsource(0)}function downFile(){var page = parseInt(document.getElementById('now-page').innerHTML) -1http('/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.datavar imgSrc = 'data:image/jpeg;base64,' + ret.baseStrvar 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 = falseimg.onmousedown = function (ev){moveFlag = !moveFlagresult_x = ev.pageX - l_widthresult_y = ev.pageYif(moveFlag){img.style.opacity = 0.8img.style.filter = 'alpha(opacity=80)'}else{img.style.opacity = 1img.style.filter = 'alpha(opacity=100)'}}source.onmousemove = function (ev){if(!moveFlag){return}var sourceWidth = source.offsetWidthvar sourceHeight = source.offsetHeightvar imgHeight2 = ret.height/2var imgTop = ev.pageY  - imgHeight2var imgLeft = ev.pageX - ret.width/2if(imgLeft < l_width){imgLeft = l_width}g_scale_x = ret.width/sourceWidthg_scale_y = ret.height/sourceHeightif(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+1btn.className = 'btn-list'btn.setAttribute('data-number',i)btn.onclick=clickPagediv.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.datag_total = ret.sizevar 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.widthpageHeight = ret.heightsource.style.width = ret.widthsource.style.height = ret.heightsource.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)/2left.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+1document.getElementById('total').innerHTML = ret.sizesetPage()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.需要源码的可以私信我或者留下邮箱

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 107.二叉树的层次遍历 II

题目描述 给你二叉树的根节点 root &#xff0c;返回其节点值 自底向上的层序遍历 。 &#xff08;即按从叶子节点所在层到根节点所在的层&#xff0c;逐层从左向右遍历&#xff09; 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[1…

【力扣专题栏】两数相加,如何实现存储在链表中的整数相加?

题解目录 1、题目描述解释2、算法原理解析3、代码编写&#xff08;原始版本&#xff09;4、代码编写&#xff08;优化版本&#xff09; 1、题目描述解释 2、算法原理解析 3、代码编写&#xff08;原始版本&#xff09; /*** Definition for singly-linked list.* struct ListN…

快速上手机器学习-朴素贝叶斯

朴素贝叶斯 引言&#xff1a;本文通过介绍先验概率&#xff0c;后验概率&#xff0c;条件概率计算和贝叶斯定理等概率论内容引入朴素贝叶斯分类算法的基本思路&#xff0c;朴素贝叶斯的最终分类思想是将输入分类给概率最大的类&#xff0c;这也是概率模型算法的共有思想。本文专…

JVM(HotSpot):GC之G1垃圾回收器

文章目录 一、简介二、工作原理三、Young Collection 跨代引用四、大对象问题 一、简介 1、适用场景 同时注重吞吐量&#xff08;Throughput&#xff09;和低延迟&#xff08;Low latency&#xff09;&#xff0c;默认的暂停目标是 200 ms超大堆内存&#xff0c;会将堆划分为…

第12次CCF CSP认证真题解

1、最小差值 题目链接&#xff1a;https://sim.csp.thusaac.com/contest/12/problem/0 100分代码&#xff1a; #include <iostream> #include <algorithm> using namespace std; int main(int argc, char *argv[]) {int n;cin >> n;int a[1010],b[1010];f…

【读书笔记·VLSI电路设计方法解密】问题28:什么是芯片可靠性

一块VLSI芯片不仅需要在前几天、几周或几个月内正常工作,还必须在整个使用寿命内可靠运行。任何用于商业目的的芯片的寿命通常定义为100,000小时或约11.4年。然而,在IC的设计、制造、组装和测试过程中,许多因素可能导致其早期失效。这一芯片开发方面被称为芯片可靠性。测试相…

LinkedList和链表之刷题课(下)

1. 给定x根据x把链表分割,大的结点放在x后面,小的结点放在x前面 题目解析: 注意此时的pHead就是head(头节点的意思) 基本上就是给定一个链表,我们根据x的值来把这个链表分成俩部分,大的那部分放在x后面,小的那部分放在x前面,并且我们不能改变链表本来的顺序,比如下面的链表,我…

【数据结构与算法】《Java 算法宝典:探秘从排序到回溯的奇妙世界》

目录 标题&#xff1a;《Java 算法宝典&#xff1a;探秘从排序到回溯的奇妙世界》一、排序算法1、冒泡排序2、选择排序3、插入排序4、快速排序5、归并排序 二、查找算法1、线性查找2、二分查找 三、递归算法四、动态规划五、图算法1. 深度优先搜索&#xff08;DFS&#xff09;2…

Ubuntu22.04环境搭建MQTT服务器

官网&#xff1a; https://mosquitto.org 1.引入库 sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa2.升级安装工具 sudo apt-get update 3.安装 sudo apt-get install mosquitto 4.安装客户端 sudo apt-get install mosquitto-clients5.添加修改配置文件 进…

MySql数据库中数据类型

本篇将介绍在 MySql 中的所有数据类型&#xff0c;其中主要分为四类&#xff1a;数值类型、文本和二进制类型、时间日期、String 类型。如下&#xff08;图片来源&#xff1a;MySQL数据库&#xff09;&#xff1a; 目录如下&#xff1a; 目录 数值类型 1. 整数类型 2. …

Python | Leetcode Python题解之第516题最长回文子序列

题目&#xff1a; 题解&#xff1a; class Solution:def longestPalindromeSubseq(self, s: str) -> int:n len(s)dp [[0] * n for _ in range(n)]for i in range(n - 1, -1, -1):dp[i][i] 1for j in range(i 1, n):if s[i] s[j]:dp[i][j] dp[i 1][j - 1] 2else:dp…

【java】java的基本程序设计结构04-数值类型的转换

类型默认值 int, short, long, byte 的默认值是0。char 的默认值是 \u0000&#xff08;空字符&#xff09;。float 的默认值是 0.0f。double 的默认值是 0.0d。boolean 的默认值是 false。引用类型&#xff08;类、接口、数组&#xff09;的默认值是 null。 引用类型 在Java中…

Kafka如何控制消费的位置?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka如何控制消费的位置?】面试题&#xff1f;希望对大家有帮助&#xff1b; Kafka如何控制消费的位置? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Kafka 中&#xff0c;控制消费位置主要通过以下几个机制来实…

C++-继承

目录 一、继承的概念和定义 1、继承概念 2、继承的语法格式 3、继承的方式 4、继承类模板 二、基类和派生类之间的转换 三、继承中的作用域 四、派生类的默认成员函数 一、默认成员函数介绍 1、派生类中基类成员的构造 2、派生类中基类成员拷贝构造 3、复制重载 4、…

帝佛卡干邑荣耀登陆泰国王权King Power

帝佛卡干邑与泰国王权免税集团&#xff08;King Power&#xff09;达成深度合作&#xff0c;共同将法国帝佛卡干邑品牌推向泰国旅游零售市场。此次合作不仅标志着帝佛卡干邑在国际市场的又一重要突破&#xff0c;也彰显了双方对高品质产品的共同追求。 帝佛卡干邑于2024年8月正…

[Python学习日记-53] Python 中的正则表达式模块 —— re

[Python学习日记-53] Python 中的正则表达式模块 —— re 简介 re 模块 练习 简介 我们在编程的时候经常会遇到想在一段文字当中找出电话号码、身份证号、身高、年龄之类的信息&#xff0c;就像下面的数据一样 # 文件名&#xff1a;美丽学姐联系方式.txt 姓名 地区 …

WinRAR技巧:如何独立压缩文件夹内的每个文件?

不知道大家是否会遇到这种情况&#xff0c;将文件夹内的多个文件或文件夹压缩成一个个压缩包文件&#xff0c;这种情况除了将文件夹中的文件一个个压缩&#xff0c;还有什么批量操作的方法呢&#xff1f;今天分享使用WinRAR批量压缩文件到每个单独的文件夹的方法。 方法如下&a…

pdf压缩如何操作?教你8招,轻松搞定文件压缩!

电脑上如果存有大量的pdf文件&#xff0c;那么一定会占用一定的空间&#xff0c;不仅不利于存储还影响传输速度。如果想要将pdf压缩变小&#xff0c;那么本文分享的内容可就要了解下了。 PDF文件怎么压缩变小&#xff1f;pdf压缩是一种常见的文件处理需求。无论是处理个人文档…

offset Explorer连接云服务上的kafka连接不上

以上配置后报连接错误时&#xff0c;可能是因为kafka的server.properties配置文件没配置好&#xff1a; 加上面两条配置&#xff0c;再次测试连接&#xff0c;成功 listeners和advertised.listeners

DICOM 基础知识:深入理解DICOM数据结构与标签说明

目录 DICOM 图像概念 DICOM 图像关键特性&#xff1a; DICOM 文件结构 常见数据元素&#xff1a; 数据元素示例详解 DICOM-VR 数据类型说明 DICOM 标准支持的数据集 结语 DICOM 图像概念 DICOM&#xff08;Digital Imaging and Communications in Medicine&…