可视化页面预览效果图
🎨 碎碎念:实用就好,没有添加什么乱七八糟的样式
🧨 声明:代码由DS生成,稍作调试之后即可直接使用
🎆 更多定制化功能问题,欢迎留言谈论交流~
图片多行水印添加完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片多行水印添加工具</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.container {
display: flex;
flex-direction: column;
gap: 20px;
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.control-group {
display: flex;
flex-direction: column;
}
textarea {
height: 100px;
}
canvas {
max-width: 100%;
border: 1px solid #ddd;
}
button {
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
font-size: 16px;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h1>图片多行水印添加工具</h1>
<div class="controls">
<div class="control-group">
<label for="imageInput">选择图片:</label>
<input type="file" id="imageInput" accept="image/*">
</div>
<div class="control-group">
<label for="watermarkText">水印文字 (多行):</label>
<textarea id="watermarkText">第一行水印\n第二行水印\n第三行水印</textarea>
</div>
<div class="control-group">
<label for="fontSize">字体大小 (px):【建议56】</label>
<input type="number" id="fontSize" value="24" min="10" max="100">
</div>
<div class="control-group">
<label for="fontColor">字体颜色:</label>
<input type="color" id="fontColor" value="#FFFFFF">
</div>
<div class="control-group">
<label for="backgroundColor">背景颜色 (透明):</label>
<input type="color" id="backgroundColor" value="#000000">
</div>
<div class="control-group">
<label for="opacity">透明度 (0-1):【建议0.1】</label>
<input type="number" id="opacity" value="0.5" min="0" max="1" step="0.1">
</div>
<div class="control-group">
<label for="angle">旋转角度 (度):【建议-45】</label>
<input type="number" id="angle" value="30" min="-180" max="180">
</div>
<div class="control-group">
<label for="fontFamily">字体:</label>
<select id="fontFamily">
<option value="Arial">Arial</option>
<option value="Microsoft YaHei">微软雅黑</option>
<option value="SimSun">宋体</option>
<option value="SimHei">黑体</option>
<option value="KaiTi">楷体</option>
</select>
</div>
</div>
<button id="addWatermarkBtn">添加水印</button>
<button id="downloadBtn" disabled>下载图片</button>
<h2>预览:</h2>
<canvas id="canvas"></canvas>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const imageInput = document.getElementById('imageInput');
const watermarkText = document.getElementById('watermarkText');
const fontSize = document.getElementById('fontSize');
const fontColor = document.getElementById('fontColor');
const backgroundColor = document.getElementById('backgroundColor');
const opacity = document.getElementById('opacity');
const angle = document.getElementById('angle');
const fontFamily = document.getElementById('fontFamily');
const addWatermarkBtn = document.getElementById('addWatermarkBtn');
const downloadBtn = document.getElementById('downloadBtn');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let originalImage = null;
// 加载图片
imageInput.addEventListener('change', function(e) {
if (e.target.files && e.target.files[0]) {
const reader = new FileReader();
reader.onload = function(event) {
const img = new Image();
img.onload = function() {
originalImage = img;
drawImage();
};
img.src = event.target.result;
};
reader.readAsDataURL(e.target.files[0]);
}
});
// 添加水印
addWatermarkBtn.addEventListener('click', function() {
if (originalImage) {
drawImage();
addWatermark();
downloadBtn.disabled = false;
} else {
alert('请先选择一张图片');
}
});
// 下载图片
downloadBtn.addEventListener('click', function() {
if (originalImage) {
const link = document.createElement('a');
link.download = 'watermarked-image.png';
link.href = canvas.toDataURL('image/png');
link.click();
}
});
// 绘制原始图片
function drawImage() {
canvas.width = originalImage.width;
canvas.height = originalImage.height;
ctx.drawImage(originalImage, 0, 0);
}
// 添加水印
function addWatermark() {
if (!originalImage) return;
const text = watermarkText.value;
const lines = text.split('\n');
const size = parseInt(fontSize.value);
const color = fontColor.value;
const bgColor = backgroundColor.value;
const alpha = parseFloat(opacity.value);
const rotation = parseInt(angle.value) * Math.PI / 180;
const font = fontFamily.value;
ctx.font = `${size}px ${font}`;
ctx.fillStyle = color;
ctx.strokeStyle = bgColor;
ctx.globalAlpha = alpha;
// 计算水印文本的最大宽度和总高度
let maxWidth = 0;
let totalHeight = 0;
const lineHeight = size * 1.2;
lines.forEach(line => {
const metrics = ctx.measureText(line);
maxWidth = Math.max(maxWidth, metrics.width);
totalHeight += lineHeight;
});
// 设置水印间距
const spacingX = maxWidth * 1.5;
const spacingY = totalHeight * 5.5;
// 平铺水印
ctx.save();
ctx.globalAlpha = alpha;
// 计算需要覆盖整个图片所需的水印数量
const cols = Math.ceil(canvas.width / spacingX) + 1;
const rows = Math.ceil(canvas.height / spacingY) + 1;
// 绘制水印
for (let i = -1; i < rows; i++) {
for (let j = -1; j < cols; j++) {
ctx.save();
// 移动到当前水印位置
const x = j * spacingX;
const y = i * spacingY;
// 移动到中心点旋转
ctx.translate(x, y);
ctx.rotate(rotation);
// 绘制每一行文字
lines.forEach((line, index) => {
// 文字描边(背景)
ctx.lineWidth = 2;
ctx.strokeText(line, 0, index * lineHeight);
// 文字填充(前景)
ctx.fillText(line, 0, index * lineHeight);
});
ctx.restore();
}
}
ctx.restore();
}
});
</script>
</body>
</html>
结语
🎤 记得三连哦~
🎉 不用客气,拿去直接用就好了~