⭐小程序canvas生成海報
由於 wx.createCanvasContext() 接口不再維護,因此,我們將記錄新舊接口生成海報的兩種方法。
先上效果圖

目前展現的是圖片等元素組成、以輪播圖形式展示的頁面。為提高性能,采用按下保存海報按鈕,再執行canvas生成海報,保存到本地相冊這樣一個操作。話不多說,來干!
⭐舊接口 wx.createCanvasContext
① 寫一個canvas對象
<canvas class="hide" canvas-id="share" style="width:480px;height:854px;"></canvas>
注意,這里只需給他加上 canvas-id 等下即可獲取到該對象。 hide類主要是將 此畫布隱掉,讓他不要出現在我們的頁面中。由於canvas的特殊性,我們采用最最最簡單的辦法,將它定位到屏幕之外即可。
.hide{
position:fixed;
left:9000px;
}
② 圖片臨時地址准備
接下來,我們就可以着手准備在畫布上畫上我們的海報。
首先、海報上有圖片。注意,網絡圖片地址是不能直接被畫上去的,要先轉為臨時地址。
當然若是本地圖片,直接采用該地址即可,無需進行臨時地址獲取。
ImgUrlToTmp方法
利用微信的 getImageInfo 接口,實現臨時地址獲取。
// 獲取海報圖片和二維碼臨時地址
ImgUrlToTmp(){
var that = this;
wx.showLoading({
title: '拼命生成中...',
});
wx.getImageInfo({
src: that.data.img_url,
success(res) {
console.log("模板圖片臨時路徑:" + res.path);
that.setData({
hbpath: res.path
},()=>{
console.log(that.data.code_url)
wx.getImageInfo({
src: that.data.code_url,
success(res) {
console.log("二維碼臨時路徑:" + res.path);
that.setData({
codepath: res.path
},()=>{
that.createNewImg()
})
},
fail(e){
console.log(e)
}
})
})
},
fail(e){
console.log(e)
}
})
},
③ canvas畫布
等我們將圖片地址准備好后,接下來,就正式進入我們的繪畫階段,上述可見調用了 createNewImg 方法
sharePage
//將canvas轉換為圖片保存到本地,然后將圖片路徑傳給image圖片的src
createNewImg: function () {
var that = this;
// 畫畫布
var context = wx.createCanvasContext("share");
var width = that.data.widths
var height = that.data.heights
context.clearRect(0, 0, width , height);
context.setFillStyle("#fff")
context.fillRect(0, 0, width, height)
context.save();
// 畫海報
var path = that.data.hbpath;
// console.log(path)
context.drawImage(path, 0, 0, width, height * 0.8);
// 畫二維碼
var codepath = that.data.codepath;
context.drawImage(codepath, 15, height * 0.83 , 100 , 100);
// 畫話
var t1 = "長按掃碼";
var title = "J1ay ' blogs";
var tishi = "每一個想要學習的念頭,那有可能是未來的你在向你求救。";
context.setFillStyle('#333');
context.setFontSize(13)
context.fillText(t1, 130, height * 0.872);
context.font = 'normal bold 13px sans-serif';
context.fillText(title, 130, height * 0.9);
context.setFillStyle('#999');
context.font = 'normal 10px sans-serif';
context.fillText(tishi, 130, height * 0.93);
context.draw()
setTimeout(() => {
that.toSave(); // 需要延遲一下,等待畫布繪畫完畢,否則將是空白
}, 500);
},
canvasToTempFilePath轉換
// 打包海報
toSave() {
let that = this
wx.canvasToTempFilePath({
x : 0,
y: 0,
canvasId: 'share',
width: that.data.widths,
height: that.data.heights ,
destWidth: that.data.widths * wx.getSystemInfoSync().pixelRatio,
destHeight: that.data.heights * wx.getSystemInfoSync().pixelRatio,
success: function (res) {
let canvasToTempFilePath = res.tempFilePath // 返回的圖片地址保存到一個全局變量里
that.saveShareImg(canvasToTempFilePath)
},
fail: function (error) {
console.log(error)
}
})
},
④ 保存到本地相冊
// 保存到系統相冊
saveShareImg: function (canvasToTempFilePath) {
wx.getSetting({
success(res) {
wx.hideLoading({
success: (res) => {},
fail: (res)=>{
console.log(res)
}
})
// 無權限
if (!res.authSetting['scope.writePhotosAlbum']) {
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail() {
wx.showToast({
title: '保存失敗',
icon: 'none'
})
}
})
},
fail (){
wx.showModal({
title: '提示',
content: '請設置允許訪問相冊,否則將無法使用該功能',
showCancel: false,
success (res) {
if (res.confirm) {
console.log('用戶點擊確定')
wx.openSetting({
success (res) {
// console.log(res.authSetting)
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail() {
wx.showToast({
title: '保存失敗',
icon: 'error'
})
}
})
},
fail(err){
console.log(err)
}
})
} else if (res.cancel) {
console.log('用戶點擊取消')
}
}
})
}
})
}
else{
wx.saveImageToPhotosAlbum({
filePath: canvasToTempFilePath,
success() {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail() {
wx.showToast({
title: '保存失敗',
icon: 'error'
})
}
})
}
},
fail() {}
});
},
⭐新接口 createSelectorQuery
① 掛載一個canvas 對象
其實是類似的。 首先也是 掛載一個canvas 對象,注意,這里需要 指定 type 屬性以及id
<canvas type="2d" class="hide" id="share" style="width:480px;height:854px;"></canvas>
下一步也是同舊接口,就不重復闡述了。
畫布方法改變
重點來了!!如何利用新的接口實現畫布繪畫。尤其是畫圖片這部分,踩坑太多。最終頂着血的教訓成功了。。
代碼如下:
//將canvas轉換為圖片保存到本地,然后將圖片路徑傳給image圖片的src
createNewImg: function () {
var that = this;
// 畫畫布
wx.createSelectorQuery()
.select('#share')
.fields({
node: true,
size: true, })
.exec(function (res) {
console.log(res)
const canvas = res[0].node
const context = canvas.getContext('2d')
const width = res[0].width
const height = res[0].height
context.restore();
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = width * dpr
canvas.height = height * dpr
context.scale(dpr, dpr)
context.clearRect(0, 0, width , height);
context.fillStyle = 'white'
context.fillRect(0, 0, width, height)
context.save();
// 畫海報 為什么要這樣呢?為了防止該圖片還未加載出來就畫了圖導致畫的一片空白!
// 網上也有很有人采用 onload方法,但是在調試多次失敗后,放棄,如下方案可行
var path = that.data.hbpath;
const hbPromise = new Promise((resolve, reject) => {
const hb = canvas.createImage()
hb.onload = () => {
resolve(hb)
}
hb.onerror = () => {
reject(new Error(`fail to fetch image form: ${path}`))
}
hb.src = path
})
hbPromise.then(img => {
context.drawImage(img, 0, 0, width, height * 0.8)
})
// 畫二維碼
var codepath = that.data.codepath;
const codePromise = new Promise((resolve, reject) => {
const code = canvas.createImage()
code.onload = () => {
resolve(code)
}
code.onerror = () => {
reject(new Error(`fail to fetch image form: ${codepath}`))
}
code.src = codepath
})
codePromise.then(img => {
context.drawImage(img, 15, height * 0.83 , 100 , 100)
})
// 畫話
var t1 = "長按掃碼";
var title = "J1ay ' blogs";
var tishi = "每一個想要學習的念頭,那有可能是未來的你在向你求救。";
context.fillStyle = '#333';
context.fillText(t1, 130, height * 0.872);
context.font = 'normal bold 13px sans-serif';
context.fillText(title, 130, height * 0.9);
context.fillStyle = '#999';
context.font = 'normal 10px sans-serif';
context.fillText(tishi, 130, height * 0.93);
context.stroke();
context.save();
setTimeout(() => {
that.toSave(canvas);
}, 1000);
});
},
畫布保存轉為地址
基本一致,就是多加了個 canvas 屬性, 也就是將 canvas 對象傳進去即可
下方利用像素點轉化,可以提升海報的高清度
// 打包海報
toSave(canvas) {
console.log(canvas)
let that = this
wx.canvasToTempFilePath({
x : 0,
y: 0,
canvasId: 'share',
canvas: canvas,
width: that.data.widths,
height: that.data.heights ,
destWidth: that.data.widths * wx.getSystemInfoSync().pixelRatio,
destHeight: that.data.heights * wx.getSystemInfoSync().pixelRatio,
success: function (res) {
let canvasToTempFilePath = res.tempFilePath // 返回的圖片地址保存到一個全局變量里
// console.log(res)
that.saveShareImg(canvasToTempFilePath)
},
fail: function (error) {
console.log(error)
}
})
},
保存到相冊方案也不多說啦。
來看一下保存海報的效果圖

輪播圖實現
接下來來看一下輪播圖實現, 微信開發者工具中直接有個組件 swiper
這里 利用
currentIndex == index判斷當前選中項,從而改變選中的樣式再加個滑動的動畫即可
<view class="main">
<swiper class="gundong" circular bindchange="changeHB" previous-margin="100rpx" next-margin="100rpx" >
<block wx:for="{{ shareImgs }}" wx:for-item="item" wx:key="index" >
<swiper-item class="gundongItem" >
<view class="Item {{currentIndex == index ? '' : 'smItem'}}">
<!-- 海報分享 -->
<view class="shareImg">
<image style="width:100%;height:100%" src="{{item.img_url}}" />
</view>
<!-- 二維碼 -->
<view class="code">
<view class="img">
<image style="width: 100rpx;height:100rpx;" class="{{currentIndex == index ? '' : 'smCode'}}" src="{{item.code_url}}" />
</view>
<view class="code_txt">
<text>長按掃碼</text>
<text style="font-weight:bold">J1ay ' blogs</text>
<text style="font-size: 14rpx;color: #999999;line-height: 20rpx;">每一個想要學習的念頭,那有可能是未來的你在向你求救。</text>
</view>
</view>
</view>
</swiper-item>
</block>
</swiper>
</view>
具體代碼如下:
圖片素材來源網絡,侵權刪
