好友
阅读权限20
听众
最后登录1970-1-1
|
下面就是网页版的,完全离线,不依赖服务器的单文件版本
我用的是腾讯元宝生成的,免费的,如果风格不满意的,你可以自己用元宝改
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片与Base64互转工具</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
min-height: 100vh;
padding: 20px;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 40px;
padding: 20px;
}
h1 {
color: #0052d9;
font-size: 2.5rem;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
h1 .icon {
font-size: 2.2rem;
}
.subtitle {
color: #666;
font-size: 1.2rem;
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.content-wrapper {
display: flex;
flex-wrap: wrap;
gap: 30px;
justify-content: center;
}
.converter-section {
background-color: white;
border-radius: 16px;
padding: 30px;
box-shadow: 0 10px 30px rgba(0, 82, 217, 0.1);
flex: 1;
min-width: 300px;
max-width: 550px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.converter-section:hover {
transform: translateY(-5px);
box-shadow: 0 15px 35px rgba(0, 82, 217, 0.15);
}
.section-title {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 2px solid #eef5ff;
}
.section-title h2 {
color: #0052d9;
font-size: 1.8rem;
}
.section-title .icon {
color: #0052d9;
font-size: 1.5rem;
}
.input-area {
margin-bottom: 25px;
}
.file-input-container {
border: 2px dashed #c2d9ff;
border-radius: 12px;
padding: 40px 20px;
text-align: center;
background-color: #f8fbff;
cursor: pointer;
transition: all 0.3s;
margin-bottom: 20px;
}
.file-input-container:hover {
border-color: #0052d9;
background-color: #f0f7ff;
}
.file-input-container .icon {
font-size: 3rem;
color: #0052d9;
margin-bottom: 15px;
}
.file-input-container p {
color: #666;
font-size: 1.1rem;
margin-bottom: 10px;
}
.file-input-container .file-types {
color: #888;
font-size: 0.9rem;
}
#fileInput {
display: none;
}
.textarea-container {
margin-top: 20px;
}
textarea {
width: 100%;
height: 200px;
padding: 15px;
border: 2px solid #e1ebff;
border-radius: 12px;
font-size: 0.95rem;
font-family: 'Courier New', monospace;
resize: vertical;
background-color: #fafcff;
transition: border 0.3s;
}
textarea:focus {
outline: none;
border-color: #0052d9;
}
.preview-container {
margin-top: 25px;
text-align: center;
}
.preview-title {
font-size: 1.2rem;
color: #0052d9;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.image-preview {
max-width: 100%;
max-height: 300px;
border-radius: 12px;
border: 2px solid #e1ebff;
padding: 5px;
background-color: white;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
}
.placeholder-text {
color: #999;
font-style: italic;
padding: 40px 20px;
background-color: #f8f9fa;
border-radius: 12px;
border: 2px dashed #e1ebff;
}
.button-group {
display: flex;
gap: 15px;
margin-top: 25px;
flex-wrap: wrap;
}
.btn {
padding: 14px 28px;
border: none;
border-radius: 10px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
transition: all 0.3s;
flex: 1;
min-width: 140px;
}
.btn-primary {
background-color: #0052d9;
color: white;
}
.btn-primary:hover {
background-color: #0041b3;
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(0, 82, 217, 0.3);
}
.btn-secondary {
background-color: #f0f7ff;
color: #0052d9;
border: 2px solid #c2d9ff;
}
.btn-secondary:hover {
background-color: #e1ebff;
transform: translateY(-2px);
}
.btn .icon {
font-size: 1.1rem;
}
.info-box {
background-color: #f0f7ff;
border-left: 4px solid #0052d9;
padding: 18px;
border-radius: 8px;
margin-top: 30px;
font-size: 0.95rem;
line-height: 1.6;
}
.info-box h3 {
color: #0052d9;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 10px;
}
.direction-arrow {
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
color: #0052d9;
margin: 20px 0;
}
.status-message {
padding: 12px 20px;
border-radius: 10px;
margin-top: 20px;
text-align: center;
font-weight: 500;
display: none;
}
.success {
background-color: #e7f7ef;
color: #0a8754;
border-left: 4px solid #0a8754;
}
.error {
background-color: #fdf0f0;
color: #d93030;
border-left: 4px solid #d93030;
}
footer {
text-align: center;
margin-top: 50px;
padding: 20px;
color: #888;
font-size: 0.9rem;
border-top: 1px solid #e1ebff;
}
@media (max-width: 768px) {
.content-wrapper {
flex-direction: column;
align-items: center;
}
.converter-section {
width: 100%;
}
h1 {
font-size: 2rem;
}
.direction-arrow {
transform: rotate(90deg);
margin: 10px 0;
}
}
/* 图标样式 */
.icon-upload::before { content: "⬆"; }
.icon-convert::before { content: "🔄"; }
.icon-copy::before { content: "📋"; }
.icon-clear::before { content: "🗑"; }
.icon-download::before { content: "⬇"; }
.icon-image::before { content: "🖼"; }
.icon-code::before { content: "</>"; }
.icon-info::before { content: "ℹ"; }
.icon-exchange::before { content: "⇄"; }
.icon-cloud-upload::before { content: "☁"; }
</style>
</head>
<body>
<div class="container">
<header>
<h1><span class="icon icon-exchange"></span> 图片与Base64互转工具</h1>
<p class="subtitle">上传图片转换为Base64编码,或粘贴Base64编码还原为图片。支持JPG、PNG、GIF、SVG等常见格式。</p>
</header>
<div class="content-wrapper">
<!-- 图片转Base64部分 -->
<section class="converter-section">
<div class="section-title">
<span class="icon icon-upload"></span>
<h2>图片转Base64</h2>
</div>
<div class="input-area">
<div class="file-input-container" id="dropArea">
<span class="icon icon-cloud-upload"></span>
<p>点击选择或拖拽图片到此区域</p>
<p class="file-types">支持 JPG, PNG, GIF, SVG, WEBP 等格式</p>
<input type="file" id="fileInput" accept="image/*">
</div>
<div class="preview-container">
<div class="preview-title">
<span class="icon icon-image"></span>
<span>图片预览</span>
</div>
<img id="imagePreview" class="image-preview" alt="图片预览" style="display: none;">
<div id="imagePlaceholder" class="placeholder-text">选择的图片将在此处显示预览</div>
</div>
</div>
<div class="textarea-container">
<div class="preview-title">
<span class="icon icon-code"></span>
<span>Base64 编码结果</span>
</div>
<textarea id="base64Output" placeholder="Base64编码将在此处显示..." readonly></textarea>
</div>
<div class="button-group">
<button class="btn btn-primary" id="convertToBase64">
<span class="icon icon-convert"></span> 转换为Base64
</button>
<button class="btn btn-secondary" id="copyBase64">
<span class="icon icon-copy"></span> 复制Base64
</button>
<button class="btn btn-secondary" id="clearImage">
<span class="icon icon-clear"></span> 清除
</button>
</div>
<div id="imageToBase64Status" class="status-message"></div>
</section>
<!-- 方向箭头 -->
<div class="direction-arrow">
<span class="icon icon-exchange"></span>
</div>
<!-- Base64转图片部分 -->
<section class="converter-section">
<div class="section-title">
<span class="icon icon-download"></span>
<h2>Base64转图片</h2>
</div>
<div class="textarea-container">
<div class="preview-title">
<span class="icon icon-code"></span>
<span>输入Base64编码</span>
</div>
<textarea id="base64Input" placeholder="在此处粘贴Base64编码(以 data:image/... 开头)或纯Base64字符串..."></textarea>
</div>
<div class="preview-container">
<div class="preview-title">
<span class="icon icon-image"></span>
<span>图片预览</span>
</div>
<img id="base64ImagePreview" class="image-preview" alt="Base64图片预览" style="display: none;">
<div id="base64ImagePlaceholder" class="placeholder-text">Base64转换的图片将在此处显示</div>
</div>
<div class="button-group">
<button class="btn btn-primary" id="convertToImage">
<span class="icon icon-convert"></span> 转换为图片
</button>
<button class="btn btn-secondary" id="downloadImage">
<span class="icon icon-download"></span> 下载图片
</button>
<button class="btn btn-secondary" id="clearBase64">
<span class="icon icon-clear"></span> 清除
</button>
</div>
<div id="base64ToImageStatus" class="status-message"></div>
</section>
</div>
<div class="info-box">
<h3><span class="icon icon-info"></span> 使用说明</h3>
<p><strong>图片转Base64:</strong>点击上传区域选择图片或拖拽图片到该区域,然后点击"转换为Base64"按钮。转换完成后,Base64编码会显示在下方文本框中,您可以点击"复制Base64"按钮复制到剪贴板。</p>
<p><strong>Base64转图片:</strong>在左侧文本框中粘贴Base64编码(完整格式如"data:image/png;base64,..."或纯Base64字符串),然后点击"转换为图片"按钮。图片显示后,可点击"下载图片"保存到本地。</p>
</div>
<footer>
<p>© 2023 图片与Base64互转工具 | 腾讯元宝风格界面 | 本工具完全在浏览器中运行,不上传任何数据到服务器</p>
</footer>
</div>
<script>
// 获取DOM元素
const fileInput = document.getElementById('fileInput');
const dropArea = document.getElementById('dropArea');
const imagePreview = document.getElementById('imagePreview');
const imagePlaceholder = document.getElementById('imagePlaceholder');
const base64Output = document.getElementById('base64Output');
const convertToBase64Btn = document.getElementById('convertToBase64');
const copyBase64Btn = document.getElementById('copyBase64');
const clearImageBtn = document.getElementById('clearImage');
const imageToBase64Status = document.getElementById('imageToBase64Status');
const base64Input = document.getElementById('base64Input');
const base64ImagePreview = document.getElementById('base64ImagePreview');
const base64ImagePlaceholder = document.getElementById('base64ImagePlaceholder');
const convertToImageBtn = document.getElementById('convertToImage');
const downloadImageBtn = document.getElementById('downloadImage');
const clearBase64Btn = document.getElementById('clearBase64');
const base64ToImageStatus = document.getElementById('base64ToImageStatus');
// DATA URI数据头
const exampleBase64 = "data:image/png;base64,";
base64Input.value = exampleBase64;
// 文件选择处理
dropArea.addEventListener('click', () => {
fileInput.click();
});
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
handleImageFile(file);
}
});
// 拖放功能
dropArea.addEventListener('dragover', (e) => {
e.preventDefault();
dropArea.style.borderColor = '#0052d9';
dropArea.style.backgroundColor = '#e8f2ff';
});
dropArea.addEventListener('dragleave', () => {
dropArea.style.borderColor = '#c2d9ff';
dropArea.style.backgroundColor = '#f8fbff';
});
dropArea.addEventListener('drop', (e) => {
e.preventDefault();
dropArea.style.borderColor = '#c2d9ff';
dropArea.style.backgroundColor = '#f8fbff';
const file = e.dataTransfer.files[0];
if (file && file.type.startsWith('image/')) {
handleImageFile(file);
} else {
showStatus(imageToBase64Status, '请拖放一个有效的图片文件', 'error');
}
});
// 处理图片文件
function handleImageFile(file) {
// 验证文件类型
if (!file.type.startsWith('image/')) {
showStatus(imageToBase64Status, '请选择一个图片文件', 'error');
return;
}
// 验证文件大小(限制为5MB)
if (file.size > 5 * 1024 * 1024) {
showStatus(imageToBase64Status, '图片文件过大,请选择小于5MB的文件', 'error');
return;
}
// 显示图片预览
const reader = new FileReader();
reader.onload = (e) => {
imagePreview.src = e.target.result;
imagePreview.style.display = 'block';
imagePlaceholder.style.display = 'none';
// 自动转换
convertToBase64();
};
reader.readAsDataURL(file);
showStatus(imageToBase64Status, `已选择: ${file.name} (${formatFileSize(file.size)})`, 'success');
}
// 图片转Base64
function convertToBase64() {
if (!imagePreview.src || imagePreview.src.startsWith('data:') === false) {
showStatus(imageToBase64Status, '请先选择一张图片', 'error');
return;
}
base64Output.value = imagePreview.src;
showStatus(imageToBase64Status, '图片已成功转换为Base64编码', 'success');
}
// Base64转图片
function convertToImage() {
const base64String = base64Input.value.trim();
if (!base64String) {
showStatus(base64ToImageStatus, '请输入Base64编码', 'error');
return;
}
// 检查是否为有效的Base64图片数据
let imageSrc = base64String;
// 如果不是完整的数据URL格式,尝试添加前缀
if (!base64String.startsWith('data:image/')) {
// 尝试检测图片类型
let mimeType = 'image/png';
// 简单检测常见的Base64前缀
if (base64String.startsWith('/9j/') || base64String.startsWith('iVBORw')) {
mimeType = 'image/jpeg';
} else if (base64String.startsWith('iVBORw0KGgo')) {
mimeType = 'image/png';
} else if (base64String.startsWith('R0lGODlh')) {
mimeType = 'image/gif';
} else if (base64String.startsWith('UklGR')) {
mimeType = 'image/webp';
} else if (base64String.startsWith('PHN2Zy')) {
mimeType = 'image/svg+xml';
}
imageSrc = `data:${mimeType};base64,${base64String}`;
}
// 测试图片是否能加载
const testImage = new Image();
testImage.onload = () => {
base64ImagePreview.src = imageSrc;
base64ImagePreview.style.display = 'block';
base64ImagePlaceholder.style.display = 'none';
showStatus(base64ToImageStatus, 'Base64编码已成功转换为图片', 'success');
};
testImage.onerror = () => {
showStatus(base64ToImageStatus, '无效的Base64图片编码,请检查格式是否正确', 'error');
};
testImage.src = imageSrc;
}
// 复制Base64到剪贴板
function copyToClipboard(text, statusElement) {
if (!text) {
showStatus(statusElement, '没有内容可复制', 'error');
return;
}
navigator.clipboard.writeText(text).then(() => {
showStatus(statusElement, '已复制到剪贴板', 'success');
}).catch(err => {
// 降级方案
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showStatus(statusElement, '已复制到剪贴板', 'success');
});
}
// 下载图片
function downloadImage() {
if (!base64ImagePreview.src || base64ImagePreview.style.display === 'none') {
showStatus(base64ToImageStatus, '没有可下载的图片', 'error');
return;
}
const link = document.createElement('a');
link.href = base64ImagePreview.src;
// 从Base64中提取可能的文件类型和生成文件名
let extension = 'png';
if (base64ImagePreview.src.includes('image/jpeg') || base64ImagePreview.src.includes('image/jpg')) {
extension = 'jpg';
} else if (base64ImagePreview.src.includes('image/gif')) {
extension = 'gif';
} else if (base64ImagePreview.src.includes('image/webp')) {
extension = 'webp';
} else if (base64ImagePreview.src.includes('image/svg+xml')) {
extension = 'svg';
}
link.download = `converted-image.${extension}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
showStatus(base64ToImageStatus, `图片已下载为 converted-image.${extension}`, 'success');
}
// 显示状态消息
function showStatus(element, message, type) {
element.textContent = message;
element.className = 'status-message ' + type;
element.style.display = 'block';
// 3秒后隐藏消息
setTimeout(() => {
element.style.display = 'none';
}, 3000);
}
// 格式化文件大小
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
// 清除图片区域
function clearImageArea() {
fileInput.value = '';
imagePreview.src = '';
imagePreview.style.display = 'none';
imagePlaceholder.style.display = 'block';
base64Output.value = '';
showStatus(imageToBase64Status, '已清除图片和Base64编码', 'success');
}
// 清除Base64区域
function clearBase64Area() {
base64Input.value = '';
base64ImagePreview.src = '';
base64ImagePreview.style.display = 'none';
base64ImagePlaceholder.style.display = 'block';
showStatus(base64ToImageStatus, '已清除Base64编码和图片', 'success');
}
// 事件监听器
convertToBase64Btn.addEventListener('click', convertToBase64);
copyBase64Btn.addEventListener('click', () => {
copyToClipboard(base64Output.value, imageToBase64Status);
});
clearImageBtn.addEventListener('click', clearImageArea);
convertToImageBtn.addEventListener('click', convertToImage);
downloadImageBtn.addEventListener('click', downloadImage);
clearBase64Btn.addEventListener('click', clearBase64Area);
// Base64输入框支持Ctrl+Enter快捷键转换
base64Input.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.key === 'Enter') {
convertToImage();
}
});
// 初始化:将示例Base64转换为图片
window.addEventListener('load', () => {
// 使用setTimeout确保页面完全加载
setTimeout(() => {
convertToImage();
}, 500);
});
</script>
</body>
</html>
|
|