针对小程序邀请好友功能,可以下载当前的海报图,分享给好友,好友通过扫描二维码跳转至小程序。
但是邀请好友,要根据当前登录者的信息去生成二维码,目的是把邀请到的好友绑定到该用户下,所以会将二维码嵌入背景海报中,合成一张图后,生成一个临时地址,再去下载图片。下边是相关代码:
html部分
<view style="visibility: hidden;">
<canvas canvas-id="shareCanvas" class="canvas" v-if="isShowCav"
:style="{height:canvasHeight+'rpx',width:canvasWidth+'rpx'}">
</canvas>
</view>
<view class="canvasImage">
<text>下图为您的专属小程序码</text>
<image :show-menu-by-longpress="true" style="" :src="pageData.first_post_img" mode=""></image>
<text>长按保存图片或发送给你的好友</text>
</view>
:show-menu-by-longpress="true"是打开长按图片的菜单
JS部分
为了邀请码更快的展示,这里用了将网络图片转换为本地图片的方法:
//获取图片的基本信息,即将网络图片转成本地图片,
getImageInfo(src) {
return new Promise((resolve, reject) => {
uni.getImageInfo({
src,
success: (res) => resolve(res),
fail: (res) => reject(res)
})
});
},
接下来就是canvas画图:
exportPost() {
let that = this
uni.showLoading({
title: '海报生成中'
})
//image是画布的底图
let image = 'https://XXXXXXX.png'
//获取系统的基本信息,为后期的画布和底图适配宽高
uni.getSystemInfo({
success: function(res) {
that.windowObj = res
that.windowObj.ratio = that.windowObj.windowWidth / 750
//因为小程序是用rpx单位,为了是后期合成的图片更好是适应各个手机屏幕的尺寸,这里先计算出一个比率,后面除以这个比率就可以对各个手机尺寸进行适配了
that.canvasWidth =1065
//*that.windowObj.ratio*2 //that.windowObj.windowWidth/that.windowObj.ratio
//设置画布的宽高
that.canvasHeight =1350 //*that.windowObj.ratio*2 //that.windowObj.windowHeight/that.windowObj.ratio
Promise.all([that.getImageInfo(image), that.getImageInfo(that.pageData.codePng), that
.getImageInfo(that.userHeadImg)
]).then(res => {
console.log(1111,res)
let arr = [{
width: res[0].width,
height: res[0].height
},
{
width: res[1].width,
height: res[1].height
},
{
width: res[2].width,
height: res[2].height
}
]
that.ctx.setFillStyle('white'); //填充白色
that.ctx.fillRect(0, 0, 244, 457); //画出矩形白色背景
that.ctx.save()
that.ctx.drawImage(res[0].path, 0, 0, 1065 * that.windowObj.ratio, 1350 *
that.windowObj.ratio);
that.ctx.drawImage(res[1].path, (arr[1].width * that.windowObj.ratio) + 60,
(arr[1].height * that.windowObj.ratio) + 190, res[1].width / 2,res[1].height / 2);
_canvas.drawCircular(that.ctx, res[2].path, 450 * that.windowObj.ratio,
170 * that.windowObj.ratio, 200 * that.windowObj.ratio, 200 * that.windowObj.ratio) //绘制圆形头像
that.ctx.setFontSize(45 * that.windowObj.ratio)
that.ctx.setFillStyle("#000")
that.ctx.textAlign = 'center'; //文字水平居中
that.ctx.fillText(that.strWXNickName, (1090 / 2) * that.windowObj.ratio,
430 * that.windowObj.ratio)
that.ctx.save()
that.ctx.draw(false, function() {
uni.canvasToTempFilePath({
x: 0,
y: 0,
width: 1065,
height: 1350,
destWidth: 1065, //这里乘以2是为了保证合成图片的清晰度
destHeight: 1350,
canvasId: 'shareCanvas',
fileType: 'jpg', //设置导出图片的后缀名
success: function(res) {
that.pageData.first_post_img = res
.tempFilePath
that.isShowCav = false;
uni.hideLoading();
}
})
});
})
}
})
},
这里的_canvas是自己引用的一个关于canvas的常用方法,在这里分享给大家
/**
* 绘制矩形
* 参数:cxt、x坐标、y坐标、宽度、高度、圆角、颜色
*/
function fillRoundRect(cxt, x, y, width, height, radius, /*optional*/ fillColor) {
console.log(cxt, 'fillRoundRect')
//圆的直径必然要小于矩形的宽高
if (2 * radius > width || 2 * radius > height) {
return false;
}
cxt.save();
cxt.translate(x, y);
//绘制圆角矩形的各个边
drawRoundRectPath(cxt, width, height, radius);
cxt.fillStyle = fillColor || '#000'; //若是给定了值就用给定的值否则给予默认值
cxt.fill();
cxt.restore();
}
function drawRoundRect(ctx, r, x, y, w, h, img) {
ctx.save();
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, x, y, w, h);
ctx.restore(); // 返回上一状态
}
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();
}
//加载图片
function getImageInfo(image) {
return new Promise((req, rj) => {
uni.getImageInfo({
src: image,
success: function(res) {
console.log(res, 'getImageInfo图片')
req(res)
},
});
})
}
/**
* 绘制圆形头像
* 参数:cxt、图标路径path、x坐标、y坐标、宽度、高度
*/
function drawCircular(ctx, url, x, y, width, height) {
//画圆形头像
var avatarurl_width = width;
var avatarurl_heigth = height;
var avatarurl_x = x;
var avatarurl_y = y;
ctx.save();
ctx.beginPath();
ctx.arc(avatarurl_width / 2 + avatarurl_x, avatarurl_heigth / 2 + avatarurl_y, avatarurl_width / 2, 0, Math.PI * 2,
false);
ctx.clip();
ctx.drawImage(url, avatarurl_x, avatarurl_y, avatarurl_width, avatarurl_heigth);
ctx.restore();
}
/*
* 绘制图片cover
* t:cxt;
* e:图片属性(通过getImageInfo获取)
* i:绘制图片宽度
* a:绘制图片高度
* s:x坐标
* o:y坐标
*/
function drawImgCover(t, e, i, a, s, o) {
console.log(e, 'drawImgCover')
if (e.width / e.height >= i / a) {
var r = e.height,
n = Math.ceil(i / a * r);
t.drawImage(e.path, (e.width - n) / 2, 0, n, e.height, s, o, i, a)
} else {
var c = e.width,
l = Math.ceil(a / i * c);
t.drawImage(e.path, 0, (e.height - l) / 2, e.width, l, s, o, i, a)
}
}
/*
* 文本自定义换行
* family = " 'PingFang SC',tahoma,arial,'helvetica neue','hiragino sans gb','microsoft yahei',sans-serif";
* var options = {
font:"22px" + family, 字体大小
ctx:ctx, uni.createCanvasContext('firstCanvas')
word:"文字", 文字
maxWidth:750, 最大宽度
maxLine:2, 最大行数
x:100, x坐标
y:100, y坐标
l_h:40 行高
}
* callback 自定义函数
*/
function dealWords(options) {
options.ctx.font = options.font; //设置字体
var allRow = Math.ceil(options.ctx.measureText(options.word).width / options.maxWidth); //实际总共能分多少行
var count = allRow >= options.maxLine ? options.maxLine : allRow; //实际能分多少行与设置的最大显示行数比,谁小就用谁做循环次数
var endPos = 0; //当前字符串的截断点
for (var j = 0; j < count; j++) {
var nowStr = options.word.slice(endPos); //当前剩余的字符串
var rowWid = 0; //每一行当前宽度
if (options.ctx.measureText(nowStr).width > options.maxWidth) { //如果当前的字符串宽度大于最大宽度,然后开始截取
for (var m = 0; m < nowStr.length; m++) {
rowWid += options.ctx.measureText(nowStr[m]).width; //当前字符串总宽度
if (rowWid > options.maxWidth) {
if (j === options.maxLine - 1) { //如果是最后一行
options.ctx.fillText(nowStr.slice(0, m - 1) + '...', options.x, options.y + (j + 1) * options
.l_h); //(j+1)*18这是每一行的高度
} else {
options.ctx.fillText(nowStr.slice(0, m), options.x, options.y + (j + 1) * options.l_h);
}
endPos += m; //下次截断点
break;
}
}
} else { //如果当前的字符串宽度小于最大宽度就直接输出
options.ctx.fillText(nowStr.slice(0), options.x, options.y + (j + 1) * options.l_h);
}
}
}
/*
* 绘制圆角按钮
* ctx:createCanvasContext
* color:背景颜色;
* x:x坐标
* y:y坐标
* width:宽
* height:高
* radius:圆角
* text:文字
* fontColor:文字颜色
* textAlign: left/center/right
*/
export const drawButton = function(ctx, color, x, y, width, height, radius, text, fontColor, textAlign) {
//分为4条直线4个圆角绘制
ctx.beginPath();
ctx.fillStyle = color;
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.arc(x + width - radius, y + radius, radius, Math.PI * 3 / 2, Math.PI * 2);
ctx.lineTo(x + width, y + height - radius);
ctx.arc(x + width - radius, y + height - radius, radius, Math.PI, Math.PI / 2);
ctx.lineTo(x + radius, y + height);
ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
ctx.lineTo(x, y + radius);
ctx.arc(x + radius, y + radius, radius, Math.PI, Math.PI * 3 / 2);
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = fontColor;
// ctx.font = 'normal bold 12px sans-serif';
ctx.textAlign = textAlign;
ctx.textBaseline = "middle";
ctx.fillText(text, x + width / 2, y + height / 2);
}
export default {
fillRoundRect: fillRoundRect, //绘制矩形
getImageInfo: getImageInfo, //加载图片
drawCircular: drawCircular, //绘制圆形头像
drawImgCover: drawImgCover, //绘制图片cover
dealWords: dealWords, //文本自定义换行
drawButton: drawButton, //绘制圆角按钮
drawRoundRect:drawRoundRect
}
然后自己调一调样式就可以了!!!!