微信小程序问题集锦
微信小程序问题集锦
#0 Canvas 绘制不生效
原因有可能是 canvas context 的创建方式不对。
通过 wx.createCanvasContext(canvasId, this)
创建 canvas 绘图上下文时,第后个参数是指自定义组件的实例。如果 canvas 位于自定义组件中,这个参数是必传的,否则绘制不生效,界面没显示任何东西。
来看官方文档关于 wx.createCanvasContext 的介绍:
自定义组件实例 this ,表示在这个自定义组件下查找拥有 canvas-id 的 ,如果省略,则不在任何自定义组件内查找
components/paint.json
{
"component": true
}
components/paint.js
Component({
ready: function () {
const ctx = wx.createCanvasContext("myCanvas", this /* 它很重要 */);
ctx.setFontSize(20);
ctx.fillText("Hello", 20, 20);
ctx.fillText("MINA", 100, 100);
ctx.draw();
},
});
#1 Canvas API 与 DOM 中不一样
部分 API 与 DOM 中 canvas 有差异,体现在方法名与参数上。
比如 :
context.createRadialGradient(x0, y0, r0, x1, y1, r1);
,
微信中我能找到对应的,至少从名称上来看,应该是 context.createCircularGradient(x,y,r)
该 API 创建放射状的渐变,渐变由两个圓形边界确定。微信小程序中提供的对应 API 少了一个圆,一如文档中所说,起点从圆心开始。可以理解为缺少的那组参数所确定的圆,其圆心与外围圆心一致,只是半径为 0。
像这种不与我们所熟知的 API 靠拢,进而设计出相近参数不同的 API,不太明白其用意和初衷。只是我们在写码时需要勤看文档,否则会困绕很久。
Component({
ready: function () {
const ctx = wx.createCanvasContext("myCanvas");
// const grd = ctx.createRadialGradient(0, 0, 50, 75, 50, 50);
const grd = ctx.createCircularGradient(75, 50, 50);
grd.addColorStop(0, "red");
grd.addColorStop(1, "white");
// Fill with gradient
ctx.setFillStyle(grd);
ctx.fillRect(10, 10, 150, 80);
ctx.draw();
},
});
#2 真机上图片绘制不生效
与 DOM 中 canvas 的图片绘制不同,小程序提供于向画布绘制图片的 API canvasContext.drawImage
其所需的图片资源为图片的地址。
特别地,如果发现绘制后没展示,多半是因为绘制的图片来自远端,需要使用先下载到本地。这其实跟原生 DOM canvas 绘制网络图片时一样,先 new Image()
等加载完后在 img.onload
回调中再绘制。
wx.downloadFile({
url: "https://example.com/foo.jpg",
success: function (res) {
const ctx = wx.createCanvasContext("myCanvas");
ctx.drawImage(res.tempFilePath, 0, 0, 150, 100);
ctx.draw();
},
});
因为小程序内对外部资源的使用的严格限制,这里使用 wx.downloadFile
API 下载的图片地址需要添加到 downloadFile 合法域名
中。
#3 cover-view
中文本样式的兼容性问题
像 <live-player>
这种运行时是 native 元素的组件,其上要盖东西有严格限制,可操作的空间不多,样式操控起来也捉襟见肘。
虽然官方文档说其只能嵌套 <cover-view>
和 <cover-image>
,实测放入文本也是可以的。真机上发现视频上盖的文本在 iOS 与 安卓端样式上有差异。比如在视频上盖一个 「静音」标签。
mute_badge.wxml
<live-player>
<cover-view class="mute-badge"> 静音模式 </cover-view>
</live-player>
mute_badge.wxss
.mute-badge {
color: #fff;
background: rgba(0, 0, 0, 0.5);
display: inline-block;
vertical-align: top;
+ padding: 0px 4px;
font-size: 24rpx;
line-height: 48rpx;
height: 48rpx;
margin: 20rpx;
}
因为想要文本与背景间有留白,所以左右给了 4px 间距。不给的话默认是紧贴着的。模拟器上没问题,真机测试问题便来了。
iOS 左右依然无留白,安卓正常。审查元素后可发现,iOS 中 padding 部分是没有背景色的!
这决定了如果想要文字左右有边距,得靠东西来填充,靠看不见的字符。当然空格键打的空格是不会起作用的,会被忽略掉,好在 \b
是可以起到填充作用的。所以文案前后加 \b
。
mute_badge.js
data: {
text: `\b\b 静音模式 \b\b`;
}
mute_badge.wxml
<live-player>
<cover-view class="mute-badge"> </cover-view>
</live-player>
这样 iOS 上是生效了。但安卓上出新问题了。因为 \b
在安卓上的表现是虽然会占空间,但不会撑开容器,所以容器还是文案那么宽,因为 \b
的加入,原来的文案便显示不下了,被挤掉了一部分。
如果想尝试文本外再包一层东西来写样式增加留白的话,会得到以下的结果:
既然难两全,那就分开处理喽。
data:{
txt:’\b\b 静音模式 \b\b’
},
ready:function() {
try {
const systemInfo = wx.getSystemInfoSync();
if (systemInfo.platform === 'android') {
this.setData({
txt: '静音模式',
});
}
} catch (error) {
//
}
}