<!DOCTYPE html>
<html lang="zh">
<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;
display: flex;
flex-direction: column;
align-items: center;
margin: 20px;
background-color: #f0f0f0;
}
h1 {
color: #333;
}
.container {
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
align-items: center;
}
input[type="file"], input[type="text"] {
margin: 10px 0;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
width: 300px;
}
select, input[type="number"], input[type="range"], input[type="color"] {
margin: 10px 0;
padding: 5px;
border: 1px solid #ccc;
border-radius: 5px;
width: 150px;
}
button {
margin: 10px;
padding: 10px 20px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
#canvas {
display: none; /* 初始隐藏 canvas */
max-width: none; /* 允许canvas超出容器宽度 */
}
.canvas-container {
display: none; /* 初始隐藏容器 */
}
.options {
display: flex;
flex-wrap: wrap;
justify-content: center;
width: 100%;
max-width: 800px;
}
.option-group {
margin: 5px 10px;
padding: 5px;
display: flex;
flex-direction: column;
align-items: flex-start;
width: 180px;
}
.option-group label {
margin-bottom: 3px;
font-size: 14px;
}
.zoom-controls {
margin: 10px 0;
display: flex;
align-items: center;
gap: 10px;
}
.canvas-container {
max-width: 100%;
overflow: auto;
margin-top: 10px;
border: 1px solid #ccc;
box-shadow: 0 0 5px rgba(0,0,0,0.2);
}
</style>
</head>
<body>
<div class="container">
<h1>身份证水印工具</h1>
<input type="file" id="upload" accept="image/*">
<input type="text" id="watermark-text" placeholder="输入水印文字">
<div class="options">
<div class="option-group">
<label for="font-size">文字大小:<span id="font-size-value">20</span>px</label>
<input type="range" id="font-size" min="10" max="100" value="20" step="1">
</div>
<div class="option-group">
<label for="rotation">旋转角度(度):</label>
<input type="number" id="rotation" value="-45" step="1">
</div>
<div class="option-group">
<label for="font-family">字体:</label>
<select id="font-family">
<option value="Arial" selected>Arial</option>
<option value="Times New Roman">Times New Roman</option>
<option value="Courier New">Courier New</option>
<option value="Verdana">Verdana</option>
</select>
</div>
<div class="option-group">
<label for="opacity">透明度(0-100):</label>
<input type="range" id="opacity" min="0" max="100" value="50">
</div>
<div class="option-group">
<label for="horizontal-spacing">水平间距(像素):</label>
<input type="number" id="horizontal-spacing" value="50" min="10" step="10">
</div>
<div class="option-group">
<label for="vertical-spacing">行间距(像素):</label>
<input type="number" id="vertical-spacing" value="100" min="10" step="10">
</div>
<div class="option-group">
<label for="font-color">字体颜色:</label>
<input type="color" id="font-color" value="#FFFFFF">
</div>
</div>
<button id="add-watermark">添加水印</button>
<div class="zoom-controls">
<label for="zoom">缩放:<span id="zoom-value">100</span>%</label>
<input type="range" id="zoom" min="10" max="200" value="100" step="5">
<button id="fit-screen">适应屏幕</button>
</div>
<div class="canvas-container">
<canvas id="canvas"></canvas>
</div>
<button id="download" style="display: none;">下载图片</button>
</div>
<script>
let originalImage = null;
let currentZoom = 100;
let lastAppliedWatermark = null;
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 更新字体大小显示
document.getElementById('font-size').addEventListener('input', function() {
document.getElementById('font-size-value').textContent = this.value;
if (originalImage && document.getElementById('watermark-text').value) {
applyWatermark();
}
});
// 更新缩放比例显示
document.getElementById('zoom').addEventListener('input', function() {
currentZoom = parseInt(this.value);
document.getElementById('zoom-value').textContent = currentZoom;
applyZoom();
});
// 适应屏幕按钮
document.getElementById('fit-screen').addEventListener('click', function() {
if (!originalImage) return;
const container = document.querySelector('.canvas-container');
const containerWidth = container.clientWidth;
const containerHeight = window.innerHeight * 0.6; // 使用屏幕高度的60%作为最大高度
const imageRatio = originalImage.width / originalImage.height;
let newZoom = 100;
if (originalImage.width > containerWidth) {
newZoom = (containerWidth / originalImage.width) * 100;
}
if (originalImage.height * (newZoom / 100) > containerHeight) {
newZoom = (containerHeight / originalImage.height) * 100;
}
document.getElementById('zoom').value = newZoom;
document.getElementById('zoom-value').textContent = Math.round(newZoom);
currentZoom = newZoom;
applyZoom();
});
// 应用缩放
function applyZoom() {
if (!originalImage) return;
const scaleFactor = currentZoom / 100;
canvas.style.width = `${originalImage.width * scaleFactor}px`;
canvas.style.height = `${originalImage.height * scaleFactor}px`;
// 如果已经应用了水印,重新应用
if (lastAppliedWatermark) {
applyWatermark();
} else {
// 只重绘原图
redrawOriginalImage();
}
}
// 重绘原图
function redrawOriginalImage() {
if (!originalImage) return;
// 保持canvas的实际尺寸为原图尺寸
canvas.width = originalImage.width;
canvas.height = originalImage.height;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(originalImage, 0, 0, canvas.width, canvas.height);
}
// 应用水印
function applyWatermark() {
if (!originalImage) {
alert('请先上传图片');
return;
}
const text = document.getElementById('watermark-text').value;
if (!text) {
alert('请输入水印文字');
return;
}
// 保存当前水印设置
lastAppliedWatermark = {
text: text,
fontSize: document.getElementById('font-size').value,
rotation: parseFloat(document.getElementById('rotation').value),
fontFamily: document.getElementById('font-family').value,
opacity: parseInt(document.getElementById('opacity').value) / 100,
horizontalSpacing: parseInt(document.getElementById('horizontal-spacing').value),
verticalSpacing: parseInt(document.getElementById('vertical-spacing').value),
fontColor: document.getElementById('font-color').value
};
// 重绘原图
redrawOriginalImage();
// 设置水印样式
ctx.font = `${lastAppliedWatermark.fontSize}px ${lastAppliedWatermark.fontFamily}`;
ctx.fillStyle = `rgba(${parseInt(lastAppliedWatermark.fontColor.slice(1, 3), 16)}, ${parseInt(lastAppliedWatermark.fontColor.slice(3, 5), 16)}, ${parseInt(lastAppliedWatermark.fontColor.slice(5, 7), 16)}, ${lastAppliedWatermark.opacity})`;
ctx.textBaseline = 'middle';
ctx.save();
// 移动到 canvas 中心并旋转
ctx.translate(canvas.width / 2, canvas.height / 2);
const angle = lastAppliedWatermark.rotation * Math.PI / 180;
ctx.rotate(angle);
// 计算水印布局
const textWidth = ctx.measureText(text).width;
const diagonal = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height);
const cols = Math.ceil(diagonal / (textWidth + lastAppliedWatermark.horizontalSpacing));
const rows = Math.ceil(diagonal / lastAppliedWatermark.verticalSpacing);
// 绘制水印
for (let i = -rows; i < rows; i++) {
for (let j = -cols; j < cols; j++) {
const x = j * (textWidth + lastAppliedWatermark.horizontalSpacing);
const y = i * lastAppliedWatermark.verticalSpacing;
ctx.fillText(text, x, y);
}
}
ctx.restore();
document.getElementById('download').style.display = 'inline-block';
}
// 上传图片
document.getElementById('upload').addEventListener('change', function(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(event) {
const img = new Image();
img.onload = function() {
originalImage = img;
// 重置缩放
currentZoom = 100;
document.getElementById('zoom').value = 100;
document.getElementById('zoom-value').textContent = 100;
// 重绘原图
redrawOriginalImage();
// 显示 canvas 和容器
canvas.style.display = 'block';
document.querySelector('.canvas-container').style.display = 'block';
document.getElementById('download').style.display = 'none';
// 自动适应屏幕
document.getElementById('fit-screen').click();
// 清除上次应用的水印记录
lastAppliedWatermark = null;
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
});
// 添加水印按钮
document.getElementById('add-watermark').addEventListener('click', applyWatermark);
// 实时预览的事件监听
const realTimePreviewElements = [
'rotation', 'font-family', 'opacity',
'horizontal-spacing', 'vertical-spacing', 'font-color'
];
realTimePreviewElements.forEach(id => {
document.getElementById(id).addEventListener('input', function() {
if (originalImage && document.getElementById('watermark-text').value) {
applyWatermark();
}
});
});
// 水印文字输入实时预览
document.getElementById('watermark-text').addEventListener('input', function() {
if (originalImage && this.value) {
applyWatermark();
}
});
// 下载图片
document.getElementById('download').addEventListener('click', function() {
const dataURL = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = dataURL;
a.download = 'watermarked-image.png';
a.click();
});
</script>
</body>
</html>

身份证添加水印源码
发布于 2025年07月15日
更新于 2025年08月27日
← 返回首页
评论 (0)
请先 登录 或 注册 后再发表评论
暂无评论,快来发表第一条评论吧!