业务需求:在一张白纸上签名,然后拍一张照片,上传后去掉白纸背景,将签名生成一张透明背景的PNG图片
以下简单demo,复制可直接测试使用,可按具体需求修改
<canvas id="signatureCanvas" width="300" height="150"></canvas>
<input type="file" id="imageInput" accept="image/*" />
const canvas = document.getElementById('signatureCanvas');
const ctx = canvas.getContext('2d');
const imageInput = document.getElementById('imageInput');
imageInput.addEventListener('change', function(e) {
const file = e.target.files[0];
const url = URL.createObjectURL(file);
const image = new Image();
image.onload = function() {
// 假设白纸的背景是白色,你可以根据实际情况调整阈值
const threshold = 250; // 灰度值阈值,白色背景会有高于这个值的灰度
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
// 检查当前像素是否为白色或接近白色
if (data[i] >= threshold && data[i + 1] >= threshold && data[i + 2] >= threshold) {
// 将非白色像素设置为透明
data[i] = data[i + 1] = data[i + 2] = 0;
data[i + 3] = 0; // 设置透明度为0
}
}
ctx.putImageData(imageData, 0, 0);
// 导出为PNG图片
const exportedDataUrl = canvas.toDataURL('image/png');
// 可以通过创建一个a标签并模拟点击,来下载生成的PNG图片
const downloadLink = document.createElement('a');
downloadLink.href = exportedDataUrl;
downloadLink.download = 'signature.png';
downloadLink.click();
};
image.src = url;
});
注意 threshold,经测试 正常白色纸张写完字之后拍摄出来的照片除非在特别亮的地方会呈现白色之外,正常室内颜色是偏灰色的,所以灰度阈值设置在100到145之间效果比较明显。其次是签名文字越粗,提取后呈现效果越好,文字过细的话可能会出现笔划断点情况,一点点调节阈值会好一些
再就是,js要写在mounted中,写在created中会因为canvas未渲染完成就执行导致报错
以下为呈现效果: