You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用纯JavaScript从spritesheet中提取指定精灵切片并返回base64

问题分析

你原有代码存在三个核心问题:

  • 图片是异步加载资源,未等加载完成就执行裁剪逻辑,drawImage操作会失效,画布为空
  • canvas变量定义在循环内部,循环结束后只能拿到最后一个tile的画布,无法匹配坐标获取对应tile
  • 未设置图片跨域属性,画布会被浏览器标记为跨域污染,无法调用toDataURL导出base64

原生JS实现方案

以下是完整可运行的实现,预加载裁剪所有tile缓存后,可直接调用getTile(x, y)获取对应tile的base64编码:

// 雪碧图基础配置
const TILE_SIZE = 16; // 单个tile的实际尺寸
const TILE_GAP = 1; // 雪碧图上tile之间的间隔像素
const SPRITE_URL = 'https://cdn.glitch.me/b3505ee1-a321-48ea-baf5-d84841324af1%2Fd3b13ce6-f5ed-4122-9bd9-37f74d13d470.image.png?v=1634242985542';
const ROW_TOTAL = 8; // 雪碧图总行数
const COL_TOTAL = 20; // 雪碧图总列数

let tileCache = []; // 所有tile的base64缓存
let spriteLoaded = false;

// 预加载雪碧图并裁剪所有tile存入缓存
function initSpriteSheet() {
  return new Promise((resolve, reject) => {
    const spriteImg = new Image();
    // 处理跨域,避免画布被污染
    spriteImg.crossOrigin = 'anonymous';
    spriteImg.src = SPRITE_URL;

    spriteImg.onload = () => {
      for (let row = 0; row < ROW_TOTAL; row++) {
        tileCache[row] = [];
        for (let col = 0; col < COL_TOTAL; col++) {
          const canvas = document.createElement('canvas');
          const ctx = canvas.getContext('2d');
          canvas.width = TILE_SIZE;
          canvas.height = TILE_SIZE;
          // 计算裁剪起始位置,跳过1px间隔
          const sourceX = col * (TILE_SIZE + TILE_GAP) + TILE_GAP;
          const sourceY = row * (TILE_SIZE + TILE_GAP) + TILE_GAP;
          ctx.drawImage(spriteImg, sourceX, sourceY, TILE_SIZE, TILE_SIZE, 0, 0, TILE_SIZE, TILE_SIZE);
          tileCache[row][col] = canvas.toDataURL('image/png');
        }
      }
      spriteLoaded = true;
      resolve();
    };

    spriteImg.onerror = reject;
  });
}

// 目标调用函数:getTile(横向坐标x, 纵向坐标y) 返回对应tile的base64
function getTile(x, y) {
  if (!spriteLoaded) throw new Error('雪碧图未加载完成,请等待初始化完成后调用');
  if (x < 0 || x >= COL_TOTAL || y < 0 || y >= ROW_TOTAL) throw new Error('tile坐标超出范围');
  return tileCache[y][x];
}

// 使用示例
initSpriteSheet().then(() => {
  // 初始化完成后可任意调用getTile
  const knightBase64 = getTile(2, 1);
  // 测试:新窗口打开查看获取到的骑士图案
  const testTab = window.open('about:blank');
  testTab.document.write(`<img src="${knightBase64}" alt="骑士tile">`);
});

注意说明

  • 所有tile仅在初始化时裁剪一次,后续调用getTile直接读取缓存,性能损耗极低
  • 坐标规则和你要求的完全一致,getTile(2,1)即可获取对应骑士图案的base64编码
  • 如果你的业务场景不需要提前缓存所有tile,也可以修改为调用getTile时实时裁剪,按需调整即可

内容的提问来源于stack exchange,提问作者qman101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 11:06:01