用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