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

前端如何用 canvas 做电影院选票功能

一、布局与基础设置

1. HTML 结构

首先在 HTML 文件中创建一个`canvas`元素,用于绘制座位图。例如:

<canvas id="seat-canvas" width="800" height="600"></canvas>

2. CSS 样式

可以为`canvas`元素添加一些基本的样式,如边框等,让它在页面中更好地显示。

#seat-canvas {border: 1px solid black;}

3. JavaScript 初始化

在 JavaScript 文件中获取`canvas`元素,并获取其绘图上下文。绘图上下文有两种类型:`2d`和`webgl`,这里使用`2d`上下文来绘制简单的座位图。

const canvas = document.getElementById("seat-canvas");const ctx = canvas.getContext("2d");

二、绘制座位图

1. 定义座位布局

假设电影院的座位是一个矩形排列的矩阵,可以用一个二维数组来表示座位布局。例如,`0`表示空座位,`1`表示已售座位,`2`表示可选座位。

const seatLayout = [[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],];

2. 绘制单个座位

编写一个函数来绘制单个座位。可以根据座位的状态(可选、已售等)来绘制不同的颜色或样式。例如,用绿色表示可选座位,红色表示已售座位,灰色表示不可用座位。

const seatWidth = 40;const seatHeight = 40;const seatMargin = 5;function drawSeat(x, y, status) {ctx.beginPath();ctx.rect(x, y, seatWidth, seatHeight);if (status === 0) {ctx.fillStyle = "gray";} else if (status === 1) {ctx.fillStyle = "red";} else if (status === 2) {ctx.fillStyle = "green";}ctx.fill();ctx.strokeStyle = "black";ctx.stroke();}

3. 绘制整个座位图

使用嵌套循环遍历座位布局数组,调用`drawSeat`函数来绘制每个座位。

let x = 0;let y = 0;for (let row = 0; row < seatLayout.length; row++) {for (let col = 0; col < seatLayout[row].length; col++) {drawSeat(x, y, seatLayout[row][col]);x += seatWidth + seatMargin;}x = 0;y += seatHeight + seatMargin;}

三、实现选票功能

1. 添加点击事件监听器

为`canvas`元素添加一个点击事件监听器,当用户点击座位时,判断点击的位置对应的座位,并根据座位状态进行相应的操作。

canvas.addEventListener("click", function (e) {const rect = canvas.getBoundingClientRect();const x = e.clientX - rect.left;const y = e.clientY - rect.top;let seatX = Math.floor(x / (seatWidth + seatMargin));let seatY = Math.floor(y / (seatHeight + seatMargin));if (seatX >= 0 &&seatX < seatLayout[0].length &&seatY >= 0 &&seatY < seatLayout.length) {let seatStatus = seatLayout[seatY][seatX];if (seatStatus === 2) {seatLayout[seatY][seatX] = 1;drawSeat(seatX * (seatWidth + seatMargin),seatY * (seatHeight + seatMargin),1);}}});

2. 记录所选座位信息

可以创建一个数组来记录所选座位的信息,例如座位的坐标或者座位在座位布局数组中的索引。

const selectedSeats = [];canvas.addEventListener("click", function (e) {const rect = canvas.getBoundingClientRect();const x = e.clientX - rect.left;const y = e.clientY - rect.top;let seatX = Math.floor(x / (seatWidth + seatMargin));let seatY = Math.floor(y / (seatHeight + seatMargin));if (seatX >= 0 &&seatX < seatLayout[0].length &&seatY >= 0 &&seatY < seatLayout.length) {let seatStatus = seatLayout[seatY][seatX];if (seatStatus === 2) {seatLayout[seatY][seatX] = 1;drawSeat(seatX * (seatWidth + seatMargin),seatY * (seatHeight + seatMargin),1);selectedSeats.push({ x: seatX, y: seatY });}}});

四、其他功能扩展

1. 显示座位信息

可以在页面上添加一个区域来显示所选座位的信息,如座位号、排数等。

const seatInfoDiv = document.createElement("div");document.body.appendChild(seatInfoDiv);function updateSeatInfo() {let seatInfoText = "所选座位:";selectedSeats.forEach((seat) => {seatInfoText += `排 ${seat.y + 1} 座 ${seat.x + 1}, `;});seatInfoDiv.textContent = seatInfoText;}canvas.addEventListener("click", function (e) {//... 前面的点击事件处理代码updateSeatInfo();});

2. 与后端交互(购买功能)

如果要实现真正的购票功能,需要将所选座位信息发送到后端服务器。可以使用`fetch`或`XMLHttpRequest`等方法来发送数据。例如:

const buyButton = document.createElement("button");buyButton.textContent = "购买所选座位";document.body.appendChild(buyButton);buyButton.addEventListener("click", function () {const seatData = {selectedSeats: selectedSeats,};fetch("https://example.com/buy-seats", {method: "POST",headers: {"Content-Type": "application/json",},body: JSON.stringify(seatData),}).then((response) => response.json()).then((data) => {if (data.success) {alert("购票成功!");} else {alert("购票失败。");}});});


http://www.mrgr.cn/news/82292.html

相关文章:

  • 有一对兔子,从出生后第三个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少?
  • vue2和vue3指令
  • 网站服务器中的文件被自动删除的原因
  • [实战]Ubuntu使用工具和命令无法ssh,但使用另一台Ubuntu机器可以用命令ssh,非root用户。
  • EE213 Lab virtuoso final project SRAM designlayout
  • Nodejs 安装配置多个版本
  • UE5动画蓝图
  • 24.Java 新特性扩展(重复注解、类型注解)
  • 人工智能安全与隐私——联邦遗忘学习(Federated Unlearning)
  • 51c视觉~合集40
  • 硬件设计-关于ADS54J60的校准问题
  • 多种方式访问mysql的对比分析
  • Pygame Zero(pgzrun)详解(简介、使用方法、坐标系、目录结构、语法参数、安装、实例解释)
  • NLP中的神经网络基础
  • SELECT的使用
  • GRAPE——RLAIF微调VLA模型:通过偏好对齐提升机器人策略的泛化能力(含24年具身模型汇总)
  • 矩阵的因子分解1-奇异值分解
  • 本地LLM部署--llama.cpp
  • Go 语言:Jank 简客博客系统
  • 我在广州学 Mysql 系列——插入、更新与删除数据详解以及实例
  • 数据结构与算法Python版 拓扑排序与强连通分支
  • chatwoot 开源客服系统搭建
  • 我的 2024 年终总结
  • 【信号滤波 (中)】采样条件及多种滤波算法对比(滑动平均/陷波滤波)
  • 【机器学习】工业 4.0 下机器学习如何驱动智能制造升级
  • JSON 系列之3:导入JSON标准示例数据