小程序获取头像图片以及昵称中含有emoji表情
问题描述
1、小程序不能转发到朋友圈,所以只能通过保存图片的方式识别二维码进入小程序,这样就用到了canvas画图,但是如果想把图像也画到canvas上面就需要把网络图片或者头像图片下载到本地缓存才能在canvas上面进行填充。小程序下载图片或者下载头像图片还是比较简单的,但是对于一些不明就里的还是比较坑的。毕竟小程序有安全域名这一说,真是想吐槽
2、现在微信的昵称中都含有emoji表情,显示的时候超过一定的长度要显示...的问题,但是在画布上如果截取的字符串正好是emoji表情,就会导致错误。而且emoji表情是占用四个字符的,汉字占用两个字符,英文或者特殊字符占用一个字符。也有特殊的。比如emoji表情中 中国国旗的emoji表情是占用八个字符的。所以也要根据情况判断;
微信api
wx.downloadFile(OBJECT)
下载文件资源到本地,客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。
小程序downloadFileAPI
这里有一个最重要的问题就是download的安全域名的设置。下载文件或者图片的url的域名要在安全域名内
比如:头像的网络地址的URL是https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLZQtgUL0YiaN3OL5RjED9zPOicjhQwcuticBWZLeGZaT5qAfqzGaBYf7vnJuKgMIycbbiavB66Tp9/132
这样就是需要把wx.qlogo.cn
添加到download的安全域名下面。
还有一点要注意的就是一定要是HTTPS协议,即使是自己的图片服务器,也一定要是HTTPS才行
设置安全域名
登陆微信公众平台 点击设置→开发设置→服务器域名→download服务器域名
这样就可以下载图片了
制作圆角信息,并且画到画布上面
//首页获取图片信息
bindGetUserInfo: function (e) {
app.globalData.userInfo = e.detail.userInfo;
if (app.globalData.userInfo == null || app.globalData.userInfo == 'undefined' || app.globalData.userInfo == '' ){
app.globalData.userImage = '';
}else {
wx.getImageInfo({
src: app.globalData.userInfo.avatarUrl, //请求的网络图片路径
success: function (res) {
//请求成功后将会生成一个本地路径即res.path,然后将该路径缓存到storageKeyUrl关键字中
app.globalData.userImage = res.path;
},
fail:function(res){
app.globalData.userImage = '';
}
})
}
// this.start()
},
//返回昵称的字符串,超过显示...
//验证是否为emoji表情
function BooleanEmoji(emoji) {
var ranges = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/ig;
return ranges.test(emoji);
// var emojireg = emoji;
// // return emojireg.replace(new RegExp(ranges.join('|'), 'g'), '');
// return emojireg.replace(ranges, '');
}
//过滤emoji表情
function filterEmoji(emoji){
var ranges = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/ig;
var emojireg = emoji;
return emojireg.replace(ranges, '');
}
function GetLength(str) {
var realLength = 0
for (let s of str) {
// 如果是emoji表情str_length 字符长度增加4
if (BooleanEmoji(s)) {
realLength = realLength + 4;
} else {
// 如果是中文字符长度增加2
if (/.*[\u4e00-\u9fa5]+.*/.test(s)) {
//中文字符的长度经编码之后大于4
realLength = realLength + 2;
} else {
// 英文或者特殊字符 字符长度增加2
realLength = realLength + 1;
}
}
}
// 返回字符串的字符串总长度
return realLength;
}
function cutstr(str, len) {
var str_length = 0;
var str_len = 0;
var str_cut = new String();
//计算得到真正的字符串长度,如果使用length会出现不是真正的字符串长度
str_len = Array.from(str).length;
// 使用es6得到每个字符串
for (let s of str) {
// 如果是emoji表情str_length 字符长度增加4
if (BooleanEmoji(s)) {
str_length = str_length + 4;
} else {
// 如果是中文字符长度增加2
if (/.*[\u4e00-\u9fa5]+.*/.test(s)) {
//中文字符的长度经编码之后大于4
str_length = str_length + 2;
} else {
// 英文或者特殊字符 字符长度增加2
str_length = str_length + 1;
}
}
var beforeStr =s;
// 拼接字符串
str_cut = str_cut.concat(s);
// 大于指定的字符长度就会显示...
if (str_length >= len) {
if (BooleanEmoji(s)) {
str_cut = filterEmoji(str_cut).trim();
if(str_cut==''){
str_cut = '我'
}
}else {
str_cut = str_cut.concat("...");
}
return str_cut;
}
}
// 小于指定的字符长度返回字符串
if (str_length < len) {
return str;
}
}
//var nickName = '荷叶';
//if(GetLength(nickName) > 16){
// var nickNameValue = cutstr(nickName,14) + ''
// }else {
// var nickNameValue = nickName + ''
// }
//console.log("表情符号是多少",nickNameValue)
// 获取userInfo
var userInfo = app.globalData.userInfo;
if (userInfo == '' || userInfo == 'undefined' || userInfo == null) {
// var nickName = userInfo.nickName;
var nickNameValue = ''
// var userInfoImage = userInfo.avatarUrl;
// console.log("userInfoImage", userInfoImage)
} else {
// console.log("userInfo",userInfo)
var userInfoImage = app.globalData.userImage;
console.log("userInfoImage", userInfoImage)
var nickName = userInfo.nickName;
//var nickName = '荷叶';
if (GetLength(nickName) > 16) {
//截取昵称第一个
var nickNameValue = cutstr(nickName,14) + ''
} else {
var nickNameValue = nickName + ''
}
}
//画布
var userInfoImage = app.globalData.userImage;
const ctx = wx.createCanvasContext('qr-canvas');
ctx.save();
ctx.beginPath();
// 下面是先定位要开个圆形的位置,50 和 90 分别就是圆的圆心的 x 坐标和 y 坐标,
//25 是半径,后面的两个参数就是起始和结束,这样就能画好一个圆了
ctx.arc(50,90, 25, 0, 2 * Math.PI);
ctx.closePath();
// 下面就裁剪出一个圆形了,且坐标在 (50, 90)
ctx.clip();
// 然后画图片,res.tempFilePath 其实是下载到本地的一个路径,使用小程序画出图片记得一定要用本地的路径,
//可以用 wx.downloadFile 来实现。 因为 drawImage 的第二个和第三个参数是图片的左上角在画布 canvas 的 x 坐标,y 坐标,
//所以图片的坐标比圆形的坐标分别都小圆的半径大小就刚刚好能被切成圆形,后面的两个参数就是图片的宽和高,请设定为圆形的直径长度。
//userInfoImage是下载的图片信息;
ctx.drawImage(userInfoImage, 25, 75, 50, 50);
ctx.restore();
//nickNameValue是昵称信息
// 计算昵称的宽度
//计算第一个设置大小之后的长度
ctx.setFontSize(18)
ctx.setFillStyle('black');
// var nickNameWidthOne = ctx.measureText(nickNameValue).width
// 设置昵称的位置
ctx.fillText(nickNameValue,90,75)
javascript有一个Unicode天坑 | 腾讯
字符的 Unicode 表示法