随着 Web 技术的发展,浏览器已经具备了强大的图像处理能力。本文将介绍如何使用 HTML、CSS 和 JavaScript 实现一个在线图片格式转换工具。这个工具支持常见的图片格式 JPEG、PNG、WebP 的相互转换。效果演示
用户可以通过点击上传区域或拖拽的方式选择本地图片,选中图片后会自动显示预览,可从下拉菜单中选择目标输出格式,点击“转换图片”按钮完成格式转换,最后可通过“下载转换后的图片”按钮保存结果。
页面结构
文件上传区域
此区域是用户与应用的第一个接触点,支持两种方式导入图片:直接点击触发、拖放操作。<div class="upload-area" id="uploadArea"> <p>点击选择图片或拖拽图片到此处</p> <input type="file" id="fileInput" accept="image/*" style="display: none;"></div>
预览容器
当用户成功加载图片后,这里会展示原图及转换后的效果图。<div id="previewContainer" style="display: none;"> <h3>预览:</h3> <img id="preview" src="" alt="预览图片"></div>
控制区域
控制区域让用户能够选择目标格式并执行转换和下载动作。<div class="controls" id="controls" style="display: none;"> <label for="formatSelect">选择输出格式:</label> <select id="formatSelect"> <option value="image/jpeg">JPEG</option> <option value="image/png">PNG</option> <option value="image/webp">WebP</option> </select> <button id="convertBtn">转换图片</button> <button id="downloadBtn" disabled>下载转换后的图片</button></div>
核心功能实现
文件读取与预览
这部分实现了文件的选择和基本校验,利用 FileReader API 将文件转成 Data URL 并显示在页面上。function handleFileSelect() { var file = fileInput.files[0]; if (!file || !file.type.match('image.*')) { showStatus('请选择一个有效的图片文件', 'error'); return; } var reader = new FileReader(); reader.onload = function(e) { preview.src = e.target.result; previewContainer.style.display = 'block'; controls.style.display = 'block'; originalImage = new Image(); originalImage.onload = function() { showStatus(`已加载图片: ${file.name}`, 'success'); }; originalImage.src = e.target.result; }; reader.readAsDataURL(file);}
图像格式转换
这是关键的核心逻辑,使用 Canvas API 来进行实际的转码工作。特别注意对 JPEG 不支持透明度的问题进行了特殊处理。function convertImage() { if (!originalImage) { showStatus('请先选择一张图片', 'error'); return; } var outputFormat = formatSelect.value; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = originalImage.width; canvas.height = originalImage.height; if (outputFormat === 'image/jpeg') { ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0, 0, canvas.width, canvas.height); } ctx.drawImage(originalImage, 0, 0); try { convertedImageData = canvas.toDataURL(outputFormat); preview.src = convertedImageData; downloadBtn.disabled = false; showStatus(`图片已转换为 ${outputFormat.split('/')[1].toUpperCase()} 格式`, 'success'); } catch (error) { showStatus(`转换失败: ${error.message}`, 'error'); }}
下载功能
通过创建临时的 <a> 标签模拟点击行为来触发浏览器下载机制。function downloadImage() { if (!convertedImageData) { showStatus('没有可下载的图片', 'error'); return; } var link = document.createElement('a'); var format = formatSelect.value.split('/')[1]; link.download = `converted-image.${format}`; link.href = convertedImageData; link.click(); showStatus('开始下载...', 'success');}
扩展建议
完整代码
git地址:https://gitee.com/ironpro/hjdemo/blob/master/convert-image/index.html<!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> * { margin: 0; padding: 0; box-sizing: border-box; } body { background: #f5f5f5; min-height: 100vh; padding: 20px; } .container { max-width: 600px; margin: 0 auto; background: white; border-radius: 15px; box-shadow: 0 20px 40px rgba(0,0,0,0.1); overflow: hidden; } .header { background: #0088B8; color: white; padding: 10px; text-align: center; } .header h1 { font-size: 24px; font-weight: 500; } .main { padding: 20px; height: 800px; text-align: center; } .upload-area { border: 2px dashed #ccc; border-radius: 10px; padding: 40px; margin: 20px 0; cursor: pointer; transition: border-color 0.3s; text-align: center; } .upload-area:hover { border-color: #007bff; } .controls { margin: 20px 0; } select, button { padding: 10px; margin: 5px; font-size: 16px; } #preview { max-width: 100%; max-height: 300px; margin: 20px 0; } #convertBtn { background-color: #28a745; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 10px; margin: 5px; font-size: 16px; }
#convertBtn:hover { background-color: #218838; }
#downloadBtn { background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; padding: 10px; margin: 5px; font-size: 16px; }
#downloadBtn:hover { background-color: #0056b3; }
#downloadBtn:disabled { background-color: #ccc; cursor: not-allowed; } </style></head><body><div class="container"> <div class="header"> <h1>图片格式转换器</h1> </div> <div class="main"> <div class="upload-area" id="uploadArea"> <p>点击选择图片或拖拽图片到此处</p> <input type="file" id="fileInput" accept="image/*" style="display: none;"> </div> <div id="previewContainer" style="display: none;"> <h3>预览:</h3> <img id="preview" src="" alt="预览图片"> </div> <div id="status"></div> <div class="controls" id="controls" style="display: none;"> <label for="formatSelect">选择输出格式:</label> <select id="formatSelect"> <option value="image/jpeg">JPEG</option> <option value="image/png">PNG</option> <option value="image/webp">WebP</option> </select> <button id="convertBtn">转换图片</button> <button id="downloadBtn" disabled>下载转换后的图片</button> </div> </div></div>
<script> var uploadArea = document.getElementById('uploadArea'); var fileInput = document.getElementById('fileInput'); var previewContainer = document.getElementById('previewContainer'); var preview = document.getElementById('preview'); var controls = document.getElementById('controls'); var formatSelect = document.getElementById('formatSelect'); var convertBtn = document.getElementById('convertBtn'); var downloadBtn = document.getElementById('downloadBtn'); var statusDiv = document.getElementById('status');
var originalImage = null; var convertedImageData = null;
uploadArea.addEventListener('click', () => { fileInput.click(); });
fileInput.addEventListener('change', handleFileSelect);
uploadArea.addEventListener('dragover', (e) => { e.preventDefault(); uploadArea.style.borderColor = '#007bff'; });
uploadArea.addEventListener('dragleave', () => { uploadArea.style.borderColor = '#ccc'; });
uploadArea.addEventListener('drop', (e) => { e.preventDefault(); uploadArea.style.borderColor = '#ccc'; if (e.dataTransfer.files.length) { fileInput.files = e.dataTransfer.files; handleFileSelect(); } }); convertBtn.addEventListener('click', convertImage); downloadBtn.addEventListener('click', downloadImage); function handleFileSelect() { var file = fileInput.files[0]; if (!file || !file.type.match('image.*')) { showStatus('请选择一个有效的图片文件', 'error'); return; } var reader = new FileReader(); reader.onload = function(e) { preview.src = e.target.result; previewContainer.style.display = 'block'; controls.style.display = 'block'; originalImage = new Image(); originalImage.onload = function() { showStatus(`已加载图片: ${file.name}`, 'success'); }; originalImage.src = e.target.result; }; reader.readAsDataURL(file); } function convertImage() { if (!originalImage) { showStatus('请先选择一张图片', 'error'); return; } var outputFormat = formatSelect.value; var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width = originalImage.width; canvas.height = originalImage.height; if (outputFormat === 'image/jpeg') { ctx.fillStyle = '#FFFFFF'; ctx.fillRect(0, 0, canvas.width, canvas.height); } ctx.drawImage(originalImage, 0, 0); try { convertedImageData = canvas.toDataURL(outputFormat); preview.src = convertedImageData; downloadBtn.disabled = false; showStatus(`图片已转换为 ${outputFormat.split('/')[1].toUpperCase()} 格式`, 'success'); } catch (error) { showStatus(`转换失败: ${error.message}`, 'error'); } } function downloadImage() { if (!convertedImageData) { showStatus('没有可下载的图片', 'error'); return; } var link = document.createElement('a'); var format = formatSelect.value.split('/')[1]; link.download = `converted-image.${format}`; link.href = convertedImageData; link.click(); showStatus('开始下载...', 'success'); } function showStatus(message, type) { statusDiv.textContent = message; statusDiv.className = type; statusDiv.style.color = type === 'error' ? 'red' : 'green'; }</script></body></html>
阅读原文:原文链接
该文章在 2025/12/16 9:59:05 编辑过