web 图片合成
1. 展示
2.原理
浏览器上一张图片作为背景,一张图片进行拖动。
然后点击下面按钮合成后,生成一张新的图片
- 前端通过拖动确定图片的位置
- 后端通过图片位置将两张图片合并成一张新的图片
- 前端通过下载,得到一张新的图片
3.前端
- 实现原理:将一张图片最为背景,另一张图片进行绝对定位,然后通过获取鼠标位置来确定图片的left 和top位置
- 背景图片有大有小,所以可以设定一个固定的宽和高,然后和实际的大小计算得到一个比值,然后传个后端
- 其他的就是元素位置的计算
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图片合成</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script th:src="@{/imgView/index.js}"></script>
<style>
body{
margin: 0;
}
.source{
width: 60%;
margin-left: 20%;
}
img{
object-fit: contain;
}
.submit-btn{
width: 200px;
height: 70px;
}
</style>
</head>
<body>
<div class="source" id="source">
<img id="sourceImg">
</div>
<div style="width: 100%;text-align: center">
<button id="submit-btn" class="submit-btn">合成</button>
</div>
</body>
</html>
var w_width,w_height,ratio
var result_x,result_y
window.onload = function () {
w_width = window.innerWidth
w_height = window.innerHeight
setSource()
.then(setTarget)
submitResult()
}
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.createElement('img')
img.setAttribute('src',imgSrc)
img.style.width = (ret.width * ratio) + 'px'
console.log('target width=',ret.width,(ret.width * ratio))
img.style.position = 'absolute'
img.style.top = '0px'
img.style.left = (w_width * 0.2) + 'px'
var source = document.getElementById('source')
source.append(img)
var moveFlag = false
img.onmousedown = function (ev){
moveFlag = !moveFlag
result_x = ev.clientX - w_width * 0.2
result_y = ev.clientY
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 imgTop = ev.clientY - ret.height/2 * ratio
var imgLeft = ev.clientX - ret.width/ 2* ratio
var imgWidth2 = ret.width/ 2* ratio
var imgHeight2 = ret.height/2 * ratio
if(imgLeft < w_width * 0.2){
imgLeft = w_width * 0.2
}
if(imgLeft + imgWidth2*2 > w_width * 0.8){
imgLeft = w_width * 0.8 - imgWidth2*2
}
if(imgTop <= 0){
imgTop = 0
}
if(imgTop + imgHeight2*2 > source.offsetHeight){
imgTop = source.offsetHeight - ret.height * ratio
}
img.style.top = imgTop + 'px'
img.style.left = imgLeft + 'px'
}
})
}
function setSource(){
return new Promise(function(resolve, reject){
http('/img/action/getSrc', {'name': 'bg.jpg'})
.then(function (res) {
var ret = res.data.data
var imgSrc = 'data:image/jpeg;base64,' + ret.baseStr
var img = document.getElementById('sourceImg')
img.setAttribute('src',imgSrc)
img.style.width = (w_width*0.6) + 'px'
ratio = (w_width*0.6)/ret.width
console.log('w_width=',w_width,'w_width*0.6=',w_width*0.6,'width=',ret.width,'ratio=',ratio)
//img.style.height = ret.height + 'px'
resolve()
})
})
}
function http(path, data) {
return axios.post(path, data)
}
function submitResult(){
document.getElementById('submit-btn')
.onclick = function(){
http('/img/action/submit', {'result_x':result_x,'result_y':result_y,'ratio':ratio,sourceImg:'bg.jpg',targetImg:'b.png'})
.then(function(){
})
}
}
4.后端
- 获取到位置进行合并,这里使用的是java 相对比较简单
double x = body.getDouble("result_x");
double y = body.getDouble("result_y");
double ratio = body.getDouble("ratio");
String sourceImg = body.getString("sourceImg");
String targetImg = body.getString("targetImg");
BufferedImage source = ImageIO.read(getFile(sourceImg));
BufferedImage target = ImageIO.read(getFile(targetImg));
Graphics2D graphics2D = source.createGraphics();
int width = (int) (x / ratio);
int height = (int) (y / ratio);
int tarWidth = target.getWidth();
int tarHeight = target.getHeight();
int start_x = width - tarWidth / 2;
int start_y = height - tarHeight / 2;
if (start_x < 0) {
start_x = 0;
}
if (start_y < 0) {
start_y = 0;
}
graphics2D.drawImage(target, start_x, start_y, tarWidth, tarHeight, null);
graphics2D.dispose();
ByteOutputStream out = new ByteOutputStream();
ImageIO.write(source, "png", out);
byte[] data = out.getBytes();
out.close();
Files.write(Paths.get("testImg.png"), data);
5.最后
最后就是做好的图片传给前端就好了