? ? 在開發(fā)微信小程序時產品提出了一個需求,就是當用戶在閱讀一片文章想分享時:1.分享時的背景需要和當前頁面文章展示的背景一致(文章展示時背景是隨機的)。2:分享時分享的封面中的文案要和當前文章有關聯,就是分享時封面的標題需要和當前用戶看到的文章標題一致。3:當用戶點擊了分享的卡片,文章展示的背景要和分享時的封面背景一致。
需求解決方案分析:
? ?1 . 分享時使用文章的封面作為分享時的封面? ?? ? ?? ??
? ? ? ? ? 當時第一想到的解決方案就是使用文章的封面作為分享時的圖片,但是這樣會給文章的編寫帶來很大壓力,每一篇文章都設計一個封面 這個顯然是不現實的,當文章大量上架時估計UI該罵街了,而且還面臨一個問題就是 分享時的圖片要求的是5:4的比例 而我們文章封面是16:9 的封面顯示也不適合作為分享的封面使用,所以這張解決方案很快就被pass,就算上這樣實現了后期被推翻的可能性很大。? ? ? ? ??
? ? 2 . 使用canvas?繪制出分享時的封面
? ? ? 正當一籌莫展時看到 微信的api 中的?imageUrl 參數?
onShareAppMessage(Object object)
imageUrl 自定義圖片路徑,可以是本地文件路徑、代碼包文件路徑或者網絡圖片路徑。
那我們可不可以使用canvas?繪制出分享時的封面,再通過api 得到一個臨時的圖片地址imageUrl的參數呢?經過一番嘗試,發(fā)現是可以的。
index.wxml? ?
?定義一個5:4 的 canvas,這里要注意的時由于canvas 的層級很高,而我們繪制頁面時又不想讓用戶看到這個?canvas 這時我們可以給這個canvas 設置定位將位置設置到屏幕以外
<canvas type="2d" id="share" canvas-id="share" style="width: 750rpx;height: 600rpx;"></canvas>
?index.wxss
#share {
position: absolute;
top: -100000rpx;
}
index.js文章來源:http://www.zghlxwxcb.cn/news/detail-696665.html
// 繪制分享的canvas
_setShareImg() {
let query = wx.createSelectorQuery()
query.select('#share')
.fields({
node: true,
size: true
})
.exec(async (res) => {
// Canvas 對象
const canvas = res[0].node
// 渲染上下文
const ctx = canvas.getContext('2d')
// Canvas 畫布的實際繪制寬高
const width = res[0].width
const height = res[0].height
canvas.width = width;
canvas.height = height;
console.log(canvas.width, canvas.height);
// 將背景圖片繪制在canvas上
await drawImageToCanvas.call(canvas, this.data.randomColor.bgUrl, 0, 0, width, height);
// 繪制 健康百科 的圓角背景
ctx.beginPath()
ctx.fillStyle = '#2CBEAC'; // 設置填充顏色
ctx.fillRect(getPositonX(70, width), getPositonY(50, height), getPositonX(150, width), getPositonY(50, height));
// 封裝方法 繪制 健康百科
fillText.call(ctx, "健康百科", "#fff", getPositonX(30, width), getPositonX(68 + 18, width), getPositonY(60, height))
// 封裝方法 繪制 都是您想知道的 杏林藥安出品
fillText.call(ctx, "都是您想知道的 ~ 杏林藥安出品", "#848484", getPositonX(34, width), getPositonX(70, width), getPositonY(122, height))
// 限制標題最大的顯示字數
let title = this.data.title;
if (title.length > 27) {
title = title.substr(0, 23) + '...'
}
// 封裝方法將文本分割成 固定數量 并返回集合數組
const textArr = TextToArray(title, 9);
const TextH = 206,
lineH = 100;
textArr.forEach((item, index) => {
// 這里調用兩遍是為了實現字體加粗的效果 繪制時錯開了 0.5px
fillText.call(ctx, item.join(""), "#333", getPositonX(70, width), getPositonX(70, width), getPositonY(TextH + lineH * index, height))
fillText.call(ctx, item.join(""), "#333", getPositonX(70, width), getPositonX(70 - 0.5, width), getPositonY(TextH + lineH * index - 0.5, height))
})
//
this.setData({
shareUrl: await canvasToTempFilePath(canvas)
})
})
},
onShareAppMessage() {
return {
title: '杏林藥安,專注藥學服務!',
path: `/pages/plunge/index?
// randomIndex 當前隨機顏色的索引
entityid=${this.data.entityid}&randomIndex=${this.data.randomIndex}`,
imageUrl: this.data.shareUrl
}
},
utils.js文章來源地址http://www.zghlxwxcb.cn/news/detail-696665.html
/**
* @deprecated 將一段字符串分割為 固定長度為一組的數組
* @param {String} textString
* @param {Number} len
*/
function TextToArray(textString, len) {
var textArr = textString.split("");
return textArr.reduce((pre, next, index, arr) => {
return pre.concat([arr.splice(0, len)])
}, []);
}
// canvas中繪制帶圓角的矩形
function drawRoundRectPath(cxt, width, height, radius) {
cxt.beginPath(0);
//從右下角順時針繪制,弧度從0到1/2PI
cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2);
//矩形下邊線
cxt.lineTo(radius, height);
//左下角圓弧,弧度從1/2PI到PI
cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI);
//矩形左邊線
cxt.lineTo(0, radius);
//左上角圓弧,弧度從PI到3/2PI
cxt.arc(radius, radius, radius, Math.PI, Math.PI * 3 / 2);
//上邊線
cxt.lineTo(width - radius, 0);
//右上角圓弧
cxt.arc(width - radius, radius, radius, Math.PI * 3 / 2, Math.PI * 2);
//右邊線
cxt.lineTo(width, height - radius);
cxt.closePath();
}
/**
*
* @param {String} text 文字
* @param {String} color 字體顏色
* @param {Number} fontSize 字號
* @param {Number} pX X坐標
* @param {Number} pY Y坐標
* @param {Number} maxWidth 最大寬度
* @param {String} textBaseline 基線
* @param {String} fontStyle 字體
* 運行兩次fillText,x,y的值一次為 (x-0.5,y),一次為 (x,y-0.5),打出來的會變粗
*/
function fillText(text, color, fontSize, pX, pY, maxWidth = 690, textBaseline, fontStyle) {
this.fillStyle = color;
this.textBaseline = textBaseline ? textBaseline : "top" // 文本基線是 em 方框的頂端
this.font = `${fontSize}px ${fontStyle?fontStyle:"PingFangSC-Semibold, PingFang SC"}`; //設置字體
this.fillText(text, pX, pY, maxWidth ? maxWidth : 690); //填充文字
}
/**
* 將canvas 轉成臨時圖片地址
* @param {String} canvas id
*/
function canvasToTempFilePath(canvas) {
return new Promise((resolve, reject) => {
wx.canvasToTempFilePath({
canvas,
fileType: "jpg",
quality: 1,
success(res) {
resolve(res.tempFilePath)
},
fail() {
reject(false)
}
})
})
}
/**
* 將圖片繪制在canvas
* @param {String} url 圖片路徑
* @param {Number} pX x 坐標
* @param {Number} pY y 坐標
* @param {Number} width 寬度
* @param {Number} height 高度
*/
function drawImageToCanvas(url, pX, pY, width, height) {
return new Promise((resolve, reject) => {
const headerImg = this.createImage();
headerImg.src = url; //微信請求返回頭像
headerImg.onload = () => {
this.getContext('2d').drawImage(headerImg, pX, pY, width, height);
resolve()
}
})
}
module.exports = {
TextToArray,
drawRoundRectPath,
fillText,
canvasToTempFilePath,
drawImageToCanvas
}
到了這里,關于微信分享時自定義分享圖片的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!