求助:如何用CSS和JS修改2行3列拼图的方块形状
自定义形状拼图块实现方案
我正在尝试用CSS和JavaScript制作一个2行3列的拼图,拼图块均为黑色且需切割成不同形状,用户需拖拽拼图块到面板完成拼接。已编写JavaScript代码生成面板与拼图块,并实现了拖拽功能,但不知如何将方形拼图块修改为其他形状,寻求技术帮助。
方法1:使用CSS clip-path 自定义形状
这是轻量化方案,无需额外图片,直接通过CSS裁剪出不规则形状,同时保证面板对应位置与拼图块形状匹配。
实现步骤
- 为2行3列的6个拼图块定义不同的形状类名
- 用
div代替img作为拼图元素,通过CSS设置黑色背景和clip-path路径 - 保持原有拖拽逻辑,仅调整元素类型和样式
代码调整示例
CSS 样式
body { font-family: Arial, Helvetica, sans-serif; text-align: center; } #board { width: 390px; height: 380px; border: 2px solid purple; margin: 0 auto; display: flex; flex-wrap: wrap; } #pieces { width: 780px; height: 200px; border: 2px solid purple; margin: 20px auto; display: flex; gap: 10px; padding: 5px; box-sizing: border-box; justify-content: center; align-items: center; } .board-tile, .piece-tile { width: 130px; height: 190px; background-color: black; cursor: grab; } .board-tile:active, .piece-tile:active { cursor: grabbing; } /* 6种自定义形状 */ .shape-1 { clip-path: polygon(0 0, 100% 0, 100% 80%, 80% 100%, 0 100%); } .shape-2 { clip-path: polygon(0 0, 100% 0, 100% 100%, 20% 100%, 0 80%); } .shape-3 { clip-path: polygon(0 20%, 20% 0, 100% 0, 100% 100%, 0 100%); } .shape-4 { clip-path: polygon(0 0, 80% 0, 100% 20%, 100% 100%, 0 100%); } .shape-5 { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%, 20% 50%); } .shape-6 { clip-path: polygon(0 0, 100% 0, 80% 50%, 100% 100%, 0 100%); }
JavaScript 逻辑
var rows = 2; var columns = 3; var currTile; var otherTile; var turns = 0; // 定义6种形状类名 const shapeClasses = ['shape-1', 'shape-2', 'shape-3', 'shape-4', 'shape-5', 'shape-6']; window.onload = function() { // 初始化2x3面板 for (let r = 0; r < rows; r++) { for (let c = 0; c < columns; c++) { let tile = document.createElement("div"); tile.classList.add('board-tile', shapeClasses[r*3 + c]); tile.draggable = true; // 绑定拖拽事件 tile.addEventListener("dragstart", dragStart); tile.addEventListener("dragover", dragOver); tile.addEventListener("dragenter", dragEnter); tile.addEventListener("dragleave", dragLeave); tile.addEventListener("drop", dragDrop); tile.addEventListener("dragend", dragEnd); document.getElementById("board").append(tile); } } // 生成并打乱拼图块 let pieces = [...shapeClasses]; for (let i = pieces.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [pieces[i], pieces[j]] = [pieces[j], pieces[i]]; } for (let i = 0; i < pieces.length; i++) { let tile = document.createElement("div"); tile.classList.add('piece-tile', pieces[i]); tile.draggable = true; // 绑定拖拽事件 tile.addEventListener("dragstart", dragStart); tile.addEventListener("dragover", dragOver); tile.addEventListener("dragenter", dragEnter); tile.addEventListener("dragleave", dragLeave); tile.addEventListener("drop", dragDrop); tile.addEventListener("dragend", dragEnd); document.getElementById("pieces").append(tile); } } // 拖拽核心逻辑 function dragStart() { currTile = this; } function dragOver(e) { e.preventDefault(); } function dragEnter(e) { e.preventDefault(); } function dragLeave() {} function dragDrop() { otherTile = this; } function dragEnd() { // 仅允许拼图块与面板位置交换 if (!currTile.classList.contains('piece-tile') || !otherTile.classList.contains('board-tile')) { return; } // 交换形状类名实现匹配 const currShape = currTile.classList[1]; const otherShape = otherTile.classList[1]; currTile.classList.remove(currShape); currTile.classList.add(otherShape); otherTile.classList.remove(otherShape); otherTile.classList.add(currShape); turns += 1; // 如需显示步数,可添加元素并赋值:document.getElementById("turns").innerText = turns; }
HTML 结构
<body> <br> <div id="board"></div> <div id="pieces"></div> </body>
其他可选方案
- SVG绘制复杂形状:用SVG路径定义更精细的拼图形状,直接嵌入到
div中或作为独立文件引入 - 带透明通道的PNG图片:用图像编辑工具制作不规则黑色拼图块(透明区域为裁剪部分),替换原代码中的图片资源
内容的提问来源于stack exchange,提问作者user15442201
相关产品推荐
相关产品推荐

