如何基于Fabric.js将Sprite Sheet转为Canvas横向连续视频缩略图
在Fabric.js中实现连续视频缩略预览组件
核心思路
- 批量加载所有Sprite Sheet图片,确保全部加载完成后再进行布局
- 遍历每张Sprite Sheet,拆分出60个缩略图,按顺序横向排列到Fabric Canvas上
- 借助容器的滚动属性,实现预览条的横向滚动效果
实现代码
// 配置参数 const SPRITE_CONFIG = { thumbnailWidth: 142, thumbnailHeight: 80, cols: 10, rows: 6, totalSprites: 3, // 示例:3分钟视频对应3张Sprite Sheet spritePathPrefix: "path/to/sprite." // 图片路径前缀,最终拼接为sprite.0.jpg格式 }; // 初始化Fabric Canvas const canvasContainer = document.getElementById("timeline-container"); const canvas = new fabric.Canvas("timeline", { height: SPRITE_CONFIG.thumbnailHeight, width: canvasContainer.clientWidth // 初始宽度适配容器 }); // 批量加载所有Sprite Sheet图片 function loadAllSprites() { const promises = []; for (let i = 0; i < SPRITE_CONFIG.totalSprites; i++) { const promise = new Promise((resolve, reject) => { const img = new Image(); img.src = `${SPRITE_CONFIG.spritePathPrefix}${i}.jpg`; img.onload = () => resolve(img); img.onerror = reject; }); promises.push(promise); } return Promise.all(promises); } // 布局所有缩略图到Canvas function layoutThumbnails(spriteImages) { let currentX = 0; // 记录当前缩略图的横向位置 spriteImages.forEach(spriteImg => { // 创建Fabric图片对象,复用原始Sprite图 const fabricSprite = new fabric.Image(spriteImg, { selectable: false, evented: false }); // 遍历当前Sprite Sheet的所有缩略图(10列×6行) for (let row = 0; row < SPRITE_CONFIG.rows; row++) { for (let col = 0; col < SPRITE_CONFIG.cols; col++) { // 计算当前缩略图在Sprite Sheet中的裁剪区域 const cropX = col * SPRITE_CONFIG.thumbnailWidth; const cropY = row * SPRITE_CONFIG.thumbnailHeight; // 克隆图片对象并设置裁剪和位置属性 const thumbnail = fabricSprite.clone(); thumbnail.set({ left: currentX, top: 0, cropX: cropX, cropY: cropY, width: SPRITE_CONFIG.thumbnailWidth, height: SPRITE_CONFIG.thumbnailHeight }); canvas.add(thumbnail); currentX += SPRITE_CONFIG.thumbnailWidth; } } }); // 更新Canvas总宽度为所有缩略图的总宽度 canvas.setWidth(currentX); canvas.setHeight(SPRITE_CONFIG.thumbnailHeight); } // 执行加载与布局流程 loadAllSprites() .then(layoutThumbnails) .catch(err => console.error("Sprite图片加载失败:", err));
容器样式设置(CSS)
要实现横向滚动,需给Canvas的容器添加以下样式:
#timeline-container { width: 100%; overflow-x: auto; overflow-y: hidden; border: 1px solid #eee; } #timeline { display: block; }
关键说明
- 批量加载:用
Promise.all确保所有Sprite图片加载完成后再布局,避免因加载顺序导致的布局错乱 - 裁剪复用:通过克隆Fabric图片对象并设置
cropX/cropY属性,高效拆分Sprite Sheet中的缩略图,减少重复创建图片对象的开销 - 滚动实现:依靠容器的
overflow-x: auto属性实现横向滚动,Canvas总宽度设为所有缩略图的总宽度,高度固定为单张缩略图的高度
内容的提问来源于stack exchange,提问作者Yogesh Yadav
相关产品推荐
相关产品推荐

