继续前两个版本的更新。本次更新加入了发牌动画以及点击开牌之后的效果。更新了一些以前没有接触到的知识点,其中动画就是一点,若想看动画制作效果请看我上一篇的博文 初学JavaScript动画。此次程序相对复杂,就不做细分,主要讲一下每个函数功能:
- 新的动画功能(考虑到效率本次中弃用)
- 使用setTimeout()
- 预加载函数
- 监听手机是否横屏
- 添加毛玻璃效果
此次经过了两次更新,第一次只考虑做出效果来,第二次改进修复了几个已知BUG,并且改善了第一次的动画流畅度,第一次的效果在手机上有明显卡顿。
先上两个版本的效果 :
第一版:
第二版:
可以明显看出动画效果不一样了。可以点击这里看第二版的实际效果: 第二版演示
一、html
在写完第一版之后其实不怎么想写bolg的,因为那天写的实在头疼,写到最后逻辑乱了,但后面又抽空去重新改良了以下,逻辑也理清了。才准备些blog记录这次成长的╭(╯^╰)╮。
好了和之前一样,首先就是单纯的写一个html文件看看实际效果布局,然后添加css和js。
1 |
|
说明:
body、article::before
选择器中:background: url(../img/lk.jpg)
即可。如需修改毛玻璃的效果程度只需修改 article::before
中 filter:blur(20px);
里面的像素即可,值越小毛玻璃效果越淡。 二、CSS
css这里就不做太多解释,主要就是布局的设置.
1 | /** 清除内外边距 **/ |
这里最后做了一下响应式,针对手机把扑克牌设置更小,否则显示太大了屏幕不能完全显示20张牌。
三、JavaScript
本次代码过多,只简单讲解一下每个函数的功能,怎么修改以达到自己想要的效果。有部分效果不是很好,代码结构设计的也不是很好,比如每一次重新开始都是重新创建20张扑克牌,想过每次开始的时候只需要把之前的20张牌初始化就行了,但是前期做的时候没有考虑好,导致如果想更改必须修改多个函数,暂时就先不修改了,等以后如果有空了则进行代码重构。
先上全部代码,然后仔细看每一个函数,欢迎指出错误与不足,请在本博客下方留言板留言。
1 | // 扑克牌值 |
首先我们读一个程序就得找到入口,在C语言中main()函数则是一个程序的入口,而js中,可以有很多入口,比如来自html的各种事件,以及window.onload
事件。首先我们应该看看js在网页加载之后有没有执行的函数,然后再看html中有没有事件触发。
在此我们先看js:
addLoadEvent(restart);
这一句就是js的开始,顺着这个函数我们可以找到整个程序的流程。首先看看addLoadEvent()
函数。
addLoadEvent()
函数:
1 | //预加载函数 |
我们发现这个函数只是一个预加载函数,就是在网页加载完毕之后执行一个函数,addLoadEvent(restart);
括号里面的则为要执行的函数。我们再去找到 restart()
函数:
restart()
函数:
1 | function restart(){ |
这个函数找到了html中id为mask的元素,也就是我们的弹出框,把它的top样式属性设置为0(在这之前我用css控制了top:-100%)这样窗口就出现了,但是我们发现好像这个函数里面并没有调用其余函数了,那么程序就到这了吗?不,这时候我们的注意力应该转移到这个id为mask的元素,看看html中是否有事件触发了js。<button onclick="start()">开始</button>
很明显,这个按钮通过单击事件触发了一个名为start()
的函数,我们再看看start()函数里写了什么:
start()
函数:
1 | // 游戏开始 |
可以看出,这个程序首先检查有没有扑克牌,如果有则删除所有扑克,并重新调用createPokers(20);
函数创建了20张扑克牌。创建完之后把mask移走,并重新获取所有扑克牌,并把他们移动到指定位置。这时候我们需要看的就有两个函数了,我们先看看 createPokers(20);
创建牌的函数,然后再回头看看setTimeout(_element(list[i],i),i*100)
:
createPokers(n)
函数:
1 | // 创建n张牌 |
这个函数调用了newCard()
函数动态创建了20张扑克牌,并为每一张扑克牌添加了一个onclick
事件触发openCard()
函数,并插入到html中。现在再往下看看
newCard()
函数:
1 | //创建一张扑克 |
newCard()
函数每创建一张扑克牌则计一下数,js的动态创建元素这里不做详细解释。现在返回之前的start()
函数,看看setTimeout(_element(list[i],i),i*100)
,首先我们看看setTimeout() ,我们发现第一个参数传递的为字符串,但是如果用字符串的话就无法为函数传递参数了,所以我们使用了另一个方法,调用_element()
函数然后通过return 返回即可解决,这里参照 给定时器settimeout、setInterval调用传递参数 给出的方法:
_element()
函数:
1 | // 发牌动画,需配合setTimeout调用此函数 |
这里将一个函数返回即可做到延时,发牌动画效果其实就是利用css3的transform:translate3d(x,y,z)
属性配合 transition
来做的,js只需要控制 元素移动,动画的实现则交给css3的 transition 来实现(考虑到流畅度这里使用transform
属性),第一版的时候是直接调用 moveElementTran()
函数的,但是发现有明显的卡顿现象,之后百度查看资料后发现修改 transform
和 transition
属性是最好的方法。请参考 优化js脚本设计,防止浏览器假死
到此时,我们的html中就出现了20张牌,并且按照我们的要求排列好了。接下来则是点击其中一张牌触发onclick事件,调用 openCard()
openCard()
函数:
1 | // 开牌 |
这个函数首先调用了 displayPoker(elem)
翻起牌,然后把其余的扑克全部移走。 接下来则是插入一条历史记录。我们再看看
displayPoker(elem)
函数:
1 | // 显示牌 |
可以看到这里首先利用正则提取出id值,然后根据id来与pokerArr、pokerColor数组进行核对。然后返回poker的值给调用它的地方。这里用到了一个简单的转换:transformationPoker(pokerArr[num-1]);
:
1 | // 把1/2/11/12/13转换为A/J/Q/K |
把一个数值转换为扑克牌值的形式返回。最后 openCard()
函数又一次调用了 setTimeout("restart()",2000);
意思为重新开始,一切又回到了开始。 其中有很多小细节没有详细说明,可自行上网查阅。
总结
其实这个东西并没有什么价值,但对于学习和研究js来说,这个东西的价值带来的“收益”非常大。其中理解了setTimeout()
如何传递参数、修改元素的top
属性要比修改transform
、transition
属性制作的动画效耗的资源更大也更卡顿。
写给想要修改此程序的人:
- 如果你想要修改发牌动画,只需要找到
_element(elem,i,x,y)
函数修改其中实现动画的效果即可。 - 如果你想给开牌效果添加一些动画,则找到
openCard()
函数和displayPoker()
修改即可。 - 如果想要创建更多/更少的牌,则找到
start()
函数中createPokers(20);
修改其中数值,并修改_element()
函数中牌的排列即可。
经历过无数次练习和代码量,你才能成长为经验老道的大牛。在以学习为目标的时候,永远不要当“脚本小子”