HTML5 Canvas图片旋转与下载功能实现
我将创建一个完整、美观的图片旋转与下载工具,使用纯HTML5 Canvas技术实现。
设计思路
- 使用Canvas绘制图片并实现旋转功能
- 提供旋转控制按钮和直接输入角度功能
- 添加图片上传功能
- 实现旋转后图片下载
- 创建直观的用户界面
下面是完整的实现代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas图片旋转与下载工具</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 30px 20px;
color: #333;
}
.container {
width: 100%;
max-width: 900px;
background-color: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
padding: 25px;
}
header {
text-align: center;
margin-bottom: 30px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
h1 {
color: #2c3e50;
font-size: 2.5rem;
margin-bottom: 10px;
}
.subtitle {
color: #7f8c8d;
font-size: 1.1rem;
}
.app-content {
display: flex;
flex-wrap: wrap;
gap: 30px;
}
.canvas-section {
flex: 1;
min-width: 300px;
}
.canvas-container {
border: 2px dashed #bdc3c7;
border-radius: 10px;
background-color: #f8f9fa;
width: 100%;
height: 400px;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
margin-bottom: 20px;
}
canvas {
max-width: 100%;
max-height: 100%;
display: block;
}
.controls-section {
flex: 1;
min-width: 300px;
}
.control-group {
background-color: #f8f9fa;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
}
h2 {
color: #2c3e50;
font-size: 1.5rem;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #eaeaea;
}
.upload-btn {
display: block;
width: 100%;
padding: 15px;
background-color: #3498db;
color: white;
border: none;
border-radius: 8px;
font-size: 1.1rem;
cursor: pointer;
transition: background-color 0.3s;
text-align: center;
margin-bottom: 15px;
}
.upload-btn:hover {
background-color: #2980b9;
}
#fileInput {
display: none;
}
.rotation-controls {
display: flex;
flex-wrap: wrap;
gap: 15px;
margin-bottom: 15px;
}
.rotation-btn {
flex: 1;
min-width: 120px;
padding: 12px;
background-color: #2ecc71;
color: white;
border: none;
border-radius: 8px;
font-size: 1rem;
cursor: pointer;
transition: background-color 0.3s;
text-align: center;
}
.rotation-btn:hover {
background-color: #27ae60;
}
.rotation-btn.reset {
background-color: #e74c3c;
}
.rotation-btn.reset:hover {
background-color: #c0392b;
}
.angle-input-group {
display: flex;
align-items: center;
margin-top: 15px;
}
.angle-input-group label {
margin-right: 10px;
font-weight: 600;
color: #2c3e50;
}
.angle-input-group input {
flex: 1;
padding: 10px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 1rem;
}
.angle-input-group button {
margin-left: 10px;
padding: 10px 20px;
background-color: #9b59b6;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s;
}
.angle-input-group button:hover {
background-color: #8e44ad;
}
.download-btn {
display: block;
width: 100%;
padding: 16px;
background-color: #e67e22;
color: white;
border: none;
border-radius: 8px;
font-size: 1.2rem;
font-weight: 600;
cursor: pointer;
transition: background-color 0.3s;
text-align: center;
margin-top: 10px;
}
.download-btn:hover {
background-color: #d35400;
}
.info {
margin-top: 25px;
padding: 15px;
background-color: #f9f9f9;
border-left: 4px solid #3498db;
border-radius: 5px;
}
.info h3 {
color: #2c3e50;
margin-bottom: 8px;
}
.info p {
color: #555;
line-height: 1.5;
}
footer {
margin-top: 30px;
text-align: center;
color: #7f8c8d;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.app-content {
flex-direction: column;
}
.canvas-container {
height: 350px;
}
h1 {
font-size: 2rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Canvas图片旋转与下载工具</h1>
<p class="subtitle">上传图片,旋转任意角度,然后下载处理后的图片</p>
</header>
<div class="app-content">
<div class="canvas-section">
<div class="canvas-container">
<canvas id="imageCanvas" width="600" height="400">
您的浏览器不支持Canvas,请升级浏览器。
</canvas>
<div id="placeholderText">请上传图片</div>
</div>
<div class="control-group">
<h2>上传图片</h2>
<button class="upload-btn" id="uploadTrigger">选择图片文件</button>
<input type="file" id="fileInput" accept="image/*">
<p style="text-align: center; color: #7f8c8d; margin-top: 10px;">支持 JPG, PNG, GIF 格式</p>
</div>
</div>
<div class="controls-section">
<div class="control-group">
<h2>旋转控制</h2>
<div class="rotation-controls">
<button class="rotation-btn" id="rotateLeft">左转 90°</button>
<button class="rotation-btn" id="rotateRight">右转 90°</button>
<button class="rotation-btn" id="rotate180">旋转 180°</button>
<button class="rotation-btn reset" id="resetRotation">重置角度</button>
</div>
<div class="angle-input-group">
<label for="angleInput">自定义角度:</label>
<input type="number" id="angleInput" min="0" max="360" value="0" step="1">
<button id="applyAngle">应用角度</button>
</div>
<div style="margin-top: 15px; text-align: center; font-weight: 600;">
当前旋转角度: <span id="currentAngle">0</span>°
</div>
</div>
<div class="control-group">
<h2>下载图片</h2>
<button class="download-btn" id="downloadBtn">下载旋转后的图片</button>
<p style="margin-top: 15px; color: #7f8c8d; text-align: center;">
点击下载按钮保存处理后的图片到您的设备
</p>
</div>
<div class="info">
<h3>使用说明</h3>
<p>1. 点击"选择图片文件"按钮上传图片</p>
<p>2. 使用旋转按钮或输入自定义角度旋转图片</p>
<p>3. 点击"下载旋转后的图片"保存处理结果</p>
</div>
</div>
</div>
<footer>
<p>基于 HTML5 Canvas 实现的图片旋转与下载工具 | 纯前端实现,无需上传到服务器</p>
</footer>
</div>
<script>
// 获取DOM元素
const canvas = document.getElementById('imageCanvas');
const ctx = canvas.getContext('2d');
const fileInput = document.getElementById('fileInput');
const uploadTrigger = document.getElementById('uploadTrigger');
const rotateLeftBtn = document.getElementById('rotateLeft');
const rotateRightBtn = document.getElementById('rotateRight');
const rotate180Btn = document.getElementById('rotate180');
const resetRotationBtn = document.getElementById('resetRotation');
const angleInput = document.getElementById('angleInput');
const applyAngleBtn = document.getElementById('applyAngle');
const downloadBtn = document.getElementById('downloadBtn');
const currentAngleSpan = document.getElementById('currentAngle');
const placeholderText = document.getElementById('placeholderText');
// 状态变量
let currentImage = null;
let rotationAngle = 0; // 角度值
let canvasWidth = 600;
let canvasHeight = 400;
// 初始化Canvas
canvas.width = canvasWidth;
canvas.height = canvasHeight;
// 上传图片
uploadTrigger.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
if (!file.type.match('image.*')) {
alert('请选择图片文件');
return;
}
const reader = new FileReader();
reader.onload = (event) => {
const img = new Image();
img.onload = () => {
currentImage = img;
rotationAngle = 0;
currentAngleSpan.textContent = rotationAngle;
angleInput.value = rotationAngle;
placeholderText.style.display = 'none';
drawImage();
};
img.src = event.target.result;
};
reader.readAsDataURL(file);
});
// 绘制图片到Canvas
function drawImage() {
if (!currentImage) return;
// 清除Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 计算旋转后的Canvas尺寸
const radians = rotationAngle * Math.PI / 180;
// 计算旋转后的边界框
const sin = Math.abs(Math.sin(radians));
const cos = Math.abs(Math.cos(radians));
// 原始图片尺寸
const imgWidth = currentImage.width;
const imgHeight = currentImage.height;
// 计算旋转后的新尺寸
const newWidth = imgWidth * cos + imgHeight * sin;
const newHeight = imgWidth * sin + imgHeight * cos;
// 调整Canvas大小以适应旋转后的图片
canvas.width = newWidth;
canvas.height = newHeight;
// 保存Canvas状态
ctx.save();
// 移动Canvas原点至中心
ctx.translate(newWidth / 2, newHeight / 2);
// 应用旋转
ctx.rotate(radians);
// 绘制图片(居中)
ctx.drawImage(
currentImage,
-imgWidth / 2,
-imgHeight / 2,
imgWidth,
imgHeight
);
// 恢复Canvas状态
ctx.restore();
}
// 旋转按钮事件
rotateLeftBtn.addEventListener('click', () => {
rotationAngle -= 90;
normalizeAngle();
updateAngleDisplay();
drawImage();
});
rotateRightBtn.addEventListener('click', () => {
rotationAngle += 90;
normalizeAngle();
updateAngleDisplay();
drawImage();
});
rotate180Btn.addEventListener('click', () => {
rotationAngle += 180;
normalizeAngle();
updateAngleDisplay();
drawImage();
});
resetRotationBtn.addEventListener('click', () => {
rotationAngle = 0;
updateAngleDisplay();
drawImage();
});
// 应用自定义角度
applyAngleBtn.addEventListener('click', () => {
const angle = parseInt(angleInput.value);
if (!isNaN(angle)) {
rotationAngle = angle;
normalizeAngle();
updateAngleDisplay();
drawImage();
}
});
// 确保角度在0-360度范围内
function normalizeAngle() {
rotationAngle = rotationAngle % 360;
if (rotationAngle < 0) {
rotationAngle += 360;
}
}
// 更新角度显示
function updateAngleDisplay() {
currentAngleSpan.textContent = rotationAngle;
angleInput.value = rotationAngle;
}
// 下载图片
downloadBtn.addEventListener('click', () => {
if (!currentImage) {
alert('请先上传图片');
return;
}
// 创建一个临时Canvas用于生成下载图片
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
// 计算旋转后的尺寸
const radians = rotationAngle * Math.PI / 180;
const sin = Math.abs(Math.sin(radians));
const cos = Math.abs(Math.cos(radians));
const imgWidth = currentImage.width;
const imgHeight = currentImage.height;
const newWidth = imgWidth * cos + imgHeight * sin;
const newHeight = imgWidth * sin + imgHeight * cos;
tempCanvas.width = newWidth;
tempCanvas.height = newHeight;
// 绘制旋转后的图片到临时Canvas
tempCtx.translate(newWidth / 2, newHeight / 2);
tempCtx.rotate(radians);
tempCtx.drawImage(
currentImage,
-imgWidth / 2,
-imgHeight / 2,
imgWidth,
imgHeight
);
// 生成下载链接
const dataURL = tempCanvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = dataURL;
// 生成文件名
const originalName = fileInput.files[0]?.name || 'image';
const nameWithoutExt = originalName.substring(0, originalName.lastIndexOf('.'));
const extension = originalName.substring(originalName.lastIndexOf('.'));
link.download = `${nameWithoutExt}_rotated_${rotationAngle}deg${extension}`;
// 触发下载
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
// 初始化示例图片
function loadExampleImage() {
const img = new Image();
img.onload = () => {
currentImage = img;
drawImage();
placeholderText.style.display = 'none';
};
// 使用一个示例图片
img.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjMzQ5OERCIi8+CiAgPHRleHQgeD0iNTAwIiB5PSIyMDAiIGZvbnQtc2l6ZT0iMjQiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZpbGw9IndoaXRlIiBmb250LWZhbWlseT0iQXJpYWwiPkNhbnZhcyBJbWFnZSBSb3RhdG9yPC90ZXh0PgogIDx0ZXh0IHg9IjUwMCIgeT0iMjQwIiBmb250LXNpemU9IjE2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmaWxsPSJ3aGl0ZSIgZm9udC1mYW1pbHk9IkFyaWFsIj5VcGxvYWQgeW91ciBvd24gaW1hZ2UgdG8gYmVnaW48L3RleHQ+Cjwvc3ZnPg==';
}
// 页面加载完成后加载示例图片
window.addEventListener('DOMContentLoaded', loadExampleImage);
</script>
</body>
</html>
功能说明
图片上传:点击"选择图片文件"按钮上传本地图片
旋转控制:
- 左转90°:逆时针旋转90度
- 右转90°:顺时针旋转90度
- 旋转180°:将图片上下颠倒
- 重置角度:恢复原始角度
- 自定义角度:输入0-360度之间的任意角度
下载功能:将旋转后的图片下载到本地设备
特点:
- 纯前端实现,无需服务器支持
- 实时预览旋转效果
- 支持任意角度旋转
- 响应式设计,适配各种屏幕尺寸
- 用户友好的界面和交互
该工具完全在浏览器中运行,图片处理不会上传到任何服务器,保护用户隐私。您可以直接复制上面的代码到HTML文件中,用浏览器打开即可使用。