<!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>
* {
box-sizing: border-box;
font-family: system-ui, sans-serif;
}
body {
max-width: 900px;
margin: 20px auto;
padding: 0 16px;
background-color: #f4f7fa;
}
.container {
background: #fff;
padding: 24px;
border-radius: 12px;
box-shadow: 0 2px 12px #00000015;
}
.row {
display: flex;
gap:20px;
flex-wrap: wrap;
}
.col-left{
flex:1;
min-width:280px;
}
.col-right{
flex:1;
min-width:280px;
}
.form-item{
margin:14px 0;
}
label{
display:block;
margin-bottom:6px;
font-weight:500;
}
select, button, input[type="file"]{
width:100%;
padding:10px;
font-size:15px;
border:1px solid #ccc;
border-radius:6px;
}
button{
background:#2563eb;
color:white;
border:none;
cursor:pointer;
margin-top:8px;
}
button:hover{
background:#1d4ed8;
}
#previewWrap{
border:1px solid #ddd;
padding:16px;
background:#eee;
min-height:300px;
display:flex;
align-items:center;
justify-content:center;
}
canvas{
max-width:100%;
}
.size-desc{
font-size:13px;
color:#555;
margin-top:4px;
}
</style>
</head>
<body>
<div class="container">
<h2>证件照生成器(本地浏览器)</h2>
<div class="row">
<div class="col-left">
<div class="form-item">
<label>上传人像照片</label>
<input type="file" id="fileInput" accept="image/*">
</div>
<div class="form-item">
<label>选择证件照尺寸</label>
<select id="sizeSelect">
<option value="big1">大一寸 33×48mm(港澳通行证/护照常用)</option>
<option value="small1">小一寸 22×32mm</option>
<option value="inch1">一寸 25×35mm</option>
<option value="small2">小二寸 35×45mm</option>
<option value="inch2">二寸 35×49mm</option>
</select>
<div class="size-desc" id="sizeTip"></div>
</div>
<div class="form-item">
<label>DPI (打印建议300)</label>
<input type="number" id="dpiInput" value="300">
</div>
<button id="genBtn">生成证件照预览</button>
<button id="downloadBtn">下载图片</button>
</div>
<div class="col-right">
<div id="previewWrap">
<span>请上传图片并点击生成</span>
</div>
</div>
</div>
</div>
<script>
// 尺寸定义 mm : [宽mm,高mm,备注]
const sizeMap = {
big1: [33, 48, "大一寸 33×48mm"],
small1: [22, 32, "小一寸 22×32mm"],
inch1: [25, 35, "一寸 25×35mm"],
small2: [35, 45, "小二寸 35×45mm"],
inch2: [35, 49, "二寸 35×49mm"]
};
const fileInput = document.getElementById('fileInput');
const sizeSelect = document.getElementById('sizeSelect');
const dpiInput = document.getElementById('dpiInput');
const genBtn = document.getElementById('genBtn');
const downloadBtn = document.getElementById('downloadBtn');
const previewWrap = document.getElementById('previewWrap');
const sizeTip = document.getElementById('sizeTip');
let sourceImg = null;
let resultCanvas = null;
sizeSelect.addEventListener('change', ()=>{
const key = sizeSelect.value;
const [w,h,tip] = sizeMap[key];
sizeTip.innerText = `${tip},宽${w}mm,高${h}mm`;
})
sizeSelect.dispatchEvent(new Event('change'));
fileInput.addEventListener('change', (e)=>{
const file = e.target.files[0];
if(!file) return;
const reader = new FileReader();
reader.onload = ev=>{
const img = new Image();
img.onload = ()=>{
sourceImg = img;
}
img.src = ev.target.result;
}
reader.readAsDataURL(file);
})
genBtn.onclick = function(){
if(!sourceImg){
alert("请先上传照片");
return;
}
const key = sizeSelect.value;
const [mmW, mmH] = sizeMap[key];
const dpi = Number(dpiInput.value) || 300;
// mm转像素: 1英寸=25.4mm
const pxW = Math.round(mmW / 25.4 * dpi);
const pxH = Math.round(mmH / 25.4 * dpi);
const canvas = document.createElement('canvas');
canvas.width = pxW;
canvas.height = pxH;
const ctx = canvas.getContext('2d');
// 居中裁剪,按证件照比例截取原图中间部分
const imgRatio = sourceImg.width / sourceImg.height;
const targetRatio = pxW / pxH;
let sx, sy, sWidth, sHeight;
if(imgRatio > targetRatio){
// 原图更宽,左右裁
sHeight = sourceImg.height;
sWidth = sourceImg.height * targetRatio;
sx = (sourceImg.width - sWidth)/2;
sy = 0;
}else{
// 原图更高,上下裁
sWidth = sourceImg.width;
sHeight = sourceImg.width / targetRatio;
sx = 0;
sy = (sourceImg.height - sHeight)/2;
}
ctx.drawImage(sourceImg, sx, sy, sWidth, sHeight, 0,0, pxW, pxH);
// 渲染预览
previewWrap.innerHTML = '';
previewWrap.appendChild(canvas);
resultCanvas = canvas;
}
downloadBtn.onclick = function(){
if(!resultCanvas){
alert("请先生成预览");
return;
}
const key = sizeSelect.value;
const name = `${sizeMap[key][2]}.png`;
const link = document.createElement('a');
link.download = name;
link.href = resultCanvas.toDataURL("image/png");
link.click();
}
</script>
</body>
</html>