红包雨游戏(vue制作)

2021-04-03  本文已影响0人  前端劝退师_ty

本篇文章是介绍具体的项目设计思路的,偏实战的讲解不是纯讲技术,如果你也恰巧有这方面的业务可以作为参考

前段时间公司计划做营销活动h5,--天降红包,我负责这个项目的前端开发,本来没打算写出来感觉没什么可说的,但是在制作的过程中还是遇到了许多有意思的东西值得整理一下。

先介绍下天降红包的基本页面

共五步 1、loading加载, 2、开始准备页面, 3、倒计时页面, 4、游戏页面, 5、奖励页面。除了这些主要的流程,其余的校验弹窗,规则及奖品等周边页面就不说了,那些不是重点 流程页面.jpg

总体流程控制

这五步分为五个组件来写,在上层组件中依次引用然后用一个流程控制字段(step)来把控当前用户所在页面,用v-if渲染出来即可,每走一步step+1 初始时 step为1,当用户玩到最后时在返回第二个页面形成一个闭环,只要把step改为2即可。

loading页面

很普通的loading加载并没什么难度,预加载就是提前加载图片和音乐,但是此时你有自己的思路吗?估计你想到了new Image | new Audio,是的我第一个想法也是这样的 然后 onload onerror,这个思路肯定是可以实现的,我在这里是介绍另一种方式, XHR,无论图片还是音乐都是资源嘛,XHR加载资源一样的,不要被json所迷惑,我们日常开发中一想到发起请求就是ajax/json,form表单,其实资源也是可以XHR加载的,浏览器会有自己的缓存方式,请求过一次的再次请求时会取缓存的数据,memory cache

        let xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.addEventListener('load',
                function () {
                    if (xhr.status === 200) {
                        console.log('成功')
                    }else{
                        console.log('失败')
                    }
                    callBack();
                },false
            );
            xhr.addEventListener('error',
                function () {
                    console.log('失败')
                    callBack();
                },false
            );
            xhr.send();

开始页面和倒计时页面就不写

其实开始页面左上角的气泡组件还是值得说一说的,但是与本文关系不大,描述后篇幅过长,大体说下,用的vue作用域插槽,组件内部实现一个个向上顶的动画,并且循环播放,然后反向把每个气泡的id抛向父组件,父组件渲染气泡的样式,为什么这样写呢,仔细看这些气泡名字颜色不一致,如果组件内直接封装上写的太死了,这样后面其他成员其他项目无法复用,写成作用域插槽后样式由上层组件控制我认为这才是正确的解题思路。
另外大多数动效是用vue transition 写的,其实css3也是能实现的,不过用vue的transition 有个好处是有动画回调的 能够精准的控制流程,不会有时间计算不好导致的僵硬

游戏页面

这里是最重要的部分,我经常和别人讲不要着急着写业务,不要把代码搞得一团乱,分好结构分好层次其实就是赢了一半

同事看到了这个页面,和我讲说干嘛自己写,不如去找个差不多的插件,我说算了我想自己写,其实自己写的原因有两点,第一找不到一模一样的插件,哪怕百分之五十的都找不到,第二找到的插件我也不敢用的,大多数找插件我都是借鉴看看实现思路,一旦插件拿过来直接用或是改改,出现线上问题时很难定位解决。

描述下业务场景,游戏是可配置的,时间倒计时,红包种类,红包样式,红包点击效果,红包下降速度,红包数量,红包方向(下降或上升),炸弹配置,话说回来能找到这种插件??不存在的


本场次效果.png

game组件是本场次主组件,spirit(精灵)组件是红包组件
game组件 ui上有头部 底部 和 spirit组件,功能上包括倒计时,红包的点击次数计算,红包的发射节点。
spirit组件 负责红包的渲染,红包降落过程,点击的触发,和点击后拆红包的效果展示
功能分清了
上面说的业务逻辑红包的动态配置不是难点,只不过是把一些参数写成活的远程加载过来罢了,
困难的地方是 多少秒钟 掉落多少红包 这个很难把控,
问题1:10秒钟内掉落5个红包,30秒钟内掉落40个红包,这个逻辑怎么写,甚至极端一些5秒钟仅有一个红包降落。
问题2:红包怎么掉落的自然,5秒钟掉落5个红包,每秒钟掉落一个? 这是不是太有频率了,用户都能点出节奏来,哒、哒、哒、哒、哒
总的来说 就是怎么让红包在指定的时间内随机且均匀的降落。

解决思路,

针对问题一,10秒5个 每两秒1个 很好算,30秒40个每秒钟1.3个,这怎么掉切开吗?肯定不是,解决思路用余数凑成整数,
第1秒1个剩余0.3
第2秒1个剩余0.6
第3秒1个剩余0.9
第4秒1个剩余1.2,1.2超过了1 这样就多掉一个 变成
第4秒2个剩余0.2
....

把这个思路带到 最后一种情况 共五秒钟 掉落一个 每秒钟0.2个 你会发现用户等了五秒 最后一秒红包落下来,因为肯定要累积到最后才余数才能被凑成整数,改变下思路,不用满足1降落满足0.5就降落

第1秒1个剩余0.3
第2秒1个剩余0.6 0.6超过了0.5 这样就多掉一个 变成
第2秒2个剩余-0.4
第3秒1个剩余-0.1
第4秒1个剩余0.2,
.....

经过这个思路 共五秒钟 掉落一个 每秒钟0.2个 红包也是在第三秒的时候降落符合预期

针对问题二,自然降落也就是随机降落,以每一秒钟为单位,这1秒钟要发射一个红包,把一秒钟换成1000毫秒 是在第200毫秒发射 还是 第800毫秒发射这个是随机

解决思路想好了,现在带着这些思路来吧代码敲出来。

image.png image.png image.png image.png image.png image.png image.png image.png image.png image.png

本次项目的坑点 (尤为重要)

ios 是有300毫秒延迟的 这个300毫秒是为了判断用户是否执行双击缩放操作,所以连读点击红包是点不上的。
解决这个问题可以用fastClick 但是还是别用了,为了解决这个小问题引进来一个第三方要考虑下成本,不值得。
另一种解决方案,click 换成 touchstart 并且取消用户滑动操作 touch-action: none; 即可解决300毫秒问题。
另外再提一点,安卓虽然是没这和设定,但是不排除人为干扰,我们公司原生app 安卓部分就做了防重点问题,就是不让用户快速的瞎点,所以如果发现安卓也有快速点击点不上的问题不妨往这个方向思考思考。

音乐问题。
首先音乐不能自动播放,ios就是这样的,他是怕程序未经用户允许自动的播放音乐给用户代码流量上的损耗。

音乐也做不了预加载 无论 preload 或是 new Audio 什么的 不管用的 还有我上面提到的 XHR 没有用的,即使加载成功了ios也不用你之前加载的缓存。

音乐播放也有问题,想要音乐播放出来,必须要用户点击时 “即刻” 播放,记住是 “即刻” 播放,这能代表用户的意愿,表明用户想听这个音乐,我们的场景点击按钮进入游戏播放音乐,点击后会有个ajax后端来判断下 游戏是否正在进行,用户是否还有机会之类的校验,通过才可以进入否则不可以,这个ajax是有时间的,这个时间的快慢代表了是否是 “即刻”,部分低端机反应慢 网速差了点虽然也很快,但是无法播放音乐的。

音乐关闭问题,最尴尬的是你会发现按home键甚至是app返回关闭了当前的webView游戏中的音乐还是存在。普通办法不好解决,我来献上一个解决办法。

let hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in document ? 'webkitHidden' : 'mozHidden' in document ? 'mozHidden' : null;
        document.addEventListener('visibilitychange', function(){
            if (document[hiddenProperty]) {
                document.getElementById("activity_music").pause();
            }
        });

监听当前页面是否被展示,这个也是需要优化下在if的else中再次启动起来,我这个没有做是因为产品说了,既然都关闭了就算了不要再启动了。

上面就是我对于这次活动的总结了,思考代码的设计和制作过程中的填坑。如果能帮助到你真的是太好了。

上一篇下一篇

猜你喜欢

热点阅读