影院座位选择简易实现(uniapp)

news2024/11/16 12:50:09

界面展示

主要使用到uniap中的movable-area,和movable-view组件实现。

代码逻辑分析

1、使用movable-area和movea-view组件,用于座位展示

<div class="ui-seat__box">
	<movable-area  class="ui-movableArea">
		<movable-view></movable-view>
	</movable-area>
</div>
.ui-movableArea {
		width: 600rpx;
		height: 500rpx;
		border: 1rpx solid #999;
		overflow: hidden;
	}

先给movable-area组件定义宽高,用于展示区域

2、 给moveable-view设置可移动,宽高等

<movable-area class="ui-movableArea">
				<movable-view direction="all" :out-of-bounds="false" :scale="false" class="ui-movableView"
					:style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}" @change="handleMove"
					scale-max="1.5"
					damping="200"
					@scale="handleSize">

				</movable-view>
			</movable-area>

其中direction,out-of-bounds,scale,scale-max,damping,@scale等配置项在uniapp文档中查看介绍,分别表示为(是否全方向移动,超出能否移动,能否放大,最大的放大倍数,回弹时间,移动的回调)

3、影院的座位数据

通过以下方法,随机生成id唯一的座位,用于座位展示

function generateSeatArray(count) {
  const seats = [];
  for (let i = 0; i < count; i++) {
    seats.push({
      id: i + 1, // 随机生成 1 到 100 之间的唯一ID
      seat_x: (i % 11) + 1, // 规律递增 seat_x,范围 1 到 11
      seat_y: Math.floor(i / 11) + 1, // 规律递增 seat_y,范围 1 到 11
      canBuy: Math.random() > 0.5, // 随机生成 true 或 false
      price: Math.floor(Math.random() * 81) + 20 // 随机生成 20 到 100 之间的整数
    });
  }
  return seats;
}
export default generateSeatArray;

此方法结果为对象数组,表示以左上角为原点,右边为x轴正方向,下面为y轴正方向的坐标(seat_x,seat_y),canBuy表示能否购买此座位,price表示座位价格

[
    {
		seat_x: 1,
		seat_y: 1,
		canBuy: true,
		price: 20
	},
    {
		seat_x: 2,
		seat_y: 1,
		canBuy: true,
		price: 20
	},
    ........
]

4、moveable-view的宽高设置

回到标题2的代码片段

<movable-area class="ui-movableArea">
				<movable-view direction="all" :out-of-bounds="false" :scale="false" class="ui-movableView"
					:style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}" @change="handleMove"
					scale-max="1.5"
					damping="200"
					@scale="handleSize">

				</movable-view>
			</movable-area>

在mova-view中有 :style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}"

whData的数据如下所示,拿到座位数据作为参数传给handleMax方法,得到最大的宽和高

handleMax(array) {
				const maxData = array.reduce((preObj, cur) => {
					preObj.width = Math.max(preObj.width, cur.seat_x);
					preObj.height = Math.max(preObj.height, cur.seat_y)
					return preObj;
				}, {
					width: 0,
					height: 0
				})
				return maxData;
			},

 datalist是标题3中生成的座位数据

this.whData = this.handleMax(dataList);
whData = {
 widht:10,
 height:10
}

5、座位展示

<movable-area class="ui-movableArea">
				<movable-view direction="all" :out-of-bounds="false" :scale="false" class="ui-movableView"
					:style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}" @change="handleMove"
					scale-max="1.5"
					damping="200"
					@scale="handleSize">
                    <view class="ui-seat">
						<!-- 座位 -->
						<view class="ui-item" v-for="item in seatList" :key="item.id"
							:style="{top:30 * item.seat_y + 'px',left:50 * item.seat_x + 'px'}"
							@click="handleSelect(item)">
							<view class="ui-item__class__can" v-if="item.canBuy">{{item.seat_x}},{{item.seat_y}}</view>
							<view class="ui-item__class" v-else>{{item.seat_x}},{{item.seat_y}}</view>
						</view>
					</view>
				</movable-view>
			</movable-area>

在moveabel-view中新增view组件,用于展示每一个座位 ,注意看类(ui-seat)设置成相对定位

	.ui-seat {
		display: flex;
		flex-wrap: wrap;
		position: relative;
	}

类(ui-item)设置成绝对定位


	.ui-item {
		margin: 5px;
		border: #999 1px solid;
		/* padding: 20rpx; */
		position: absolute;
	}

 因为在现实情况下会出现某个地方没有座位的情况,需要使用绝对定位的方式,根据每个座位的x,y的坐标进行展示

:style="{top:30 * item.seat_y + 'px',left:50 * item.seat_x + 'px'}"

这行表示根据每个item项的坐标进行对应展示,并且不会重叠

<view class="ui-item__class__can" v-if="item.canBuy">{{item.seat_x}},{{item.seat_y}}</view>

 <view class="ui-item__class" v-else>{{item.seat_x}},{{item.seat_y}}</view></view>

关于能否选择座位使用v-if来进行判断

6、左边列表展示 

			<movable-area class="ui-movableArea">
				<movable-view direction="all" :out-of-bounds="false" :scale="false" class="ui-movableView"
					:style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}" @change="handleMove"
					scale-max="1.5"
					damping="200"
					@scale="handleSize">
					<view class="ui-seat">
						<!-- 座位 -->
						<view class="ui-item" v-for="item in seatList" :key="item.id"
							:style="{top:30 * item.seat_y + 'px',left:50 * item.seat_x + 'px'}"
							@click="handleSelect(item)">
							<view class="ui-item__class__can" v-if="item.canBuy">{{item.seat_x}},{{item.seat_y}}</view>
							<view class="ui-item__class" v-else>{{item.seat_x}},{{item.seat_y}}</view>
						</view>
						<!-- 列表 -->
						<view class="ui-list" :style="{left: moveX + 'px'}">
							<view class="ui-list__item" v-for="i in whData.height" :key="index">
								{{i + 1}}
							</view>
						</view>
					</view>
				</movable-view>

在座位代码下面新增列表展示,在moveable-view中有@change方法,用于获取上下左右移动了多少,并存到moveX,和moveY中,根据左移的距离判断列表位置

handleMove(e) {
				const {
					x,
					y,
					source
				} = e.detail;
				setTimeout(() => {
					this.moveX = Math.abs(x);
					this.moveY = y;
				}, 200)
			},

完整代码

<template>
	<view class="content">
		<view class="ui-top">
			电影信息
		</view>
		<view class="ui-body">
			以下是座位控制
		</view>
		<div class="ui-seat__box">
			<movable-area class="ui-movableArea">
				<movable-view direction="all" :out-of-bounds="false" :scale="true" class="ui-movableView"
					:style="{width:60 * whData.width + 'px',height:40 * whData.height + 'px'}" @change="handleMove"
					scale-max="1.5"
					damping="200"
					@scale="handleSize">
					<view class="ui-seat">
						<!-- 座位 -->
						<view class="ui-item" v-for="item in seatList" :key="item.id"
							:style="{top:30 * item.seat_y + 'px',left:50 * item.seat_x + 'px'}"
							@click="handleSelect(item)">
							<view class="ui-item__class__can" v-if="item.canBuy">{{item.seat_x}},{{item.seat_y}}</view>
							<view class="ui-item__class" v-else>{{item.seat_x}},{{item.seat_y}}</view>
						</view>
						<!-- 列表 -->
						<view class="ui-list" :style="{left: moveX + 'px'}">
							<view class="ui-list__item" v-for="i in whData.height" :key="index">
								{{i + 1}}
							</view>
						</view>
					</view>
				</movable-view>
			</movable-area>
		</div>

	</view>
</template>

<script>
	import seatfun from './seat-data.js';
	export default {
		data() {
			return {
				title: 'Hello',
				seatList: [],
				whData: {},
				moveX: 0,
				moveY: 0
			}
		},
		onLoad() {
			const dataList = seatfun(50);
			// dataList.splice(2,4);
			// dataList.splice(10,12);
			this.seatList = dataList;
			// 获取宽度
			this.whData = this.handleMax(dataList);
		},
		methods: {
			handleMax(array) {
				const maxData = array.reduce((preObj, cur) => {
					preObj.width = Math.max(preObj.width, cur.seat_x);
					preObj.height = Math.max(preObj.height, cur.seat_y)
					return preObj;
				}, {
					width: 0,
					height: 0
				})
				return maxData;
			},
			handleSelect(item) {
				// console.log(item.seat_x,item.seat_y);
				if (item.canBuy) {
					item.canBuy = !item.canBuy;
				} else {
					// console.log(item);
					uni.showToast({
						title: '此座位不可选'
					})
				}
			},
			handleMove(e) {
				const {
					x,
					y,
					source
				} = e.detail;
				setTimeout(() => {
					this.moveX = Math.abs(x);
					this.moveY = y;
				}, 200)
			},
			handleSize(e){
				const {x,y,scale} = e.detail;
				setTimeout(() => {
					this.moveX = Math.abs(x);
					this.moveY = y;
				}, 200)
			}
		}
	}
</script>

<style scoped>
	view {
		box-sizing: border-box;
	}

	.ui-top {
		height: 200rpx;
		background-color: greenyellow;
	}

	.ui-movableArea {
		width: 600rpx;
		height: 500rpx;
		border: 1rpx solid #999;
		overflow: hidden;
	}

	.ui-seat__box {
		display: flex;
		justify-content: center;
	}

	.ui-seat {
		display: flex;
		flex-wrap: wrap;
		position: relative;
	}

	.ui-movableView {
		width: 700rpx;
		height: 700rpx;
		overflow: hidden;
		background-color: antiquewhite;
	}

	.ui-item__class__can {
		width: 60rpx;
		height: 40rpx;
		background-color: darkred;
	}

	.ui-item__class {
		width: 60rpx;
		height: 40rpx;
		background-color: palegreen;
	}

	.ui-item {
		margin: 5px;
		border: #999 1px solid;
		/* padding: 20rpx; */
		position: absolute;
	}

	.active {
		background-color: greenyellow;
	}

	.ui-list {
		position: absolute;
		top: 30px;
		width: 50rpx;
		background-color: #fff;
	}

	.ui-list__item {
		margin: 10rpx;
		padding: 5rpx;
	}
</style>

seat-data.js代码

function generateSeatArray(count) {
  const seats = [];
  for (let i = 0; i < count; i++) {
    seats.push({
      id: i + 1, // 随机生成 1 到 100 之间的唯一ID
      seat_x: (i % 11) + 1, // 规律递增 seat_x,范围 1 到 11
      seat_y: Math.floor(i / 11) + 1, // 规律递增 seat_y,范围 1 到 11
      canBuy: Math.random() > 0.5, // 随机生成 true 或 false
      price: Math.floor(Math.random() * 81) + 20 // 随机生成 20 到 100 之间的整数
    });
  }
  return seats;
}
export default generateSeatArray;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1574207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ 内存分配时地址对齐

如果数据地址的对齐与CPU相兼容&#xff0c;那么CPU读写内存时性能会更高。 因此在C中&#xff0c;有时会希望在堆或栈中分配内存时&#xff0c;返回的地址能按照特定的长度对齐。 如果希望在栈中分配的内存时&#xff0c;返回地址按照特定长度对齐&#xff0c;可以使用 alig…

IVS模型解释

核心思路 【Implied volatility surface predictability: The case of commodity markets】 半参数化模型&#xff1a;利用各种参数(或者因子)对隐含波动率进行降维&#xff08;静态参数化因子模型&#xff09;&#xff0c;对参数化因子的时间序列进行间接的建模 基于非对称…

蓝桥杯 十一届C++A组 字符排序 21分(运行超时)

思路&#xff1a; 1. 此题考查的冒泡排序中的交换次数&#xff0c;其实就是考察当前数与后面的逆序对个数问题。而为了最大利用位数&#xff0c;应当使每一位都不小于后面的字符&#xff0c;否则会造成一次逆序对的浪费&#xff08;贪心&#xff0c;为了使总位数最少&#xff…

代码随想录算法训练营三刷 day45 | 动态规划 之 70. 爬楼梯 (进阶) 322. 零钱兑换 279.完全平方数

三刷day45 70. 爬楼梯 &#xff08;进阶&#xff09;1. 确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例来推导dp数组 322. 零钱兑换1. 确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组 279.完全平方…

01.IDEA中出现Cannot resolve symbol ‘SpringApplication异常

试了很多次&#xff0c;看了这篇文章终于发现了问题。IDEA解决springboot工程中Cannot resolve symbol SpringApplication异常-CSDN博客 我存在的问题在于Maven home path有误&#xff0c;改正之后就没有问题&#xff0c;不标红了。

逆向案例十二——看准网企业信息json格式的信息

网址&#xff1a;【全国公司排行|排名榜单|哪家好】-看准网 打开开发者工具——刷新——网络——XHR——下滑页面加载新的页面——找到数据包 发现参数加密&#xff0c;返回的数据也进行了加密 按关键字在下方搜索 kiv进入第一个js文件 ctrlf打开文件里面的搜索框继续搜kiv找到…

【机器学习入门】使用YOLO模型进行物体检测

系列文章目录 第1章 专家系统 第2章 决策树 第3章 神经元和感知机 识别手写数字——感知机 第4章 线性回归 第5章 逻辑斯蒂回归和分类 第5章 支持向量机 第6章 人工神经网络(一) 第6章 人工神经网络(二) 卷积和池化 第6章 使用pytorch进行手写数字识别 文章目录 系列文章目录前…

ECAI 2024投稿指南

诸神缄默不语-个人CSDN博文目录 ECAI也写一下&#xff0c;作为备胎。毕竟ECAI是CCF B会。 ECAI dblp官网&#xff1a;https://dblp.uni-trier.de/db/conf/ecai/index.html 征文网址&#xff1a;https://www.ecai2024.eu/calls/main-track ECAI 2024在西班牙开&#xff0c;如…

伦敦银行情上涨时投资盈利

在讨论如何根据伦敦银行情上涨时机投资盈利之前&#xff0c;投资者需要了解伦敦银的特性以及影响其价格波动的因素。伦敦银&#xff0c;即银的伦敦市场交易价格&#xff0c;是全球贵金属交易中的重要参考价。银的价格受到多种因素的影响&#xff0c;包括全球经济状况、货币政策…

FJSP:巨型犰狳优化算法(Giant Armadillo Optimization,GAO)求解柔性作业车间调度问题(FJSP),提供MATLAB代码

一、柔性作业车间调度问题 柔性作业车间调度问题&#xff08;Flexible Job Shop Scheduling Problem&#xff0c;FJSP&#xff09;&#xff0c;是一种经典的组合优化问题。在FJSP问题中&#xff0c;有多个作业需要在多个机器上进行加工&#xff0c;每个作业由一系列工序组成&a…

网络安全流量平台_优缺点分析

FlowShadow&#xff08;流影&#xff09;&#xff0c;Ntm&#xff08;派网&#xff09;&#xff0c;Elastiflow。 Arkimesuricata&#xff0c;QNSMsuricata&#xff0c;Malcolm套件。 Malcolm套件优点&#xff1a;支持文件还原反病毒引擎&#xff08;clamav/yara&#xff09;…

基于单片机冬季供暖室温调节控制系统

**单片机设计介绍&#xff0c;基于单片机冬季供暖室温调节控制系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的冬季供暖室温调节控制系统是一种集温度检测、控制和显示功能于一体的智能化系统。该系统以单片机为…

Kubernetes(k8s):Pod 的 Node Selector详解

Kubernetes&#xff08;k8s&#xff09;&#xff1a;Pod 的 Node Selector详解 1、什么是Node Selector&#xff1f;2、Node Selector的工作原理3、Node Selector的用法1、例如&#xff1a;给node01 、node02 分别打上标签2、使用标签调度Pod3、删除节点的标签 &#x1f496;Th…

SystemC入门学习Demo用例的工程化配置

背景&#xff1a;对不同的用例文件&#xff0c;使用CMakeLists.txt进行工程化管理的演示&#xff0c;这样开发者可以更加关注在代码开发上。 1&#xff0c;首先安装好系统环境的systemC库&#xff1a;ubuntu系统安装systemc-2.3.4流程-CSDN博客 2&#xff0c;准备好一个demo用…

Golang | Leetcode Golang题解之第12题整数转罗马数字

题解&#xff1a; 题解&#xff1a; var (thousands []string{"", "M", "MM", "MMM"}hundreds []string{"", "C", "CC", "CCC", "CD", "D", "DC", "…

Python最简单的图片爬虫

Python最简单的图片爬虫&#xff0c;20行代码带你爬遍整个网站-腾讯云开发者社区-腾讯云 (tencent.com) import urllib.parse import json import requests import jsonpath url https://www.duitang.com/napi/blog/list/by_search/?kw{}&start{} label 美女 label url…

剑指Offer题目笔记27(动态规划单序列问题)

面试题89&#xff1a; 问题&#xff1a; ​ 输入一个数组表示某条街道上的一排房屋内财产的数量。相邻两栋房屋不能同时被盗&#xff0c;问小偷能偷取到的最多财物。 解决方案一&#xff08;带缓存的递归&#xff09;&#xff1a; 解决方案&#xff1a; 由于有报警系统&…

【保姆级教程】如何在 Windows 上实现和 Linux 子系统的端口映射

写在前面 上次分享【保姆级教程】Windows上安装Linux子系统&#xff0c;搞台虚拟机玩玩&#xff0c;向大家介绍了什么是虚拟机以及如何在Windows上安装Linux虚拟机。对于开发同学而言&#xff0c;经常遇到的一个问题是&#xff1a;很多情况下代码开发需要依赖 Linux 系统&…

八股面试速成—计算机网络部分

暑期实习面试在即&#xff0c;这几天八股和算法轮扁我>_ 八股部分打算先找学习视屏跟着画下思维导图&#xff0c;然后看详细的面试知识点&#xff0c;最后刷题 其中导图包含的是常考的题&#xff0c;按照思维导图形式整理&#xff0c;会在复盘后更新 细节研究侧重补全&a…

kubelet安装

安装 在大致了解了一些k8s的基本概念之后&#xff0c;我们实际部署一个k8s集群&#xff0c;做进一步的了解 1. 裸机安装 采用三台机器&#xff0c;一台机器为Master&#xff08;控制面板组件&#xff09;两台机器为Node&#xff08;工作节点&#xff09; 机器的准备有两种方式…