微信小程序开发-踩坑+笔记

@一棵菜菜  June 19, 2018

说明

描述:在此次换装游戏的结果分享页中,由于用户点击『分享到朋友圈』按钮后,将生成一张图片并保存到本地相册中(原因见传送门),而这张图片是需要根据用户所选装扮、得分进行动态绘制的,所以我采用了微信canvas绘图相关的api。现在将此次快速开发中使用canvas踩的坑做个小结,方便自己随时查阅回顾。

提示:我觉得canvas是一个很好玩的绘图 API ,虽然这次学习和开发时间很短,自己也简单入了canvas的门,但希望自己后面有时间可以深入去学习和研究canvas~~~

canvas中的单位问题

在canvas中绘制的单位都是px,但由于不同屏幕的像素比不同,在小程序中样式我们使用的单位是rpx,所以在canvas中就需要把rpx换成对应的px;由于rpx可以根据屏幕宽度进行自适应,规定屏幕宽为750rpx,所以rpx换算成px的公式是:

1rpx = 屏幕宽度px / 750rpx

当前元素rpx / 750rpx = 绘制使用的宽度px / 屏幕宽度px

则:

绘制使用的宽度px =( 屏幕宽度px / 750) * 当前元素rpx 

屏幕宽度可以使用wx.getSystemInfoSync()获取。

所以例如在样式中canvas宽度为650rpx,那么在canvas中绘制使用的宽度就是:(屏幕宽度 * 650)/ 750 ;

封装代码如下

function rpx2px(num) {
    var reg = /^\d+(?=\.{0,1}\d+$|$)/;
    if (!reg.test(num)) {
        throw Error('px2rpx参数必须为数字!');
    }
    var info = wx.getSystemInfoSync();
    var screenWidth = info.screenWidth;
    return parseFloat((screenWidth * num / 750).toFixed(2));
}
查看小程序的官方文档叙述

真机上页面绘制的canvas中的图片元素不显示

问题描述

在结果分享页,点击『分享到朋友圈』按钮后,将绘制一张canvas,绘制出的效果图如下。
但直接用接口返回的图片地址(或网络图片)在canvas中绘制结束后,canvas中的图片元素却不显示(是空白),文字内容能正常显示。
分享图.png

解决办法

法1 使用wx. getImageInfo

wx. getImageInfo()res.path会返回图片的本地路径,即相当于把网络图片下载到本地存入缓存;
然后再调用canvasContext.drawImage绘制图像到画布,最后用canvasContext.draw(将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中),转成图片后,就可以保存了。

法2 使用wx.downloadFile【我们实际采用的】

原因

微信开发工具中可以正常显示canvas中绘制出的图片,是因为模拟器上可以拿到缓存,真机不行。

参考代码和思路

wx.getImageInfo({
  src: ‘htttp://****’,
  success: function (res) {
    console.log(res.path)
    // TODO 绘制分享canvas图draw 
    // TODO 绘制成功后,把canvas转化成图片wx.canvasToTempFilePath 
    // TODO 转成功后,自动保存图片到系统相册wx.saveImageToPhotosAlbum    
  }
})
推荐文章:
https://blog.csdn.net/hushilin001/article/details/79136052

微信小程序button样式修改

<button class="result-btn" open-type="share" type="default" size="mini">
    <text class='btn-text'>邀请ta来PK</text>
</button>

重写wx的<button>按钮的样式

微信小程序button去掉边框

.result-btn::after{  
    border: 0px solid #bfbfbf;  
}  

设置按钮里的文字上下垂直居中

.result-btn{
  height: 68rpx;
  line-height: 68rpx !important;
}  

设置按钮的文字全显示(不换行)

.btn-text {
    white-space: nowrap;
}

使用cover-view解决微信小程序canvas等原生组件层级问题

直接在canvas上使用view、image等是不行的,因为查看微信小程序canvas的API底部Bug&Tip有一句话:

canvas 组件是由客户端创建的原生组件,它的层级是最高的,不能通过 z-index 控制层级。

所以直接在canvas上使用view等是没有效果的!即使使用z-index改变z轴也没用。而且在微信开发者工具中调试时层级是没有问题的,但是在手机上canvas就会处于最高层级。

解决办法

可使用控件cover-view

覆盖在原生组件之上的文本视图,可覆盖的原生组件包括map、video、canvas、camera、live-player、live-pusher,只支持嵌套cover-view、cover-image。
<canvas canvas-id="shareCanvas" style="bottom:-{{screenHeight*2}}px;width:{{screenWidth}}px;height:{{screenHeight}}px;" >
    <cover-view class="forbidden-scroll result-img-box">
        <cover-image src="{{canvasImgUrl}}" style="width:{{dWidth}}px; height:{{dHeight}}px;"></cover-image>
</cover-view>
</canvas>
更多详情见cover-view文档介绍

提示:但在结果分享页,我并没有使用cover-view,因为这个页面包含的标签元素种类太多,比如form、button,而且由于埋点的原因又只能用form、button标签,但cover-view内只支持嵌套cover-view、cover-image,所以无法采用上述方法。我采用的是让canvas标签定位的bottom足够远(bottom:-{{screenHeight*2}}px),使其不在屏幕可视范围内。虽然笨拙,但是也算是解决方法之一了


2018.7.24 任务2后的小结

小程序中遮罩层的滚动穿透问题

问题描述

实现遮罩层效果时,会出现滚动穿透的问题,即在遮罩层上滑动时(position:fixed),遮罩层后面的页面依旧可以滚动。

解决方案

添加 catchtouchmove 事件来阻止冒泡。

<!--视频播放浮层-->
<view wx:if="{{currentVideoUrl}}" catchtouchmove="forbiddenScroll" bindtap="closeVideoPop" class="video-box box box-tb box-center-center pop-mask">
    <view catchtap="stopBubble">
        <video src="{{currentVideoUrl}}" autoplay='{{videoAutoplay}}' controls='{{videoControls}}' objectFit='contain' class="video">
        </video>
    </view>
</view>

备注

在其他移动端开发时ipone手机上此方法可能会滑动卡顿,解决办法:在需要滚动的元素上加上下面的样式代码。

 -webkit-overflow-scrolling : touch;  //可以让页面在Native端滚动时模拟原生的弹性滚动效果
查看更多相关文章

仅点击视频外的区域才关闭遮罩的方法

问题描述:只能点击视频周围的黑层遮罩才能关闭视频层

解决办法:我采用的是点击video标签时阻止向上冒泡(catchtap)执行closeVideoPop方法。

video-pop.jpeg

视频在弹窗中的bug

bug描述

ios下,使用catchtouchmove仍然无法解决滑动bug(即在video上滑动时,仍然触发了页面的滚动)猜测可能是video是微信再客户端生成且层级最高的原因,但android下无此bug(疑问???)。所以单独针对ios进行处理。

解决原理

未打开视频弹窗时,记录下页面滚动的距离videoScrollNum;当打开视频弹窗后,一但在视频标签上监听到页面有滚动就设置页面滚动距离值为videoScrollNum,以达到禁止滚动的效果。

onload:function(){
  wx.getSystemInfo({
    success: function (res) {
        // 判断是否是ios系统
        if (res.system.toLowerCase().indexOf('ios') > -1
        || res.platform.toLowerCase().indexOf('ios') > -1) {
            that.setData({
                isIos:true
            });
        }
    }
  });
},
onPageScroll:function(e) {
    var that = this;
    // ios:打开视频弹窗后,在<video>上滑动时禁止页面滚动
    if (this.data.isIos) {
        if (this.data.openVideoPop) {
            wx.pageScrollTo({
                scrollTop: that.data.videoScrollNum,// 固定页面滚动距离(即达到禁止滚动的效果)
                duration: 300
            });
        } else {
            // 存页面距离
            this.setData({
                videoScrollNum:e.scrollTop
            });
        }
    }

备注

我尝试过在遮罩打开的时候为页面容器添加hiddenScroll这个class,然后遮罩关闭后再移除的方法,虽然的确可以禁止滚动,但当弹出层出现,底层body会回到页面顶部,这个并不是我想要的,所以此方法被放弃了。

.hiddenScroll{
    height:100%;
    overflow:hidden;
}

swiper组件的指示点样式修改

  1. 简单修改:每个小点都有一个class wx-swiper-dot
  2. 禁用swiper的indicator-dots属性,用view组件模拟dots。
查看参考文章

wx.navigateBack携带参数

场景

在页面A有品牌列表选项(只展示前8个),用户可多选。通过『更多』按钮前往全部品牌列表页B,并携带用户已选项,用户在这个页面可增删选多个品牌,点击『确定』按钮后回到页面A。
期望达到的顺序:
前往顺序:index -> A -> B。
回退顺序:index <- A <- B。

所以B到A页面,不能使用wx.navigateTo(将把A页面再次加到页面栈,即index -> A -> B -> A,则返回也将是ABAindex)。所以我使用了wx.navigateBack(传送门):

var brandIds = '111';
var pages = getCurrentPages();// 当前页面
var prevPage = pages[pages.length - 2];// 上一页面
prevPage.setData({// 直接给上一页面赋值
    from:'brandFilter',
    brandFilterIds:brandIds
}, function() {
    wx.navigateBack({ // 返回
        delta: 1
    });
});

再回到上一页的js,在data里定义from、brandFilterIds,然后在onshow里处理:

if (this.data.from === 'brandFilter') {
    this.initData();
    this.setData({
        from:''
    });
}

navigateBack.jpeg

查看更多介绍

小程序之webview在ios下访问不到

问题描述

ios端小程序里用web-view打开的H5页面有的白屏,H5地址是后台反的。

解决

经过排查问题发现,web-view的src中携带的参数中含有符号"|",所以只能让后台给参数值转码了,h5页面提取参数的时候再解码一下即可。(貌似中文也有这个问题,也需要转码)
如地址http://caiyichen.me?sell_params=shoppe_source:shoppe|show_id:7044,需要将sell_params值转码。

  1. 编码 encodeURIComponent()
  2. 解码 decodeURIComponent()
web-view 组件是一个可以用来承载网页的容器。(web-view传送门)

pointer-events

传送门

-webkit-overflow-scrolling

相关文章
iOS safari 如何阻止“橡皮筋效果”【需了解】
微信里面防止下拉"露底"组件 【需了解】

video封面poster

使用的poster属性,开发工具上图片闪一下就没了。在video里用cover-view和cover-image,开发工具里正常显示,但是图片不能自适应。

video层级太高,顶部导航固定上滑会出现,覆盖现象暂无法解决。所以这次没有做tab分类的吸顶功能(也由于顶部内容显示/隐藏条件判断多,无法设置固定滚动距离再吸顶)。


添加新评论