前端小项目(一)| 电影院座位预定
前言
开始好好学习前端啦。学紫色爱心记录一波!!
初步学了html,css,js,在github上找了几个前端小项目模仿着练练手。第一个就是电影院座位预定页面,主要的功能是:选择看哪部电影、选择座位、自动生成价格。
完整代码放在https://github.com/titibabybaby/FED/tree/main/movie%20seat%20booking 学习github上大佬bradtraversy的demo,感谢~
效果长这样~
1.html
html代码主要是搭建整体框架、结构:
- movie-container :可以选择的电影|movie
- showcase :展示屏幕+三种座位类型|seat、seat seatshow、seat occupied
- seat-container:座位部分,6行8列|row|seat/seat occupied
- text:显示选择的个数和总价格|num、price
<div class="movie-container">
<label>pick a movie : </label>
<select id="movie">
<option value="32">头文字D(¥32)</option>
<option value="38">想见你(¥38)</option>
<option value="35">禁闭岛(¥35)</option>
<option value="30">阳光姐妹淘(¥30)</option>
</select>
</div>
<ul class="showcase">
<li>
<div class="seat"></div>
<small>Avaliable</small>
</li>
<li>
<div class="seat seatshow"></div>
<small>Selected</small>
</li>
<li>
<div class="seat occupied"></div>
<small>Occupied</small>
</li>
</ul>
座位部分放一点~重复就ok
<div class="seat-container">
<div class="screen"></div>
<div class="row">
<div class="seat"></div>
<div class="seat"></div>
<div class="seat"></div>
<div class="seat occupied"></div>
<div class="seat"></div>
<div class="seat"></div>
<div class="seat occupied"></div>
<div class="seat"></div>
</div>
<div class="text">
<p>You have selected <span id=num>num</span>
seats for a price of
<span id="price">price</span>
</p>
</div>
2. CSS
主要是设计丰富html元素的样式:
- 对class类,css用 .
- 对id属性的,css用 #
Note:
- body、movie-container、showcase、row、li…都用的弹性布局:
display: flex;
justify-content:
align-items:
接下来贴我觉得重要的代码~
body{
background-color:darkslategray;
font-family:Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.movie-container{
display: flex;
justify-content: center; /*弹性容器属性*/
align-items: center; /*弹性布局容器属性*/
width: 800px;
height: auto;
margin: 100px auto 0 auto;
}
.showcase{
background-color:olive;
border-radius: 3px;
display: flex;
justify-content: space-between;
list-style-type: none;
width: 300px;
margin: 30px auto;
padding: 5px 10px;
}
.showcase li{
color:lightgray;
display: flex;
align-items: center;
justify-content: center;
margin: 0 10px;
}
关于.screen,屏幕的设计:首先先画一个矩形,然后用transform让它沿x轴旋转,注意还要在其父元素seat-container上调整视角距离perspective,调近一些。才会看起来明显是一个梯形,像电影屏幕~
.screen{
margin:5px auto 20px auto;
width: 250px;
height: 60px;
transform:rotateX(-28deg);
background-color: snow;
box-shadow: 0 3px 10px rgba(250, 246, 246, 0.7); /*0.7是不透明度*/
}
关于seat,首先画一个小正方形,然后让其上面左右都有一个圆边角,就像一个小座位啦~
.seat{
background-color:darkgrey;
width: 15px;
height: 12px;
border-top-left-radius: 6px;
border-top-right-radius: 6px;
margin: 0px 3px;
}
.seat设置了三种属性,被占用的(白色),当前选择的(三文鱼色),在showcase展示的被选择的(三文鱼色),其本身是未被选择状态(灰色)。
.seat.occupied{
background-color:floralwhite;
}
.seat.selected{
background-color:salmon;
}
.seat.seatshow{
background-color:salmon;
}
.seat:not(.occupied):hover{
background-color: salmon;
transform: scale(1.2);
cursor:pointer;
}
.seat:not(.occupied):active{
background-color: salmon;
cursor:pointer;
}
.seat:nth-last-of-type(2){
margin-left: 20px;
}
.seat:nth-last-of-type(6){
margin-left: 20px;
}
3.JavaScript
1.const定义变量
const container: 从.seat-container
const seats: 从.seat:(not occupied
const num:记录选择的电影票数量
const price:总价格
const movieSelect:选择的电影座位
const selectedMovieIndex = localStorage.getItem (‘selectedMovieIndex’);
2.let定义变量(可变的)
ticketPrice = + movieSelect.value
3.声明函数
- 保存选择的电影的index和moviePrice(价格)
function setMovieData(movieIndex, moviePrice){
//localStorage.setItem(key,value) 是本地存储,永久性的,将value存储在key字段
localStorage.setItem('selectedMovieIndex',movieIndex);
localStorage.setItem('selectedMoviePrice',moviePrice);
}
- 更新选择的电影总数num以及价格price
function updateSelectedCount(){
const selectedSeats=document.querySelectorAll('.seat.selected');
//.map()返回一个新数组,里面存着选择的座位的index
const seatsIndex=[...selectedSeats].map(seat=>[...seats].indexOf(seat));
//存储在本地
localStorage.setItem('selectedSeats',JSON.stringify(seatsIndex));
//计算选择的座位数量,并写到num里
const selectedSeatsCount=selectedSeats.length;
num.innerText=selectedSeatsCount;
//计算总价格
price.innerText=selectedSeatsCount*ticketPrice;
//将选择的电影和相对于的价格存储在本地
setMovieData(movieSelect.selectedIndex,movieSelect.value);
}
- 更新populateUI(把被选中的seat加一个selected属性)
//从localStorage获取数据selectedSeats数据,并把被选中的seat加一个selected属性,更新populate UI
function populateUI(){
//JSON.parse() 方法将数据转换为 JavaScript 对象。
selectedSeats=JSON.parse(localStorage.getItem('selectedSeats'));
if(selectedSeats!=null&&selectedSeats.length>0){
seats.forEach((seat,index)=>{
if(selectedSeats.indexOf(index)>-1){
//加属性.selected
seat.classList.add('selected');
}
});
}
}
- 两个事件
//选择movie事件
movieSelect.addEventListener('change',e=>{
ticketPrice=+e.target.value;
updateSelectedCount();
});
//点击seat事件
container.addEventListener('click', e => {
if (
e.target.classList.contains('seat') &&
!e.target.classList.contains('occupied')
) {
e.target.classList.toggle('selected');
updateSelectedCount();
}
});
完结撒花~感觉记录了一下印象也更深刻了。