图片转base64在线生成器源码
7小时前
本地处理,无需上传服务器 | 支持JPG、PNG、GIF、WebP等格式 | 一键复制
<!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>
:root {
--primary: #3b82f6;
--primary-light: #60a5fa;
--bg: #f8fafc;
--panel: #ffffff;
--border: #e2e8f0;
--text: #1e293b;
--text-light: #64748b;
--shadow: 0 4px 12px rgba(59, 130, 246, 0.1);
--danger: #ef4444;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Inter', system-ui, -apple-system, sans-serif;
}
body {
background-color: var(--bg);
color: var(--text);
padding: 20px;
line-height: 1.6;
}
header {
text-align: center;
margin-bottom: 30px;
padding: 15px 0;
}
h1 {
color: var(--primary);
margin-bottom: 8px;
font-weight: 700;
font-size: 2rem;
}
.subtitle {
color: var(--text-light);
font-size: 1.1rem;
max-width: 600px;
margin: 0 auto;
}
.container {
display: flex;
flex-wrap: wrap;
gap: 30px;
max-width: 1200px;
margin: 0 auto;
}
.upload-panel, .result-panel {
flex: 1;
min-width: 300px;
background: var(--panel);
border-radius: 16px;
padding: 30px;
box-shadow: var(--shadow);
}
.panel-title {
font-size: 1.3rem;
font-weight: 600;
color: var(--primary);
margin-bottom: 20px;
display: flex;
align-items: center;
gap: 8px;
}
.upload-area {
border: 2px dashed var(--border);
border-radius: 12px;
padding: 40px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
margin-bottom: 25px;
}
.upload-area:hover {
border-color: var(--primary-light);
background-color: rgba(59, 130, 246, 0.03);
}
.upload-area.active {
border-color: var(--primary);
background-color: rgba(59, 130, 246, 0.05);
}
.upload-icon {
font-size: 3rem;
color: var(--primary-light);
margin-bottom: 15px;
}
.upload-text {
font-size: 1.1rem;
margin-bottom: 10px;
}
.upload-hint {
font-size: 0.9rem;
color: var(--text-light);
line-height: 1.5;
}
#file-input {
display: none;
}
.preview-container {
margin-top: 25px;
display: none;
}
.preview-title {
font-weight: 600;
margin-bottom: 10px;
color: var(--text);
}
.preview-box {
width: 100%;
height: 200px;
border: 1px solid var(--border);
border-radius: 8px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background-color: #f1f5f9;
}
.preview-img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
}
.file-info {
margin-top: 15px;
padding: 12px;
background-color: #f1f5f9;
border-radius: 8px;
font-size: 0.9rem;
}
.info-item {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
}
.info-label {
color: var(--text-light);
}
.settings-group {
margin-bottom: 25px;
}
.settings-label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: var(--text);
}
select {
width: 100%;
padding: 12px 15px;
border: 2px solid var(--border);
border-radius: 8px;
font-size: 1rem;
transition: all 0.2s;
background-color: white;
}
select:focus {
outline: none;
border-color: var(--primary-light);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.btn {
width: 100%;
padding: 14px;
border: none;
border-radius: 8px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.convert-btn {
background-color: var(--primary);
color: white;
margin-bottom: 15px;
}
.convert-btn:hover {
background-color: #2563eb;
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
}
.convert-btn:active {
transform: translateY(0);
}
.reset-btn {
background-color: #f8fafc;
color: var(--text);
border: 2px solid var(--border);
}
.reset-btn:hover {
background-color: #f1f5f9;
border-color: #cbd5e1;
}
.result-content {
margin-top: 20px;
}
.base64-output {
width: 100%;
min-height: 300px;
padding: 15px;
border: 2px solid var(--border);
border-radius: 8px;
font-family: monospace;
font-size: 0.9rem;
resize: vertical;
background-color: white;
white-space: pre-wrap;
word-break: break-all;
overflow-y: auto;
}
.output-actions {
display: flex;
gap: 15px;
margin-top: 15px;
}
.action-btn {
flex: 1;
padding: 10px;
border: none;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
font-size: 0.95rem;
}
.copy-btn {
background-color: var(--primary);
color: white;
}
.copy-btn:hover {
background-color: #2563eb;
}
.download-btn {
background-color: #f1f5f9;
color: var(--text);
}
.download-btn:hover {
background-color: #e2e8f0;
}
.notification {
position: fixed;
top: 20px;
right: 20px;
background-color: #10b981;
color: white;
padding: 12px 20px;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2);
transform: translateX(120%);
transition: transform 0.3s ease;
z-index: 1000;
display: flex;
align-items: center;
gap: 8px;
}
.notification.show {
transform: translateX(0);
}
.error-notification {
background-color: var(--danger);
}
.loading {
display: none;
text-align: center;
padding: 20px;
}
.loading-spinner {
width: 40px;
height: 40px;
border: 4px solid rgba(59, 130, 246, 0.1);
border-left-color: var(--primary);
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 15px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
@media (max-width: 768px) {
.container {
flex-direction: column;
}
h1 {
font-size: 1.8rem;
}
.upload-panel, .result-panel {
padding: 25px;
}
.preview-box {
height: 150px;
}
.base64-output {
min-height: 250px;
}
}
</style>
</head>
<body>
<header>
<h1>在线图片转Base64生成器</h1>
<p class="subtitle">本地处理,无需上传服务器 | 支持JPG、PNG、GIF、WebP等格式 | 一键复制</p>
</header>
<div class="container">
<div class="upload-panel">
<h2 class="panel-title">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
上传图片
</h2>
<!-- 上传区域 -->
<div class="upload-area" id="upload-area">
<div class="upload-icon">?</div>
<div class="upload-text">点击或拖拽图片到此处上传</div>
<div class="upload-hint">支持 JPG、PNG、GIF、WebP、BMP 格式<br>单文件最大 10MB</div>
<input type="file" id="file-input" accept="image/*">
</div>
<!-- 预览区域 -->
<div class="preview-container" id="preview-container">
<div class="preview-title">图片预览</div>
<div class="preview-box">
<img src="" alt="预览图" class="preview-img" id="preview-img">
</div>
<div class="file-info">
<div class="info-item">
<span class="info-label">文件名:</span>
<span class="info-value" id="file-name">-</span>
</div>
<div class="info-item">
<span class="info-label">文件大小:</span>
<span class="info-value" id="file-size">-</span>
</div>
<div class="info-item">
<span class="info-label">尺寸:</span>
<span class="info-value" id="file-dimensions">-</span>
</div>
<div class="info-item">
<span class="info-label">格式:</span>
<span class="info-value" id="file-format">-</span>
</div>
</div>
</div>
<!-- 设置区域 -->
<div class="settings-group">
<label class="settings-label" for="output-format">输出格式</label>
<select id="output-format">
<option value="full">完整 Base64 (带 Data URI 前缀)</option>
<option value="pure">纯 Base64 (不含前缀)</option>
<option value="html">HTML img 标签</option>
<option value="css">CSS background 样式</option>
</select>
</div>
<button class="btn convert-btn" id="convert-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5"></path>
<path d="M2 12l10 5 10-5"></path>
</svg>
开始转换
</button>
<button class="btn reset-btn" id="reset-btn">重置</button>
</div>
<div class="result-panel">
<h2 class="panel-title">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
<line x1="16" y1="13" x2="8" y2="13"></line>
<line x1="16" y1="17" x2="8" y2="17"></line>
<polyline points="10 9 9 9 8 9"></polyline>
</svg>
转换结果
</h2>
<!-- 加载中 -->
<div class="loading" id="loading">
<div class="loading-spinner"></div>
<div>转换中,请稍候...</div>
</div>
<!-- 结果输出 -->
<div class="result-content" id="result-content" style="display: none;">
<textarea class="base64-output" id="base64-output" readonly></textarea>
<div class="output-actions">
<button class="action-btn copy-btn" id="copy-btn">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"></path>
</svg>
复制结果
</button>
<button class="action-btn download-btn" id="download-btn">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="7 10 12 15 17 10"></polyline>
<line x1="12" y1="15" x2="12" y2="3"></line>
</svg>
下载 TXT
</button>
</div>
</div>
<!-- 初始提示 -->
<div id="initial-hint" style="text-align: center; padding: 40px 20px; color: var(--text-light);">
上传图片并点击"开始转换"按钮,生成的 Base64 代码将显示在这里
</div>
</div>
</div>
<div class="notification" id="notification">操作成功!</div>
<script>
// 获取DOM元素
const uploadArea = document.getElementById('upload-area');
const fileInput = document.getElementById('file-input');
const previewContainer = document.getElementById('preview-container');
const previewImg = document.getElementById('preview-img');
const fileName = document.getElementById('file-name');
const fileSize = document.getElementById('file-size');
const fileDimensions = document.getElementById('file-dimensions');
const fileFormat = document.getElementById('file-format');
const outputFormat = document.getElementById('output-format');
const convertBtn = document.getElementById('convert-btn');
const resetBtn = document.getElementById('reset-btn');
const loading = document.getElementById('loading');
const resultContent = document.getElementById('result-content');
const base64Output = document.getElementById('base64-output');
const copyBtn = document.getElementById('copy-btn');
const downloadBtn = document.getElementById('download-btn');
const notification = document.getElementById('notification');
const initialHint = document.getElementById('initial-hint');
// 存储上传的文件和Base64编码
let uploadedFile = null;
let base64Code = '';
// 格式化文件大小
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + ' B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB';
return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
}
// 显示通知
function showNotification(message, isError = false) {
notification.textContent = message;
notification.className = 'notification';
if (isError) notification.classList.add('error-notification');
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
}, 2000);
}
// 处理图片上传
function handleFileSelect(file) {
if (!file) return;
// 检查文件类型
if (!file.type.startsWith('image/')) {
showNotification('请上传图片文件!', true);
return;
}
// 检查文件大小(最大10MB)
const maxSize = 10 * 1024 * 1024; // 10MB
if (file.size > maxSize) {
showNotification(`文件过大(最大支持10MB),当前文件大小:${formatFileSize(file.size)}`, true);
return;
}
uploadedFile = file;
// 更新文件信息
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
fileFormat.textContent = file.type.split('/')[1].toUpperCase();
// 预览图片并获取尺寸
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
fileDimensions.textContent = `${img.width} × ${img.height} px`;
previewImg.src = e.target.result;
previewContainer.style.display = 'block';
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
// 显示上传区域激活状态
uploadArea.classList.add('active');
setTimeout(() => {
uploadArea.classList.remove('active');
}, 500);
}
// 转换图片为Base64
function convertToBase64() {
if (!uploadedFile) {
showNotification('请先上传图片!', true);
return;
}
// 显示加载状态
loading.style.display = 'block';
resultContent.style.display = 'none';
initialHint.style.display = 'none';
// 读取文件并转换
const reader = new FileReader();
reader.onload = function(e) {
base64Code = e.target.result;
formatOutput(base64Code);
// 隐藏加载状态,显示结果
setTimeout(() => {
loading.style.display = 'none';
resultContent.style.display = 'block';
}, 300);
};
reader.readAsDataURL(uploadedFile);
}
// 格式化输出结果
function formatOutput(base64) {
const format = outputFormat.value;
let output = '';
switch (format) {
case 'full':
output = base64;
break;
case 'pure':
// 移除Data URI前缀
output = base64.split(',')[1];
break;
case 'html':
output = `<img src="${base64}" alt="图片" />`;
break;
case 'css':
output = `background-image: url("${base64}");`;
break;
}
base64Output.value = output;
}
// 复制结果到剪贴板
function copyToClipboard() {
if (!base64Code) {
showNotification('暂无转换结果可复制!', true);
return;
}
base64Output.select();
document.execCommand('copy');
showNotification('复制成功!');
}
// 下载Base64为TXT文件
function downloadAsTxt() {
if (!base64Code) {
showNotification('暂无转换结果可下载!', true);
return;
}
const blob = new Blob([base64Output.value], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `base64_${uploadedFile.name.split('.')[0]}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
showNotification('下载已开始!');
}
// 重置所有状态
function resetAll() {
uploadedFile = null;
base64Code = '';
fileInput.value = '';
previewContainer.style.display = 'none';
previewImg.src = '';
fileName.textContent = '-';
fileSize.textContent = '-';
fileDimensions.textContent = '-';
fileFormat.textContent = '-';
base64Output.value = '';
resultContent.style.display = 'none';
loading.style.display = 'none';
initialHint.style.display = 'block';
showNotification('已重置!');
}
// 事件监听 - 点击上传区域
uploadArea.addEventListener('click', () => {
fileInput.click();
});
// 事件监听 - 选择文件
fileInput.addEventListener('change', (e) => {
if (e.target.files.length > 0) {
handleFileSelect(e.target.files[0]);
}
});
// 事件监听 - 拖拽上传
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('active');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('active');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('active');
if (e.dataTransfer.files.length > 0) {
handleFileSelect(e.dataTransfer.files[0]);
}
});
// 事件监听 - 转换按钮
convertBtn.addEventListener('click', convertToBase64);
// 事件监听 - 重置按钮
resetBtn.addEventListener('click', resetAll);
// 事件监听 - 输出格式变更
outputFormat.addEventListener('change', () => {
if (base64Code) {
formatOutput(base64Code);
}
});
// 事件监听 - 复制按钮
copyBtn.addEventListener('click', copyToClipboard);
// 事件监听 - 下载按钮
downloadBtn.addEventListener('click', downloadAsTxt);
</script>
</body>
</html>
没有了