游戏玩法
游戏主要考验玩家的空间感和记忆能力,玩家需要通过开局的3秒内尽可能多的记忆两个空间内相同元素的位置,3秒后将会翻牌把图案盖住,玩家需要点击卡牌来翻转牌面,两张相同图案的卡牌即可保留,游戏计时将在卡牌翻转之后开始,完全翻转所有卡牌则计时结束,我打赌没人能在60秒内通关这个游戏
游戏彩蛋
假如有好事者将鼠标移动到我们的标题看谁翻得快
的时候,会发现这是一个复古魂斗罗标题样式,具体实现依赖的是background-image里的repeating-linear-gradient与-webkit-background-clip
,我们利用伪元素::before
和::after
,来实现复古的重叠文字效果。
- repeating-linear-gradient 重复径向渐变
- -webkit-background-clip 以盒子内的文字作为裁剪区域向外裁剪,文字之外的区域都将被裁剪掉
看谁翻得快
.title {width: 380px;position: absolute;left: 0;right: 0;top: 0;margin: auto;display: block;color: #1e80ff;font-size: 64px;letter-spacing: 8px;cursor: pointer;
}.title::before {content: "看谁翻得快";position: absolute;color: transparent;background-image: repeating-linear-gradient(45deg,transparent 0,transparent 2px,white 2px,white 4px);-webkit-background-clip: text;top: 0px;left: 0;z-index: -1;transition: 1s;}.title::after {content: "看谁翻得快";position: absolute;color: transparent;background-image: repeating-linear-gradient(135deg,transparent 0,transparent 2px,white 2px,white 4px);-webkit-background-clip: text;top: 0px;left: 0px;transition: 1s;}.title:hover:before {top: 10px;left: 10px;}.title:hover:after {top: -10px;left: -10px;}
核心实现
- 容器 容器是由720x450的盒子拆成的两个350x450的小盒子构成,大盒子通过flex布局水平垂直居中,小盒子也是通过flex布局实现水平拆分。
#box{width: 720px;height: 450px;display: flex;justify-content: space-between;align-items: center;}.left,.right{width: 350px;height: 450px;background: #fff;border-radius: 8px;overflow: hidden;display: flex;justify-content: space-around;align-items: center;flex-wrap: wrap;transform-style: preserve-3d;}
- 元素,元素样式是100x100的小卡片,背景图随机生成,背景图来源于掘金商城,随机生成算法还是通过标记法去重,图片一共12张,所以我们需要生成不重复的随机顺序的12个数字,从0开始。将生成的数字以 自定义属性
key
记录在对应的dom上, 牌面的翻转覆盖效果通过transition
配合transform
来实现,不管是添加还是移除,都会应用过渡效果,所以看起来像是在翻转一样
// 样式
.left div, .right div{width: 100px;height: 100px;border-radius: 8px;cursor: pointer;box-shadow: inset 0 0 15px 3px rgb(12, 133, 215);background-position: center;background-size: contain;background-repeat: no-repeat;transform: rotateY(180deg);transition: all ease .5s;}#box .shine{transform: rotateZ(360deg) rotateY(360deg);}// 随机算法// 参数map是标记对象,from是为了将dom正确append, imgSrc比较多,不在这里罗列了function randomKey (map, from) {let ket = nulldo {key = Math.floor(Math.random()*len)} while (map[key])let div = $('')div.addClass('item')div.addClass('shine')div.attr('key', key)div.css('background-image', `url(${imgSrc[key]})`)map[key] = div$(`.${from}`).append(div)}for(let i =0;i
- 倒计时3s翻转卡牌 ,这里采用了定时器的方法,上面讲过,添加移除
transfrom
都会响应过渡,那么我们只需要在倒计时结束时统一为卡牌更换背景图即可
let t =setTimeout(function () {for(let i in left_Map) {left_Map[i].removeClass('shine')left_Map[i].css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)}for(let i in right_Map) {right_Map[i].removeClass('shine')right_Map[i].css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)}},3000)
- 添加点击事件,处理翻牌相同和翻牌不同的情况, 这里,我们需要一个缓存数组cache,将点击获得的属性key缓存在cache里,然后进行判断即可,这里我们只需要判断,cache有长度和cache没长度的情况,有长度则需要进行比较,没长度直接将key缓存在cache内即可,相关注释都在代码里了
$('.item').click(function () {
// 这里判断的是 假如已经翻转了牌面,就不再响应点击事件if ($(this).hasClass('shine')) {return false}// 获取key,将牌面翻转并设置key对应的背景图let key = Number($(this).attr('key'))$(this).addClass('shine')$(this).css('background-image', `url(${imgSrc[key]})`)// 判断缓存数组长度if (cache.length === 1) {// 判断当前点击Key与缓存的key是否一致if (cache.find(v => v===key)
结语 & 码上掘金地址
笔者多次尝试,哪怕作弊,时间也在110秒左右,真的很考验记忆力
最后
整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。
有需要的小伙伴,可以点击下方卡片领取,无偿分享