用HTML5的<canvas>元素实现刮刮乐游戏
用HTML5的<canvas>元素实现刮刮乐,要求:将上面的“图层”的图像可用鼠标刮去,露出下面的“图层”的图像。
示例从简单到复杂。
简单示例
准备两张图像,我这里上面的图像top_image.png,下面的图像bottom_image.png,如下图:
我这里为方便 ,经图片和源码文件放在同一个文件夹中。
先看用一个canvas元素实现刮刮乐,源码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>刮刮乐(Scratch Card)</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #f0f0f0; /* 背景色 */ } canvas { background-image: url('bottom_image.png'); /* 底层图片 */ background-size: cover; } </style> </head> <body> <canvas id="canvas" width="356" height="358"></canvas> <script> var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // 加载上层图片(可被刮去的图层) var img = new Image(); img.src = "top_image.png"; // 上层图片路径 img.onload = function() { ctx.drawImage(img, 0, 0, canvas.width, canvas.height); }; // 标记是否按下鼠标(开始刮卡) var isDown = false; // 鼠标按下事件 canvas.addEventListener('mousedown', function() { isDown = true; // 切换到“擦除”模式 ctx.globalCompositeOperation = 'destination-out'; }); // 鼠标松开事件 canvas.addEventListener('mouseup', function() { isDown = false; }); // 鼠标移动事件 canvas.addEventListener('mousemove', function(event) { if (isDown) { let x = event.offsetX; let y = event.offsetY; // 绘制擦除效果 ctx.beginPath(); ctx.arc(x, y, 20, 0, Math.PI * 2, false); // 使用圆形笔触 ctx.fill(); ctx.closePath(); } }); </script> </body> </html>
复制
下面用两个canvas元素实现刮刮乐,底层图片和上层图片各用一个canvas元素,效果和上面的一样。实现的源码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>刮刮乐(Scratch Card)2</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #f0f0f0; } #container { position: relative; width: 356px; height: 358px; } canvas { position: absolute; top: 0; left: 0; } </style> </head> <body> <div id="container"> <canvas id="bottomCanvas" width="356" height="358"></canvas> <!-- 底层Canvas --> <canvas id="topCanvas" width="356" height="358"></canvas> <!-- 上层Canvas --> </div> <script> document.addEventListener('DOMContentLoaded', function() { var bottomCanvas = document.getElementById('bottomCanvas'); var topCanvas = document.getElementById('topCanvas'); var bottomCtx = bottomCanvas.getContext('2d'); var topCtx = topCanvas.getContext('2d'); // 加载底层图片 var bottomImage = new Image(); bottomImage.src = 'bottom_image.png'; // 底层图片路径 bottomImage.onload = function() { bottomCtx.drawImage(bottomImage, 0, 0, bottomCanvas.width, bottomCanvas.height); }; // 加载上层图片 var topImage = new Image(); topImage.src = 'top_image.png'; // 上层图片路径 topImage.onload = function() { topCtx.drawImage(topImage, 0, 0, topCanvas.width, topCanvas.height); }; var isDown = false; // 鼠标按下事件 topCanvas.addEventListener('mousedown', function() { isDown = true; topCtx.globalCompositeOperation = 'destination-out'; }); // 鼠标松开事件 topCanvas.addEventListener('mouseup', function() { isDown = false; }); // 鼠标移动事件 topCanvas.addEventListener('mousemove', function(event) { if (!isDown) return; var x = event.offsetX; var y = event.offsetY; // 绘制擦除效果 topCtx.beginPath(); topCtx.arc(x, y, 20, 0, Math.PI * 2, false); // 使用圆形笔触 topCtx.fill(); topCtx.closePath(); }); }); </script> </body> </html>
复制
复杂示例
下面是改进,从列表框(下拉框)选择图片刮刮乐,增加了游戏的趣味性。
先给出效果
项目(project)的目录结构如下:
我这里游戏图片:
源码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>刮刮乐(Scratch Card)3</title> <style> div{ margin:20px; text-align:center; } * { margin: 0; padding: 0; box-sizing: border-box; } body { height: 100vh; display: flex; justify-content: center; align-items: center; background-color: #f0f0f0; } #container { position: relative; width: 356px; height: 358px; } canvas { position: absolute; top: 0; left: 0; } </style> </head> <body> <div> 选择游戏图片 <select id="mySelect" onchange="loadImages()"> <!-- 添加 onchange 事件 --> <option value="1">1</option> <!-- 更改 value 以匹配图像名称 --> <option value="2">2</option> <option value="3">3</option> </select> <div> <div id="container"> <canvas id="bottomCanvas" width="356" height="358"></canvas> <!-- 底层Canvas --> <canvas id="topCanvas" width="356" height="358"></canvas> <!-- 上层Canvas --> </div> <script> function loadImages() { var selectElement = document.getElementById('mySelect'); var selectedValue = selectElement.options[selectElement.selectedIndex].value; var bottomCanvas = document.getElementById('bottomCanvas'); var topCanvas = document.getElementById('topCanvas'); var bottomCtx = bottomCanvas.getContext('2d'); var topCtx = topCanvas.getContext('2d'); // 清除画布 bottomCtx.clearRect(0, 0, bottomCanvas.width, bottomCanvas.height); topCtx.clearRect(0, 0, topCanvas.width, topCanvas.height); // 加载底层图片 var bottomImage = new Image(); bottomImage.src = 'img/bottom' + selectedValue + '.png'; bottomImage.onload = function() { bottomCtx.drawImage(bottomImage, 0, 0, bottomCanvas.width, bottomCanvas.height); }; // 重新加载并绘制上层图片 var topImage = new Image(); topImage.src = 'img/top' + selectedValue + '.png'; // 确保这里的路径正确匹配你的图片路径和命名 topImage.onload = function() { topCtx.globalCompositeOperation = 'source-over'; // 重置合成操作为默认值 topCtx.drawImage(topImage, 0, 0, topCanvas.width, topCanvas.height); // 确保刮刮效果重新应用 addScratchEffect(topCanvas, topCtx); }; } function addScratchEffect(canvas, ctx) { var isDown = false; // 移除之前可能添加的事件监听器 canvas.onmousedown = null; canvas.onmouseup = null; canvas.onmousemove = null; // 鼠标按下事件 canvas.onmousedown = function() { isDown = true; ctx.globalCompositeOperation = 'destination-out'; // 设置合成操作以实现刮效果 }; // 鼠标松开事件 canvas.onmouseup = function() { isDown = false; }; // 鼠标移动事件 canvas.onmousemove = function(event) { if (!isDown) return; var x = event.offsetX; var y = event.offsetY; // 绘制擦除效果 ctx.beginPath(); ctx.arc(x, y, 20, 0, Math.PI * 2); // 使用圆形笔触 ctx.fill(); }; } // 页面加载完毕后初始化画布 document.addEventListener('DOMContentLoaded', function() { loadImages(); // 页面加载时也加载图片 }); </script> </body> </html>
复制
本文是对https://blog.csdn.net/cnds123/article/details/112392014 例子的补充
关于HTML5中,使用<select>元素创建一个列表框(下拉框),并使用JavaScript来操作,可参见https://blog.csdn.net/cnds123/article/details/128353007