如何在棋盘尺寸不固定时从CSS精灵图提取国际象棋棋子?
嘿,这个问题我之前做国际象棋小项目的时候刚好踩过坑!用CSS精灵图来减少HTTP请求确实是个聪明的选择,尤其是这种需要一堆小图标的场景。针对可变尺寸棋盘的适配,核心其实是把棋子的尺寸和棋盘格子绑定,然后用相对比例来计算精灵图的背景位置和大小,给你几个具体的实现思路:
第一步:先摸清楚精灵图的布局比例
首先得搞清楚你用的这张SVG精灵图的结构:它是2行(白棋一行、黑棋一行),每行8个棋子(对应国际象棋的各类棋子,哪怕有重复也不影响)。也就是说:
- 每个棋子的宽度占整个精灵图宽度的
1/8 - 每个棋子的高度占整个精灵图高度的
1/2 - 每个棋子的相对位置可以用比例来表示(比如白王在左上角,比例坐标是
(0, 0);白后是(1/8, 0);黑王是(0, 1/2)以此类推)
第二步:绑定棋子尺寸到棋盘格子
不管棋盘总尺寸怎么变,每个格子的边长(我们叫它 squareSize)肯定是「棋盘总宽度 / 8」(国际象棋是8×8格子)。我们把棋子的容器尺寸直接和这个 squareSize 绑定:
- 用CSS变量来动态传递这个值,比如定义
--square-size,然后给棋子容器设置:
.chess-piece { width: var(--square-size); height: var(--square-size); background-image: url('Chess_Pieces_Sprite.svg'); background-repeat: no-repeat; }
- 当棋盘尺寸变化时,用JS计算
squareSize并更新这个变量就行,比如:
const board = document.getElementById('chess-board'); const updatePieceSize = () => { const squareSize = board.offsetWidth / 8; document.documentElement.style.setProperty('--square-size', `${squareSize}px`); }; // 初始化+监听窗口变化 updatePieceSize(); window.addEventListener('resize', updatePieceSize);
第三步:用相对比例设置精灵图的背景参数
这一步是关键,不用固定像素值,全用百分比来适配:
- background-size:要让单个棋子刚好填满容器,我们需要把整个精灵图缩放成「8倍容器宽、2倍容器高」,这样每个1/8宽、1/2高的棋子区域就刚好匹配容器大小。所以设置:
.chess-piece { background-size: 800% 200%; /* 8×100% = 800%,2×100% = 200% */ }
- background-position:根据每个棋子的相对比例来设置偏移,比如:
/* 白棋行(y轴偏移0) */ .white.king { background-position: 0 0; } .white.queen { background-position: -12.5% 0; } /* 1/8 × 100% = 12.5%,负号是向左偏移 */ .white.rook { background-position: -25% 0; } .white.bishop { background-position: -37.5% 0; } .white.knight { background-position: -50% 0; } .white.pawn { background-position: -62.5% 0; } /* 黑棋行(y轴偏移50%) */ .black.king { background-position: 0 -50%; } .black.queen { background-position: -12.5% -50%; } .black.rook { background-position: -25% -50%; } .black.bishop { background-position: -37.5% -50%; } .black.knight { background-position: -50% -50%; } .black.pawn { background-position: -62.5% -50%; }
额外小Tips
- 因为用的是SVG精灵图,不管怎么缩放都不会模糊,完美适配各种尺寸的棋盘;
- 如果之后精灵图布局有变化,只需要调整比例数值就行,不用改逻辑;
- 如果你的棋盘格子不是正方形(虽然国际象棋一般都是),可以把background-size的宽和高分别设置成
8×格子宽和2×格子高,一样能适配。
内容的提问来源于stack exchange,提问作者bestprogrammerintheworld
相关产品推荐
相关产品推荐

