三国英雄归位游戏
效果图
实现
首先是布局的实现,需要先搭好框架
<div class="f1">
<!-- this指代绑定事件的对象 -->
<img src="img/关羽.webp" alt="" onclick="move(this,0)">
<img src="img/曹操.jpg" alt="" onclick="move(this,1)">
<img src="img/孙权.webp" alt="" onclick="move(this,2)">
<img src="img/刘备.jpg" alt="" onclick="move(this,3)">
<img src="img/刘协.webp" alt="" onclick="move(this,4)">
<img src="img/貂蝉.webp" alt="" onclick="move(this,5)">
</div>
<div class="f2">
<div>曹操</div>
<div>孙权</div>
<div>刘备</div>
<div>貂蝉</div>
<div>关羽</div>
<div>刘协</div>
</div>
可以看到是一个div中有多个子元素,那么怎么将他们平均地横排分布呢?
首先可能想到地是父级元素相对定位,子元素绝对定位的方式来实现。但是会发现一个问题:这样的话每个子元素都是相对于父元素的左上角的位置来定位的,它们的left他和top初始值不一样,一开始将会全部都重叠在一起,如图
如果想要它们平均的分布开来,还得设置每一个子元素的left和top的值,因为与靠后的子元素离父元素的左边距越远,并且考虑到还得平均分布,那么每一个元素的left值都得计算出来,才能保证它们之间间距相等。
#heroList div{
position: absolute;
display: block;
}
#heroList div:nth-child(1){
left: 10px;
z-index: 999;
}
#heroList div:nth-child(2){
left: 170px;
z-index: 999;
}
#heroList div:nth-child(3){
left: 330px;
z-index: 999;
}
#heroList div:nth-child(4){
left: 490px;
z-index: 999;
}
#heroList div:nth-child(5){
left: 650px;
z-index: 999;
}
#heroList div:nth-child(6){
left: 810px;
z-index: 999;
}
这样写的代码是非常冗余且复杂的。
所以我们可以使用**flex
**流式布局,它主要用来操作多个子元素的。
-
首先设置父元素为flex布局,在父元素上声明每个子元素平均间距分布
.f1,.f2{ display: flex; /* 平均分布 */ justify-content: space-around; }
justufy-content
用于设置子元素的横向分布情况,还有align-content
用于设置子元素竖向分不清情况 -
让每一个子元素相对自己本身的初始位置定位,也就是相对定位。这要在操作这些子元素时它们的left和top的改动都是相对于自己本身的初始位置来改动的。
.f1>img{ width: 200px; height: 300px; position: relative; }
这样就只需要几行css代码就能实现布局了。
其次则是js代码的实现,控制img移动:
首先需要为每一个img添加上点击事件,当点击哪个img键盘就移动的是哪个img,那这样的话是不是就需要为每一个img设置id值来获 取它们用于操作呢?这固然是一种办法,当然还有更好的办法,那就是在调用事件方法时候传入一个**this
**参数,这个this代表的就是绑 定事件的dom对象
<div class="f1">
<!-- this指代绑定事件的对象 -->
<img src="img/关羽.webp" alt="" onclick="move(this,0)">
<img src="img/曹操.jpg" alt="" onclick="move(this,1)">
<img src="img/孙权.webp" alt="" onclick="move(this,2)">
<img src="img/刘备.jpg" alt="" onclick="move(this,3)">
<img src="img/刘协.webp" alt="" onclick="move(this,4)">
<img src="img/貂蝉.webp" alt="" onclick="move(this,5)">
</div>
这样就可以轻松的获取到每一个需要操作的dom对象修改它们的left和top值就行了。
第二步就是移动dom对象,首先创建变量记录元素的当前位置
//定义坐标对象,记录当前操作的元素位置
let pos = {x:0,y:0}
这样写会有一个bug,那就是每一个dom都操作通过一个x和y,当移动了一个元素之后x的值和y的值将会继续作用到下个移动的元素上面。所以我们应该为每一个元素创建一个x和y记录它们的位置
//定义数组存放6个对象,独立记录每个对象的运动坐标
let arr = [{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0}];
在调用事件函数的时候传入它们对应运动坐标对象的下标即可
<img src="img/关羽.webp" alt="" onclick="move(this,0)">
这样一来就很好实现了,接下来的只需要监听键盘事件来修改x和y的值即可
function move(el,index) {
console.log(el);
pos = arr[index];
document.onkeydown = function (event) {
switch (event.keyCode) {
case 37:
pos.x -= 5
el.style.left = pos.x + 'px';
break;
case 38:
pos.y -= 5;
el.style.top = pos.y + 'px';
break;
case 39:
pos.x += 5;
el.style.left = pos.x + 'px'
break;
case 40:
pos.y += 5;
el.style.top = pos.y + 'px';
break;
default:
break;
}
}
}
未来之星投票
效果图
实现
-
首先利用flex布局均匀的分布每一张图片。使用img:hover伪类选择器做出鼠标悬停的动态效果
-
js中我们将所有未来之星的姓名信息和票数信息封装在一个对象中并且用数组存放。
-
利用for循环将信息添加到页面中(使用到模板字符串)
let beauty = [ {name:'a.webp',num:0},{name:'b.webp',num:0},{name:'c.jpeg',num:0}, {name:'d.webp',num:0},{name:'e.webp',num:0},{name:'f.webp',num:0}, {name:'g.webp',num:0},{name:'h.webp',num:0},{name:'i.webp',num:0}, {name:'j.webp',num:0},{name:'k.webp',num:0},{name:'l.webp',num:0}, ] let main = document.getElementById("main"); //根据数组中的数据自动生成图片到页面 function flushImg(){ let s = ''; beauty.forEach((e,i) => { //利用模板字符串取值 s+= ` <div> <img src="imgs/${e.name}" alt=""><br> <span>${e.name.slice(0,e.name.indexOf('.'))}--${e.num}</span><br> <button οnclick="vote(${i})">投票</button> </div> `; }); main.innerHTML = s; } flushImg();
-
为每一个button元素绑定click事件来投票,并且传入投票对象在数组中对应的下标。每投一张票都需重新填充页面
function vote(i){ //添加票数 beauty[i].num ++; //刷新 flushImg(); }
-
当投完票之后还需要将票数前三名的未来之星渲染到顶部的三个元素中。需要注意的是我们不能操作元素组,因为元素组发生改变的话,主体部分的内容也会发生改变。
function vote(i){ //添加票数 beauty[i].num ++; //刷新 flushImg(); //更新前三甲 updateTop3(); } let tops = document.getElementById("top"); function updateTop3() { //es6解构赋值 let x,y = beauty_copy = [...beauty]; beauty_copy.sort((e1,e2) =>{ return e2.num - e1.num; }) //去数组的前三个对象 let beauty2 = beauty_copy.slice(0,3); tops.innerHTML = `<div> <img src="imgs/${beauty2[1].name}" alt=""><br> <span>榜眼</span><br> ${beauty2[1].name.slice(0,beauty2[1].name.indexOf('.'))} -- ${beauty2[1].num} </div> <div> <img src="imgs/${beauty2[0].name}" alt=""><br> <span>状元</span><br> ${beauty2[0].name.slice(0,beauty2[0].name.indexOf('.'))} -- ${beauty2[0].num} </div> <div> <img src="imgs/${beauty2[2].name}" alt=""><br> <span>探花</span><br> ${beauty2[2].name.slice(0,beauty2[2].name.indexOf('.'))} -- ${beauty2[2].num} </div>`; }
数组的sort方法每次获取array[i]和array[i+1]的值
- 如果 函数return 的结果小于 0 ,那么array[i]会被排列到array[i+1] 之前;
- 如果 函数 return 的结果等于 0 , array[i] 和 array[i+1] 的相对位置不变。
- 如果 函数 return 的结果大于 0 , array[i+1] 会被排列到array[i] 之前。
总结来说优势 array[i+1] - array[i] 会得到一个降序的数组,array[i] - array[i+1]会得到一个升序的数组。
- 如果 函数return 的结果小于 0 ,那么array[i]会被排列到array[i+1] 之前;
- 如果 函数 return 的结果等于 0 , array[i] 和 array[i+1] 的相对位置不变。
- 如果 函数 return 的结果大于 0 , array[i+1] 会被排列到array[i] 之前。
总结来说优势 array[i+1] - array[i] 会得到一个降序的数组,array[i] - array[i+1]会得到一个升序的数组。
-