小程序生成分享海报并转发朋友圈(超全版)

小程序生成分享海报并转发朋友圈(超全版)

前言

在使用小程序canvas生成分享海报过程中,学到了一些可以优化的方案,在这里记录一下,方便以后使用

文章目录

前言屏幕适配字体加粗实现文本的换行canvas'伪'层级绘制网络图片的绘制画布(canvas)隐藏保存至相册用户授权(保存至相册时)

屏幕适配

思路:

获取设备宽高,以iPhone6为参照,进行各机型上的长度转换

px转rpx

const px = rpx / 750 * wx.getSystemInfoSync().windowWidth;

rpx转px

const rpx = px * 750 / wx.getSystemInfoSync().windowWidth;

具体代码

// 屏幕适配函数封装

function createRpx2px() {

const { windowWidth } = wx.getSystemInfoSync()

return function(rpx) {

return windowWidth / 750 * rpx

}

}

const rpx2px = createRpx2px()

// 基本使用

draw () {

const ctx = wx.createCanvasContext('myCanvas', this)

// 绘制title

ctx.setTextAlign('center')

ctx.fillText(

'适配',

rpx2px(200 * 2),

rpx2px(100 * 2)

// 在各机型下,位置基本相同

)

ctx.stroke()

ctx.draw()

}

当然,如果不想在调用rpx2px()时传入的参数再乘2,可以在createRpx2px()中修改

字体加粗实现

思路:

这里我们可以通过将绘制文本进行偏移,几次绘制的文字部分重叠,达到字体加粗的目的

const ctx = wx.createCanvasContext('myCanvas', this)

const bold = rpx2px(4 * 2)

ctx.setTextAlign('center')

ctx.setFontSize(170)

ctx.setFillStyle('#ffffff')

ctx.fillText('25', canvasW / 2, beginY + YThree)

// 文字偏移,使其加粗

ctx.fillText('25', canvasW / 2 + bold, beginY + YThree + bold)

ctx.fillText('25', canvasW / 2 - bold, beginY + YThree - bold)

ctx.fillText('25', canvasW / 2 - bold, beginY + YThree + bold)

ctx.fillText('25', canvasW / 2 + bold, beginY + YThree - bold)

文本的换行

思路:

确定好行宽,字体大小,以及最大行数后,通过循环和字符串的截取,一次绘制一行即可

const ctx = wx.createCanvasContext('myCanvas', this)

var maxLine = 2

var fontSize = 30

var beginX = 40

var beginY = 100

var str = '小程序海报生成,文本换行解决。解解解解解解解解解解解解解解解解解解解决啦'

var td = Math.ceil(textWidth / fontSize)

var tr = Math.ceil(str.length / td)

ctx.setTextAlign('center')

ctx.setFontSize(fontSize)

ctx.setFillStyle('#ffffff')

for (var i=0; i

text = str.substring(i*td, (i+1)*td)

if (i < maxLine) {

if (i == maxLine - 1) {

text = str.substring(i*td, (i+1)*td - 2)

}

ctx.fillText(text, beginX, beginY + i*space)

}

}

ctx.stroke()

ctx.draw()

参数说明

参数说明str待绘制总文本maxLine绘制文本的最大行数fontSize绘制文本的字号beginX绘制文本的左上角的横位置beginY绘制文本的左上角的纵位置td每行显示的字符个数tr待绘制的文本将要绘制的行数text每行将要绘制的文本

canvas’伪’层级绘制

问题解释:

在使用画布时,想设置一个遮罩层,把一些文字显示在遮罩层上而不被遮挡。

ctx.save()

// 其他绘制内容

// 遮罩绘制

const bottomHeight = rpx2px(150 * 2)

ctx.setFillStyle('#000000')

ctx.rect(0, canvasH - bottomHeight, canvasW, bottomHeight)

ctx.setGlobalAlpha(0.2)

ctx.restore()

// 遮罩层上方内容绘制

ctx.setTextAlign('center')

ctx.setFontSize(100)

ctx.setFillStyle('#ffffff')

ctx.fillText('扫码使用', canvasW / 2, canvasH - rpx2px(40 * 2))

ctx.stroke()

ctx.draw()

网络图片的绘制

思路:

先通过wx.downloadFile()将网络图片下载到本地,在回调函数中进行绘制

const ctx = wx.createCanvasContext('myCanvas', this)

wx.downloadFile({

url: 'https://iwtf.github.io/posts/uncategorized/2019-02-10-Image/Cache_5e515784c66542c4.jpg',

success(res) {

if (res.statusCode === 200) {

ctx.drawImage(res.tempFilePath, 0, 0, 150, 150)

ctx.draw(false, () => {

setTimeout(() => {

canvasToTempFilePath({

canvasId: 'firstCanvas',

}, this).then(({ tempFilePath }) => that.setData({ imageFile: tempFilePath }))

}, 100)

})

}

}

})

画布(canvas)隐藏

可以设置css样式,将其移出可视区域,如下:

position: fixed;

left: 999px

保存至相册

小程序现没提供转发API,所以我们需要先保存图片至手机,再发至朋友圈。

在保存到手机前,先加一个封装好的,把当前画布指定区域的内容导出生成指定大小的图片。

// 海报保存临时路径

function canvasToTempFilePath(option, context) {

return new Promise((resolve, reject) => {

wx.canvasToTempFilePath({

...option,

success: resolve,

fail: reject,

}, context)

})

}

// 简单使用

draw () {

// 进行了绘制操作后

ctx.draw(false, () => {

setTimeout(()=>{

canvasToTempFilePath({

canvasId: 'share',

}, this).then(({ tempFilePath }) => console.log(tempFilePath))

}, 100)

})

}

将图片保存到本地

// 保存海报到本地

function saveImageToPhotosAlbum(option) {

return new Promise((resolve, reject) => {

wx.saveImageToPhotosAlbum({

...option,

success: resolve,

fail: reject,

})

})

}

// 调用函数,传入临时路径即可

用户授权(保存至相册时)

先判断用户是否开启用户授权相册,处理不同

情况下的结果。

// 获取用户是否开启用户授权相册

if (!openStatus) {

wx.openSetting({

success: (result) => {

if (result) {

if (result.authSetting["scope.writePhotosAlbum"] === true) {

openStatus = true;

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: '图片保存成功,快去分享到朋友圈吧~',

icon: 'none',

duration: 2000

})

},

fail() {

wx.showToast({

title: '保存失败',

icon: 'none'

})

}

})

}

}

},

fail: () => { },

complete: () => { }

});

} else {

wx.getSetting({

success(res) {

// 如果没有则获取授权

if (!res.authSetting['scope.writePhotosAlbum']) {

wx.authorize({

scope: 'scope.writePhotosAlbum',

success() {

openStatus = true

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: '图片保存成功,快去分享到朋友圈吧~',

icon: 'none',

duration: 2000

})

},

fail() {

wx.showToast({

title: '保存失败',

icon: 'none'

})

}

})

},

fail() {

// 如果用户拒绝过或没有授权,则再次打开授权窗口

openStatus = false

console.log('请设置允许访问相册')

wx.showToast({

title: '请设置允许访问相册',

icon: 'none'

})

}

})

} else {

// 有则直接保存

openStatus = true

wx.saveImageToPhotosAlbum({

filePath: canvasToTempFilePath,

success() {

that.setData({

showShareImg: false

})

wx.showToast({

title: '图片保存成功,快去分享到朋友圈吧~',

icon: 'none',

duration: 2000

})

},

fail() {

wx.showToast({

title: '保存失败',

icon: 'none'

})

}

})

}

},

fail(err) {

console.log(err)

}

})

}

相关推荐