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

前端如何用 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.kler.cn/a/464270.html

相关文章:

  • 超越YOLO11!DEIM:先进的实时DETR目标检测
  • SAP SD销售模块常见BAPI函数
  • node.js之---CommonJS 模块
  • ubuntu22.04录屏黑屏,飞书共享屏幕黑屏问题
  • C++ —— 智能指针
  • 如何利用Logo设计免费生成器创建专业级Logo
  • 【人工智能数据科学与数据处理】——深入详解数据科学与数据处理之数据获取与清洗
  • Visual Studio 2022安装教程
  • Effective C++读书笔记——item2(const,enum,inlines取代#define)
  • Java实现下载excel模板,并实现自定义下拉框
  • 应用架构模式
  • Python 列表的高级索引技巧
  • axios 实现进度监控
  • 第3章 总线
  • 搭建开源版Ceph分布式存储
  • 跨域问题解决
  • Java网络套接字
  • 云原生架构:构建高效、可扩展的微服务系统
  • 【LeetCode Hot100 二分查找】搜索插入位置、搜索二维矩阵、搜索旋转排序数组、寻找两个正序数组的中位数
  • 获取淘宝分类详情:深入解析taobao.cat_get API接口
  • leetcode热题100(739. 每日温度)单调栈c++
  • 革新排版机产线:一体式IO模块引领自动化高效控制新时代
  • orm03
  • js 文档注释
  • springboot实战(19)(条件分页查询、PageHelper、MYBATIS动态SQL、mapper映射配置文件、自定义类封装分页查询数据集)
  • 2025-1-2-sklearn学习(30)模型选择与评估-验证曲线: 绘制分数以评估模型 真珠帘卷玉楼空,天淡银河垂地。