写在前面
本例使用js,jquery等方法实现虚拟餐厅的运行、烹饪、结账、发工资、扩大店面等功能,效果大体如下:
↓↓末尾可以进入demo↓↓
整体功能如下:
使用构造函数创建餐厅、服务员、厨师、雇员、顾客、菜品等,其中服务员和厨师继承于雇员。
各个类添加功能,如餐厅的hire()和fire(),雇员、服务员、厨师的work()等等方法。
使用svg创建图形。
在每个人的工作中,使用迭代来完成人物位置的改变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73function moveout(p){
if(p.name){
p.moving = true;
}
//因为顾客和服务员都会调用moveout,所以加了个判定判断实参是否是服务员。
var src = p.position,
dest = [];
var svg1 = document.createElementNS('http://www.w3.org/2000/svg',"svg")
svg1.setAttribute("width",760)
svg1.setAttribute("height",506)
var cir = document.createElementNS('http://www.w3.org/2000/svg',"circle")
cir.setAttribute("cx",p.position[0])
cir.setAttribute("cy",p.position[1])
cir.setAttribute("r",10)
if(p.name){
dest = [80,10]
cir.setAttribute("fill","rgb(99, 0, 0)")
if(document.getElementById(p.name)){
document.getElementById(p.name).remove();
}
var tex = document.createElementNS('http://www.w3.org/2000/svg',"text")
tex.setAttribute("x", p.position[0] - 45)
tex.setAttribute("y", p.position[1] + 5)
tex.style = "font-size:16;fill:black"
tex.innerHTML = p.name
svg1.append(tex)
}
else{
dest = [770,10]
cir.setAttribute("fill","rgb(170, 170, 255)")
if(document.getElementById(p.seat)){
document.getElementById(p.seat).remove();
}
}
if(src[1] > dest[1]){
src[1] -= 10;
setTimeout(function(){
moveout(p)
},20)
}
else if(src[1] < dest[1]){
src[1] += 10;
setTimeout(function(){
moveout(p)
},20)
}
else if(src[0] > dest[0]){
src[0] -= 10;
setTimeout(function(){
moveout(p)
},20)
}
else if(src[0] < dest[0]){
src[0] += 10;
setTimeout(function(){
moveout(p)
},20)
}
else{
if(!p.slary){
return;
}
else{
p.working = false;
p.moving = false;
}
}
svg1.append(cir)
svg1.id = p.name || p.seat
document.getElementById("person").append(svg1)
return;
}添加锁来锁定需要工作的类型的工作状态,使得任何人不能同时执行多件工作。
统计每天的盈利、支出情况。通过函数判定,当时间进入新的一天时,发工资,并更新统计数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16if(nowHour == 0 && newday == 0){
newday = 1;
//此处判断进入新的一天,并将flag设置为1。
days++;
expend += totleSlary;
x.money -= totleSlary;
InfoUpdate("今天支出了 " + totleSlary + " 工资");
//InfoUpdate是更新所有工作内容的方法。
receipts = 0;
expend = 0;
//重置收入和支出,以便统计每日收支情况。
}
if(nowHour == 1 && newday == 1){
//此处将flag恢复为0。
newday = 0;
}每完成一件工作,及时更新工作内容、效果在一个
- 条目上限20,自上而下更新的div中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function InfoUpdate(str,checkOut){
checkOut = checkOut || null;
//此处根据实参判断是否是结账信息,是的话需要加粗~
var info = document.getElementById("InfoList")
if(info.childNodes.length > 20){
info.childNodes[19].remove()
}
var li = document.createElement("li")
if(checkOut){
li.innerHTML = "<strong>" + str + "</strong>"
}
else{
li.innerHTML = str
}
info.insertBefore(li,info.childNodes[0])
return;
}
期间遇到的问题:
在锁的使用中,遇到了已经锁定了的人物被选中的问题。经过分析,最后发现,我在调用人物的时候,是在函数中部将人物的锁给锁定。也许电脑会很快的计算出来,也许这个过程只需要0.001毫秒。但是即使是0.001毫秒,也有可能导致该人物在同一时间被不同工作选中。而解决的办法就是当人物一进入函数,立马将人物锁定。
在使用setTimeout做函数迭代的过程中发现,假设setTimeout函数之后还有一段代码,则js在编码的时候会先跳过setTimeout去执行下一段代码,而在settimeout的时间到了之后再跳回执行setTimeout中的代码。如:
1
2
3
4
5
6
7
8function(){
setTimeout(function(){
alert("1")
return;
},1000)
alert("2")
}
//会先弹出2,再弹出1闭包函数过多引起的内存泄露。因为各种调用关系比较复杂,导致很多函数有进无出,引起内存泄露。统一再编码整合之后,该问题得到很好的改善。