有时候想给某张图片添加一个自己的水印,但是又懒的下载相应软件,用js canvas制作一个静态页面,对于单张图片添加自定义文字水印,大小 间距,角度可调。
页面如下:
选择图片,设置相应参数,点击添加水印:
效果:
完整程序如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>添加水印</title>
<link rel="shortcut icon" href="https://img1.imgtp.com/2024/01/09/BKw2wjPL.png" type="image/x-icon">
<style>
body {
background-color: #c8adc4;
}
.ml-5 {
margin-left: 15px;
}
.container {
display: flex;
justify-content: space-between;
/* 使两个 div 平均分布在容器中 */
}
.box {
width: 49.5%;
/* 或根据需要设置 */
/* 其他样式 */
}
#canvas {
border: 2px solid rgb(210, 208, 208);
width: 95%;
height: auto;
overflow: hidden;
}
#p {
margin-top: 20px;
width: 95%;
height: auto;
}
#canvas img {
width: 100%;
height: 100%;
object-fit: cover;
}
#imageUpload {
height: auto;
width: auto;
font-size: 16px;
}
</style>
</head>
<body>
<div class="container">
<div class="box">
<div style="border: 2px solid #c9c9c9cc; padding: 10px;">
<div>
<input type="file" id="imageUpload" style="color: rgb(249, 137, 109); margin-left: 40%;">
</div>
<div style="margin-left: 10%;margin-top: 30px;">
<span>大小:</span><input type="text" placeholder="修改水印大小" style="height: 24px;width: 100px;"
value="100" id="ipt1">
<span class="ml-5">透明度:</span><input type="text" placeholder="范围1~10"
style="height: 24px;width: 100px;" value="5" id="ipt2">
<span class="ml-5">间距:</span><input type="text" placeholder="范围1-10"
style="height: 24px;width: 100px;" value="5" id="ipt3">
</div>
<div style="margin-top: 20px;margin-left: 10%;">
<span class="ml-5">倾斜方向:</span>
<select id="s2">
<option value="left">左倾斜</option>
<option value="right">右倾斜</option>
</select>
<span class="ml-5">倾斜角度:</span>
<input type="text" placeholder="修改倾斜大小" style="height: 20px;width: 30px;" value="30" id="ipt4"><span
style="margin-left: 5px; ;">度</span>
</div>
<div style="margin-left: 10%;margin-top: 40px;">
文本:<input type="text" id="watermarkText" placeholder="请输入水印内容" style="height: 24px;">
<button id="confirmButton"
style="margin-left: 100px; width: 80px;height: 30px;background-color: rgb(127, 214, 255);color: white;font-size: 16px;border: none;border-radius: 5px;">添加水印</button>
<button id="saveButton"
style="width: 60px;height: 30px;background-color: rgb(28, 119, 161);color: white;font-size: 16px;border: none;border-radius: 5px;">下载</button>
<button id="reflash" onclick="flush()"
style="width: 80px;height: 30px;background-color: rgb(248, 126, 81);color: white;font-size: 16px;border: none;border-radius: 5px;">重置页面</button>
</div>
</div>
<span style="color: rgb(255, 255, 255); font-weight: bold;font-size: 20px;">原图:</span>
<img id="p"></img>
</div>
<div class="box">
<span style="color: rgb(255, 255, 255); font-weight: bold;font-size: 20px;">预览框:</span>
<canvas id="canvas"></canvas>
</div>
</div>
<script>
//回显
document.getElementById('imageUpload').addEventListener('change', function (e) {
var reader = new FileReader();
reader.onload = function (e) {
document.getElementById('p').src = e.target.result;
document.getElementById('p').style.display = 'block';
}
reader.readAsDataURL(e.target.files[0]);
})
//添加水印
document.getElementById('confirmButton').addEventListener('click', function () {
var image = document.getElementById('imageUpload').files[0]; //图片对象
var watermarkText = document.getElementById('watermarkText').value; //水印对象
var canvas = document.getElementById('canvas'); //canvas
var ctx = canvas.getContext('2d');
var img = new Image(); //img对象
var fontsize = document.getElementById('ipt1').value; //初始大小
var transparency = document.getElementById('ipt2').value / 10; //透明度
var jianju = document.getElementById('ipt3').value; //间距
//单行多行
//倾斜方式
var tilt = document.getElementById('s2').value;
var angle = document.getElementById('ipt4').value;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
ctx.font = fontsize + 'px Arial'; //大小 字体
ctx.fillStyle = `rgba(170, 171, 172, ${transparency})`;
if (tilt === 'left') painWatermarket_left(watermarkText, canvas, jianju, ctx, angle);
if (tilt === 'right') painWatermarket_right(watermarkText, canvas, jianju, ctx, angle);
};
img.src = URL.createObjectURL(image);
});
// 单行左倾斜params: watermarkText canvas jianju\
function painWatermarket_left(watermarkText, canvas, jianju, ctx, angle, lineNumber) {
var txtLen = Math.ceil(ctx.measureText(watermarkText).width / 2);
for (var i = 150 - txtLen, j = 150 - txtLen;
i < canvas.width, j < canvas.height;
i += canvas.width / jianju, j += canvas.height / jianju) {
ctx.save();
ctx.translate(i, j);
ctx.rotate(angle * Math.PI / 180);
ctx.fillText(watermarkText, 0, 0);
ctx.restore();
}
}
// 单行右倾斜params: watermarkText canvas jianju
function painWatermarket_right(watermarkText, canvas, jianju, ctx, angle) {
angle = -1 * angle;
var txtLen = Math.ceil(ctx.measureText(watermarkText).width / 2); //文本宽度
for (var i = 150 - txtLen, j = canvas.height; i < canvas.width, j > 150 - txtLen; i += canvas.width / jianju, j -= canvas.height / jianju) {
ctx.save();
ctx.translate(i, j);
ctx.rotate(angle * Math.PI / 180);
ctx.fillText(watermarkText, 0, 0);
ctx.restore();
}
}
//保存
document.getElementById('saveButton').addEventListener('click', function () {
var canvas = document.getElementById('canvas');
var dataUrl = canvas.toDataURL('image/png');
var blob = dataURItoBlob(dataUrl);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'demo.png';
link.click();
});
function dataURItoBlob(dataURI) {
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
}
//重置
function flush() {
location.reload();
}
</script>
</body>
</html>