以下是完成的代码,包含所有功能实现:
```javascript
// 根据选择的格式生成不同的MIME类型
let mimeType;
switch(selectedFormat) {
case 'jpeg':
mimeType = 'image/jpeg';
break;
case 'webp':
mimeType = 'image/webp';
break;
default:
mimeType = 'image/png';
}
const link = document.createElement('a');
link.download = `stamped-image.${selectedFormat}`;
link.href = tempCanvas.toDataURL(mimeType, 0.92);
link.click();
});
// 重置
resetBtn.addEventListener('click', function() {
currentImage = null;
currentStamp = null;
activeStamp = null;
previewStamp.src = '';
initCanvas();
});
// 印章大小控制
sizeControl.addEventListener('input', function() {
if (!activeStamp) return;
const size = parseInt(this.value);
const ratio = activeStamp.originalWidth / activeStamp.originalHeight;
let width, height;
if (ratio > 1) {
width = size;
height = size / ratio;
} else {
height = size;
width = size * ratio;
}
// 保持中心点不变
const centerX = activeStamp.x + activeStamp.width/2;
const centerY = activeStamp.y + activeStamp.height/2;
activeStamp.width = width;
activeStamp.height = height;
activeStamp.x = centerX - width/2;
activeStamp.y = centerY - height/2;
drawCanvas();
});
// 格式选择
formatBtns.forEach(btn => {
btn.addEventListener('click', function() {
formatBtns.forEach(b => b.classList.remove('active'));
this.classList.add('active');
selectedFormat = this.dataset.format;
});
});
// 画布交互 - 拖动和调整大小
canvas.addEventListener('mousedown', function(e) {
if (!activeStamp) return;
const rect = canvas.getBoundingClientRect();
const x = (e.clientX - rect.left) / (rect.width / canvas.width);
const y = (e.clientY - rect.top) / (rect.height / canvas.height);
// 检查是否点击在调整大小的手柄上
const handleSize = 15;
const handleX = activeStamp.x + activeStamp.width;
const handleY = activeStamp.y + activeStamp.height;
if (Math.abs(x - handleX) < handleSize && Math.abs(y - handleY) < handleSize) {
isResizing = true;
}
// 检查是否点击在印章上
else if (x >= activeStamp.x && x <= activeStamp.x + activeStamp.width &&
y >= activeStamp.y && y <= activeStamp.y + activeStamp.height) {
isDragging = true;
dragStartX = x - activeStamp.x;
dragStartY = y - activeStamp.y;
}
if (isDragging || isResizing) {
drawCanvas(); // 显示选中框
}
});
canvas.addEventListener('mousemove', function(e) {
if (!activeStamp) return;
const rect = canvas.getBoundingClientRect();
const x = (e.clientX - rect.left) / (rect.width / canvas.width);
const y = (e.clientY - rect.top) / (rect.height / canvas.height);
if (isDragging) {
activeStamp.x = x - dragStartX;
activeStamp.y = y - dragStartY;
}
else if (isResizing) {
const minSize = 20;
const newWidth = Math.max(minSize, x - activeStamp.x);
const newHeight = newWidth * (activeStamp.height / activeStamp.width);
activeStamp.width = newWidth;
activeStamp.height = newHeight;
// 更新大小控制滑块
sizeControl.value = Math.max(activeStamp.width, activeStamp.height);
}
if (isDragging || isResizing) {
drawCanvas();
}
});
canvas.addEventListener('mouseup', function() {
isDragging = false;
isResizing = false;
drawCanvas();
});
canvas.addEventListener('mouseleave', function() {
isDragging = false;
isResizing = false;
drawCanvas();
});
// 窗口大小变化时调整画布
window.addEventListener('resize', function() {
if (currentImage) {
fitCanvasToImage();
} else {
initCanvas();
}
drawCanvas();
});
// 初始化
formatBtns[0].classList.add('active'); // 默认选中PNG
initCanvas();
});
</script>
</body>
</html>
```
### 完整功能说明
1. **左右布局设计**:
- 左侧为控制面板,分为源文件操作、印章操作、印章设置和输出操作四个部分
- 右侧为画布展示区域,适配不同尺寸图片
2. **多格式支持**:
- 支持PNG、JPEG、WEBP三种输出格式
- 格式切换按钮直观可见
- 下载时根据选择格式自动转换
3. **印章控制增强**:
- 精确的印章大小调节滑块
- 实时拖动位置功能
- 拖动时显示半透明选中框
- 右下角可调整大小(类似图片编辑器)
4. **用户体验优化**:
- 画布自动适应图片比例
- 印章保持原图比例缩放
- 拖动和调整大小时视觉反馈清晰
- 响应式设计适配不同屏幕尺寸
5. **骑缝章改进**:
- 精确计算图片中缝位置
- 印章左右部分完美对接
- 骑缝章也可拖动和调整大小
这个实现保持了代码的精简性(仍然只有一个HTML文件),同时提供了完整的功能集和现代化的用户界面。