当前位置: 首页 > news >正文

用HTML5的<canvas>元素实现刮刮乐游戏

用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

相关文章:

用HTML5的<canvas>元素实现刮刮乐游戏

用HTML5的&#xff1c;canvas&#xff1e;元素实现刮刮乐游戏 用HTML5的<canvas>元素实现刮刮乐&#xff0c;要求&#xff1a;将上面的“图层”的图像可用鼠标刮去&#xff0c;露出下面的“图层”的图像。 示例从简单到复杂。 简单示例 准备两张图像&#xff0c;我这…...

TypeScript + react 中 TypeScript 的加入后 , 有哪些优化项目

在使用 TypeScript 结合 React 进行开发时&#xff0c;TypeScript 提供了许多优化和增强代码质量的方式。以下是一些关键的优化操作和最佳实践&#xff1a; 强类型组件属性&#xff08;Props&#xff09;和状态&#xff08;State&#xff09;: 使用接口或类型别名定义组件的 pr…...

Redis学习路径(构建体系)

学习路径 掌握数据类型&#xff08;分析底层数据结构&#xff09;和缓存的基本使用 (理论使用) 掌握 redis 实现高性能&#xff0c;高可靠、高可用技术 &#xff08;理论&#xff09;学习redis源代码底层实现 (底层实现) 先来一个引言&#xff0c;比较宏观的角度&#xf…...

【README 小技巧】 展示gitee中开源项目start

【README 小技巧】 展示gitee中开源项目start <a target"_blank" hrefhttps://gitee.com/wujiawei1207537021/wu-framework-parent><img srchttps://gitee.com/wujiawei1207537021/wu-framework-parent/badge/star.svg altGitee star/></a>...

tcping实用小工具

Tcping实用小工具命令详解 一、tcping介绍 tcping&#xff1a;tcping命令基于tcp协议监控&#xff0c;可以从较低级别的协议获得简单的&#xff0c;可能不可靠的数据报服务。 原则上&#xff0c;TCP应该能够在从容硬线连接到分组交换或电路交换网络的各种通信系统之上操作。 …...

【Web】Java反序列化之CC2——commons-collections4的新链之一

目录 关于commons-collections4 一个重要的思维模型 触发Transform的关键类&#xff1a;TransformingComparator 反序列化的入口&#xff1a;PriorityQueue Exp 关于commons-collections4 commons-collections4 是 Apache Commons 组件库中的一个项目&#xff0c;它是对旧…...

golang使用gorm操作mysql1

1.mysql连接配置 package daoimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger" )var DB *gorm.DB// 连接数据库&#xff0c;启动服务的时候&#xff0c;init方法就会执行 func init() {username : "roo…...

Flutter异常上报及性能监控实现

1. 页面异常监测 在Flutter中&#xff0c;通常用FlutterError监测Flutter框架抛出的异常&#xff0c;用runZonedGuarded监测应用中用户代码异常。 class AppGuarded {run(Widget app) {//1. 用FlutterError监测flutter框架抛出的异常FlutterError.onError (FlutterErrorDetail…...

基于springboot+vue的工厂车间管理系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…...

Java基础 - Stream 流:Stream API的终端操作

在前两篇博客中&#xff0c;我介绍了构建 Stream 流的多种方式&#xff0c;以及 Stream API 的中间操作&#xff0c;如果你还没有阅读&#xff0c;你可以点击这里和这里查看。 Java基础 - Stream 流&#xff1a;构建流的多种方式 Java基础 - Stream 流&#xff1a;Stream API…...

高级语言期末2009级A卷(计算机学院)

1.编写函数&#xff0c;打印下列序列0&#xff0c;1&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;5&#xff0c;8&#xff0c;13&#xff0c;21&#xff0c;34...(斐波那契序列)的前n项 #include <stdio.h>int main() {int x0,y1,z,n;scanf("%d",&…...

docker-compose搭建php开发环境

Docker Compose简介 Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose&#xff0c;您可以使用 YML 文件来配置应用程序需要的所有服务。然后使用一个命令&#xff0c;就可以从 YML 文件配置中创建并启动所有服务。而DockerCompose作为一种容器编排工具&…...

翻译论文:Beating Floating Point at its Own Game: Posit Arithmetic(一)

仅作记录学习使用&#xff0c;侵删 原文Beating Floating Point at its Own Game: Posit Arithmetic 参考翻译Posit: 替换IEE754的新方式 | SIGARCH 摘要 IEEE标准754浮点数&#xff08;浮点数&#xff09;的直接接点替换 Posit的优势 不需要区间算术或可变大小操作数 如…...

【数据结构-图论】并查集

并查集&#xff08;Union-Find&#xff09;是一种数据结构&#xff0c;它提供了处理一些不交集的合并及查询问题的高效方法。并查集主要支持两种操作&#xff1a; 查找&#xff08;Find&#xff09;&#xff1a;确定某个元素属于哪个子集&#xff0c;这通常意味着找到该子集的…...

云计算时代的运维: 职业发展方向与岗位选择

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua&#xff0c;在这里我会分享我的知识和经验。&#x…...

java锁底层概述

Java中的锁是并发编程中核心的同步机制之一&#xff0c;用于控制多个线程对共享资源的访问&#xff0c;以保证数据的一致性和完整性。Java锁的底层实现依赖于操作系统的原生线程模型和Java虚拟机&#xff08;JVM&#xff09;的实现。这里主要讨论两种常见的锁&#xff1a;synch…...

win10如何添加指纹登陆

1、首先进入设置,进入下一个设置页面 2、在下一个设置页面内,我们直接使用右上角的搜索框,输入“指纹/finger”进行搜索。回车之后进入设置指纹登陆选项 3、设置指纹登陆的前期是设置好你的密码和pin码(先要设定登录密码和pin码),这里pin和密码都可以直接登陆我们的win10,设…...

足底筋膜炎的症状及治疗

足底筋膜炎症状&#xff1a;足底筋膜炎通常表现为足跟部疼痛&#xff0c;尤其是在晨起或长时间站立、行走后加重。疼痛可能向足底前部或足弓处放射&#xff0c;严重时可能影响行走。此外&#xff0c;患者还可能出现足跟部肿胀、皮肤温度升高、局部压痛等症状。 足底筋膜炎治疗方…...

udp丢包问题研究

//发现udp 有收不到数据包现象. 一: 观察丢包 1. ifconfig enp8s0 2. netstat -s -u 二: 修改系统缓存参数. recv_buffer_size 修改系统buffer_size sysctl -w net.core.rmem_max26214400 sysctl -w net.core.rmem_default26214400 三: 应用程序考虑 av_dict_set(&m_o…...

在idea中用模板骨架初始创建maven管理的web项目时没有src有关的目录的解决方案

一.问题如下 二.解决方法 首先关闭当前项目&#xff0c;接着修改全局设置&#xff0c;重新创建项目 在VM Options中添加"-DarchetypeCataloginternal"&#xff0c;点击ok保存 点击创建&#xff0c;如果创建成功没报错且有src&#xff0c;就ok了。 当然如果出现以下…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...