小程序獲取頭像圖片以及昵稱中含有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服務器域名
image.png
這樣就可以下載圖片了
制作圓角信息,并且畫到畫布上面
//首頁獲取圖片信息
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)