初心不变
上一期我们整理了一些框架搭建中遇到的问题与较优书写方案,本期记录了最近开发中经常遇到的一些稀碎(前两点),以及小程序canvas绘制中会遇到的问题与必备技能海报绘制的简单解决方案。
本文所有分析文档基于uni-app,适合初识小程序的新手小白,以及有使用canvas实现绘画需求的朋友们。
稀碎小问题
1.订阅消息勿踩坑
进入页面调用uni.requestSubscribeMessage()方法实现订阅时会出现以下报错:
- 问题出现原因(官网回答):用户发生点击行为或者发起支付回调后,才可以调起订阅消息界面
- 也就是说一定是在用户确认需要订阅时才能调起该函数
- 解决方案:
①简易版:增加提示窗口,引导用户点击按钮触发订阅弹窗,演示如下:
js
subscribeMessage() {
uni.showModal({
title: "提示",
content: "请订阅消息",
showCancel: false,
confirmText:"好的",
success(res) {
if (res.confirm) {
wx.requestSubscribeMessage({
//api.ordertmplIds:订阅消息的tmplIds数组
tmplIds: api.ordertmplIds,
success(res) {},
fail(res) {
console.log(res, "fail");
},
});
} else {
}
},
});
},
②如果在tabbar页面时就想激起订阅消息可以自定义底部tabbar,具体交互可参考顺丰快递的小程序,这样点击tabbar就相当于用户自觉触发点击行为,就可以调起订阅弹窗啦!
2.设置背景图不生效
上一期我们说到大一些的图片都存到远端,防止图片占用过多主包空间,
这里依然出现了本地图片设置背景图不成功的问题,会一直提示找不到图片(偶尔一直复现,偶尔不会出现),
目前原因尚不明确,不过最好设置background-image时都用远端地址路径喔,不然很容易在这个问题上一直找图片路径的错误而浪费时间。
canvas相关
3.canvas绘制画板层级极高
最近在做两个有画图功能的小程序,其中一个要在画板上根据条件放置一些按钮,但是由于canvas覆盖层级过高,事件被canvas优先触发了无法传到按钮上,因此遇到此类需求可以考虑使用canvas-2d实现
4.使用canvas-2d绘制
绘制一个canvas-2d画板代码如下,供大家参考:
js
const query = uni.createSelectorQuery().in(this);
//获取目标元素
const node = query.select("#" + this.cid);
node.node((res) => {
canvasData.node = res.node;
const context = res.node.getContext("2d");
canvasData.context = context;
//获取设备信息
let {
windowWidth,
windowHeight,
pixelRatio: dpr,
} = wx.getSystemInfoSync();
//根据设备信息设置画板宽度和高度
res.node.width = windowWidth * dpr;
res.node.height = windowHeight * dpr;
//画板横纵坐标根据像素比进行缩放
context.scale(dpr, dpr);
//颜色填充
context.fillStyle = this.canvasBg;
//设置线条高度
context.lineWidth = this.lineWidth;
//设置边框颜色
context.strokeStyle = this.lineColor;
//设置线条端点样式
context.lineCap = "round";
}).exec();
因为这个需求中要使画板能够缩放并且画笔颜色、宽度等也要跟随变化,所以设置了许多动态属性。
对于小程序,不管使用canvas或是canvas-2d,都或多或少都会存在一些问题,所以使用哪一种可以视情况而定,最好是两种都尽量了解,这样做替换或修改时也相对方便。
5.生成海报小工具
最后,一个完善的小程序必然会涉及到生成一些具有特定场景的图片供用户保存或者分享,
给大家分享一个特别好用的小组件,我用这个组件生成过一些结构比较复杂的海报,作者很好的封装了canvas并且还在不断的迭代更新,
下面是利用这个组件生成的简单海报图片(相当于上面是一个特定的海报样式,下面左边的小猫可以是一个二维码)
对应的template代码部分如下(可以直接粘到自己的项目里面调整对应参数):
js
<!-- 外层容器,custom-style用于做隐藏容器处理 -->
<l-painter
ref="painter"
css="width: 750rpx;background:white;border-radius: 20rpx;padding:40rpx;"
custom-style="position: fixed; left: 200%"
>
<!-- 在这个标签里写内容 -->
<l-painter-view>
<!-- 插入一张图片并设置样式 -->
<l-painter-image
src="https://img2.baidu.com/it/u=2408544351,2772066353&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667"
css="width: 670rpx;margin-bottom:20rpx"
/>
</l-painter-view>
<l-painter-view css="display:flex">
<l-painter-image
src="https://img2.baidu.com/it/u=2408544351,2772066353&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=667"
css="width: 144rpx;height:144rpx;border-radius:72rpx;margin-right:40rpx"
/>
<!-- 插入一段文字并设置样式 -->
<l-painter-text
css="color: #999; font-size: 28rpx;width:450rpx;margin-top:20rpx;text-align:center"
text="我画的画也太好看了吧,快来扫描二维码一起来画吧~"
/>
</l-painter-view>
</l-painter>
下面是保存图片时需要调用的方法(套路,直接cv就能用):
js
toShare() {
this.$store.state.audioContext.play();
// 保存成图片
// 渲染
this.$refs.painter.canvasToTempFilePathSync({
fileType: "jpg",
// 如果返回的是base64是无法使用 saveImageToPhotosAlbum,需要设置 pathType为url
pathType: "url",
quality: 1,
success: (res) => {
console.log(res.tempFilePath);
// 非H5 保存到相册
// H5 提示用户长按图另存
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success: function () {
wx.showToast({
title: "保存成功",
icon: "success",
duration: 1500,
});
},
});
},
});
},
给大家附上组件的文档,有感兴趣的朋友们可以直接去查看喔:ext.dcloud.net.cn/plugin?id=2...
最后感谢大家的喜欢,如果大家在实操中发现一些好的点子请给我留言,我都会一一观看并回复,万分感谢!