文章目录
实例:选电影票(通过DOM对象的方法实现)
效果展示
1. 初始状态
浅灰色的表示可以选择的座位;红色的表示票已经售出,不可选择。
2. 选择
点击要选择的座位,会计算出票价,并显示选择的座位对应的票。
3. 取消
通过点击绿色的座位(或者下方的票),实现取消票的选择。
分析
1. 布局
在这个例子中,布局较为简单,使用三个容器布局即可:第一个容器用来放置座位、第二个容器用来放置选择的票、第三个容器用来放置已经选择的票的总价格。
<body>
<div id="seats" class="center border">
</div>
<div id="selected" class="center border top_margin">
</div>
<div class="center total">
总票价:¥<span id="totalPrice">0</span>
</div>
</body>
2. 电影票及电影票生成
简单分析,一张电影票最基础的信息有:id、行号、列好、价格、是否售出。(其实真正要做电影票的业务,还要包括其他的信息,例如电影名,放映事件等等。这里只是为了巩固之前学习的知识)
因此,可以写一个简单的类。
function Ticket(ticketId, rowId, colId, price, isSold){
this.ticketId = ticketId;
this.rowId = rowId;
this.colId = colId;
this.isSold = isSold;
this.price = price;
}
接下来需要一个模拟的方法,用来生成一个场次的电影票。
function getTickets(rowNum, colNum, price){
var tickets = {
rowNum : rowNum,
colNum : rowNum,
ticketArray : new Array()
};
for(let i = 0; i < rowNum; ++i){
for(let j = 0; j < colNum; ++j){
let isSold = Math.random() > 0.8 ? true : false;//让其中一些票“售出”
tickets.ticketArray.push(new Ticket(i * colNum + j, i + 1, j + 1, 35.5, isSold));
}
}
return tickets;
}
3. 根据生成的电影票,生成可视化的座位
/**
* @param tickets 模拟生成的电影票对象
*/
function buildSeats(tickets){
//首先获取放置座位的容器
let seats = document.getElementById("seats");
//根据电影票的列数,生成不同的容器宽度
//每个座位的大小(width + border + 2 * margin)
seats.style.width = tickets.colNum * (28 + 2 + 2 * 5) + "px";
for(let i = 0; i < tickets.rowNum; ++i){
for(let j = 0; j < tickets.colNum; ++j){
//创建一个“座位”元素
let seat = document.createElement("span");
//给这个座位添加样式,让它的class="seat"
seat.className = "seat";
//把这个座位对应的电影票,作为这个座位的属性,保存起来
seat.ticket = tickets.ticketArray[i * tickets.colNum + j];
//在一次购票过程中是否被选中,防止座位多次被选择
seat.ticket.selected = false;
//如果这个座位对应的票已经售出,修改它的颜色为红色
if(seat.ticket.isSold){
seat.style.backgroundColor = "#a55";
}
//绑定点击事件,在“点击座位”时触发
seat.onclick = clickSeat;
//将座位作为子节点插入seats,被渲染到页面中
seats.appendChild(seat);
}
}
}
4. 点击座位时,触发的操作
function clickSeat(){
//获得这个座位对应的票
var ticket = this.ticket;
//如果这个票已经售出,点击这个座位不会有任何效果
if(ticket.isSold)
return;
//接下来判断这个座位是否在被选中、
//1. 如果未选中,则选择这张票
//2. 如果已经选中了,则取消选择这张票
if(!this.selected){
//选中座位时,修改它的颜色为绿色
this.style.backgroundColor = "#3a3";
//将这个座位的状态修改为“已选中”
this.selected = true;
//获得“以选择票”容器对应的DOM对象
var selected = document.getElementById("selected");
//获得“总价格”容器对应的DOM对象
var totalPrice = document.getElementById("totalPrice");
//创建一个元素(对象),表示已经选择的票
var selectedBtn = document.createElement("button");
//将它与对应的座位绑定,在后续点击时,修改座位的状态
selectedBtn.seat = this;
//座位记录这个按钮,再次点击这个座位时,要删除这个座位
this.selectedBtn = selectedBtn;
//提示选择的座位的位置
selectedBtn.innerHTML = ticket.rowId + "排" + ticket.colId + "座";
//添加样式
selectedBtn.className += "selected";
//绑定点击事件(用来取消座位的选择)
selectedBtn.onclick = cancelSelected;
//记录对应的票
selectedBtn.ticket = ticket;
//渲染
selected.appendChild(selectedBtn);
//修改总价格
let money = Number(totalPrice.innerHTML);
totalPrice.innerHTML = money + ticket.price;
}else{
//座位已经被选中,再次点击取消选中
this.selectedBtn.onclick();
}
}
5. 取消“选中”
function cancelSelected(){
//修改座位状态为未选中
this.seat.selected = false;
//修改总价格
var totalPrice = document.getElementById("totalPrice");
let money = Number(totalPrice.innerHTML);
totalPrice.innerHTML = money - this.ticket.price;
//删除结点
this.parentNode.removeChild(this);
//修改座位颜色
this.seat.style.backgroundColor = "rgb(239, 239, 239)"
}
6. 渲染
buildSeats(getTickets(20, 20, 35.5));