如何使用JavaScript移除精灵图(Sprite)的背景?
Canvas绘制精灵表移除背景的解决方案
你用马里奥NES精灵表绘制时遇到的背景移除问题,不用第三方工具,直接用JavaScript就能精准解决,还能避免切掉Goomba脚部的情况,下面是两种实用方法:
方法一:利用globalCompositeOperation快速移除单一背景色
这种方法适合背景色统一的精灵表,操作简单性能高:
- 创建一个离屏Canvas临时处理精灵,不直接修改主Canvas
- 把要截取的Goomba精灵绘制到离屏Canvas
- 设置混合模式为
destination-out,用精灵表的背景色填充整个离屏Canvas,自动删除所有背景色像素 - 最后把处理好的精灵画到主Canvas里
示例代码:
<img src="https://www.mariouniverse.com/wp-content/img/sprites/nes/smb/enemies-8.png" height="0" width="0" id="enemies"> <canvas></canvas> <script> const enemies = document.getElementById("enemies"); const canvas = document.querySelector('canvas'); const c = canvas.getContext('2d'); canvas.width = innerWidth; canvas.height = innerHeight; // 必须等图片加载完再处理,不然会画不出来 enemies.onload = function() { // 创建临时离屏Canvas const offscreenCanvas = document.createElement('canvas'); const offscreenCtx = offscreenCanvas.getContext('2d'); offscreenCanvas.width = 16; offscreenCanvas.height = 16; // 把Goomba画到临时Canvas offscreenCtx.drawImage(enemies, 0, 18, 16, 16, 0, 0, 16, 16); // 设置混合模式:填充的颜色会移除画布上相同颜色的区域 offscreenCtx.globalCompositeOperation = 'destination-out'; // 这里填精灵表的背景色,用取色器精确获取(示例是#FFE4E1) offscreenCtx.fillStyle = '#FFE4E1'; offscreenCtx.fillRect(0, 0, 16, 16); // 把处理好的透明精灵画到主Canvas c.drawImage(offscreenCanvas, 0, 0); }; </script>
方法二:逐像素修改ImageData精准控制透明区域
如果背景色有细微色差,或者需要更精细的控制,就用这种方法逐个检查像素,把背景色的像素设为透明:
- 先把精灵画到主Canvas的临时区域
- 获取这个区域的像素数据(ImageData)
- 遍历每个像素,对比颜色,和背景色匹配的就把透明度设为0
- 把修改后的像素数据放回Canvas
示例代码:
<img src="https://www.mariouniverse.com/wp-content/img/sprites/nes/smb/enemies-8.png" height="0" width="0" id="enemies"> <canvas></canvas> <script> const enemies = document.getElementById("enemies"); const canvas = document.querySelector('canvas'); const c = canvas.getContext('2d'); canvas.width = innerWidth; canvas.height = innerHeight; enemies.onload = function() { // 先把Goomba画到主Canvas左上角 c.drawImage(enemies, 0, 18, 16, 16, 0, 0, 16, 16); // 获取这块区域的像素数据 const imageData = c.getImageData(0, 0, 16, 16); const data = imageData.data; // 用取色器获取的背景色精确RGB值 const bgR = 255; const bgG = 228; const bgB = 225; // 遍历每个像素(每4个元素对应一个像素的RGBA) for (let i = 0; i < data.length; i += 4) { const r = data[i]; const g = data[i+1]; const b = data[i+2]; // 匹配背景色就把透明度设为0(完全透明) if (r === bgR && g === bgG && b === bgB) { data[i+3] = 0; } } // 把修改后的像素数据放回Canvas c.putImageData(imageData, 0, 0); }; </script>
关键注意点
- 必须等图片加载完成再执行绘制逻辑,用
onload事件监听,不然会出现空白或者绘制失败 - 背景色的RGB值一定要精确,用浏览器开发者工具的取色器直接从精灵表背景上取,别凭感觉填,这样才能避免误删Goomba的脚部像素
- 之前用第三方工具切掉脚,是因为工具自动识别透明区域时,把脚部和背景接近的颜色误判成了背景,用代码指定精确颜色就不会有这个问题
内容的提问来源于stack exchange,提问作者Nguyen Tran
相关产品推荐
相关产品推荐

