记第一个小程序遇到的那些坑

记第一个小程序遇到的那些坑

七月 14, 2018

项目概况

时间大概是6月25号到7月15号这样,目的是给美宜佳优惠券小程序添加一个抽奖游戏模块和一个配套的控制后台。
这个项目最大的挑战有几个:

  1. 没做过小程序
  2. 美宜佳方不提供源码
  3. 时间周期短
  4. 只能使用原生小程序代码

好处是,可以尝试一下未知的领域,扩充经验

  1. 阅读小程序文档、调研小程序可以使用的第三方库、了解小程序能力等。
  2. 知道小程序canvas库可以用:ECharts、WeZrender、wxDraw,以及如何引入第三方库
  3. 了解小程序组件间传值、项目化小程序开发

最终做出来的效果,还算行吧

遇到的问题

canvas(好像仅限IOS)drawImage无法使用网络图片

微信的canvas API不能使用网络图片,并且微信小程序源码包大小不能超过2M,所以,也不能用本地图片[假笑脸]。塞几张图片到项目里随随便便都能超过2M。
车到山前必有路,船到桥头自然直,微信提供了wx.getImageInfo方法,可以下载网络图片,返回的是一个http协议开头的但是用浏览器又不能访问的本地图片url,然后可以利用这个本地资源url来drawImage。由于资源需要及时更新(可配置)且不清楚本地图片的过期时间,所以不做缓存。

需要注意的是,如此一来的话,需要把要下载的图片域名加到微信的downloadFile安全域名中
用这样的方式间接在canvas里渲染网络图片

在有canvas里的dom可以看见但是无法点击(好像还是仅限IOS)

在微信小程序中,canvasvideomaptextarealive-playerlive-pushercamera组件是由客户端创建的原生组件,层级最高的组件,不能通过z-index来手动修改层级。再因为,微信开发者工具是使用nw.js来模拟的浏览器环境,本质上和IOS、Android都不一样,所以就会导致这样的问题

  1. dom在canvas“之上”时,微信开发者工具可以点到dom,但是移动设备上可见,不可点。
  2. 如果有任何弹窗在canvas里,必须把canvas隐藏了,才能让canvas不覆盖在弹窗dom。

要做到,点击某个dom触发某些事件,只能通过判断dom的位置,然后在canvas里定义热区,通过判断点击点是否在热区中来判断是否触发某个事件了。

微信小程序API boundingClientRect可以获取到某个wxml元素的宽高、尺寸、位置,类似DOM的getBoundingClientRect来获取热区参数,但是做的时候没有加上。

开启vconsole时不会验证域名

当你发现是否开启vconsole时小程序表现不一致,去检查代码里用到的网络请求是否都添加到了微信安全域名中,因为启动vconsole时,小程序不会验证安全域名。

音乐播放器的问题

总结到的一个是,微信有两种播放器,一个是系统级别的音乐播放器(getBackgroundAudioManager),另一个类似H5的Audio(createAudioContext)。但是有很多坑。

getBackgroundAudioManager:

  1. 系统级别的音乐播放器没有loop参数,想要实现无限循环,只能在实例onEnd的时候,从新给实例的src复制。即使src路径和上次一模一样也没问题。
  2. 一般H5里的背景音乐、音效不应该用这个,这个应该在一些音乐播放器功能是才应该用这个。
  3. 整个H5中(或者在整个操作系统中)只能使用一个。无法new更多实例

createAudioContext:

  1. 这个和H5的Audio很像,功能基本一样,只是用法不同
  2. 坑是createAudioContext实例的paused参数不正确,一直都不正确。
  3. 解决的办法是,自定义一个myPaused参数,在play时,手动设置为false,暂停时手动设置为true,然后判断myPaused,但是要控制好。

IOS和Android canvas性能差异

这是这个项目中遇到的最神奇的事情,本来以为游戏部分动效比较多,游戏部分统一使用canvas来实现,但是神奇的是,Android能40~50帧的动画,IOS上竟然只有十多帧。最低竟然低过10帧。整个canvas也就drawImage7、8张图片,而且图也没很大,如果性能真这么差的话,要canvas何用,几乎都废了。

经过近一天的尝试之后,把部分不复杂的动画换成CSS3来实现,IOS瞬间满血复活。60帧一帧都没掉,但是Android帧率大概降低了10帧(我的老三星没降太多,小米千元机降低很多),动得比较快的地方卡顿就比较明显了。

真心**。

  • 如果真要解决,最快的办法是进行UA判断,编写两套代码。(时间不允许,且2M的代码限制。。。。。。)

  • 初步认定为是WeZrender的性能问题,github issue也有人提出卡顿的问题,给的demo中,图片动画,换上稍大的图片也会掉帧。

遗留的问题

游戏性能差

因为时间和IOS、Android之间性能差异的问题,Android阵营游戏帧率普遍低,且低到有点难以忍受的地步。

canvas游戏按理来说要在16ms时间内让js处理那么多像素、还要处理其他逻辑,确实很吃力,要达到满帧率很难,但是网上很多按理都能实现。所以说,满帧率复杂canvas游戏还是可以实现的,今后的一个重要的目标之一就是,高性能canvas游戏。嗯,加油

后台管理系统部分没有表单验证

呃。。。element UI同一路由,两个表单,定义两个路由规则,有一个实现不了?没时间搞,且不是硬需求。以后再说。。。。

在使用jQuery.uploadify时,发现post不一定会先发一次OPTION请求

这个应该涉及到简单请求和非简单请求的知识点。先扔个链接,有空再学习学习:跨域资源共享 CORS 详解

游戏配置部分应该使用js的防篡改对象,防止意外修改配置表

Object有几个方法可以控制对象的访问、修改权限分别是:preventExtensions isExtensible seal isSealed freeze isFrozen

  • preventExtensions(不可扩展对象)
    Object.preventExtensions(obj):obj不能添加、可以修改、可以删除

  • isExtensible
    Object.isExtensible(obj) 判断obj是否被限制扩展

  • seal(密封对象)
    Object.seal(obj):obj不可添加、不可删除、可以修改

  • isSealed
    Object.isSealed(obj):判断obj是否被密封

  • freeze(冻结对象)
    Object.freeze(obj):obj不可添加、不可删除、不可修改

  • isFrozen
    Object.isFrozen(obj):obj是否被冻结

所以配置表应该用seal来密封住会比较安全