这个问题我上网搜了一下,答案有多种,但是真正能用的没有几何。很多答案都是雷同,有的网友也不负责任,直接拿来照抄,自己也不跑一遍看看。哎,不说了,说多了全是泪。希望我们的技术达人在分享的时候,能够真实的走一遍代码,尽量能让我等小白看的懂啊。闹骚发过了,下面我们就进入正题吧(*^__^*) 嘻嘻……
今天分享的是不仅仅把页面生成图片,同时,也要满足能够识别图中的二维码。我们先来看看效果图。点击生成海报,就生成右侧图片
其中左边的图片是页面,右边是生成的图片。具体实现代码如下:
一、页面布局(wxml)
<view class="am_box">
<view class="am_hysn">好友送您</view>
<view class="am_jyq">15元加油券</view>
<!--福利开始-->
<view class="am_fuli">
<view class="am_bk">
<view class="am_title">用悦孚加油 享四大福利</view>
<view class="am_fltype">
<view class="am_type">每次加油都省钱</view>
<view class="am_type">实时查价更便捷</view>
<view class="am_type">油品保障资质全</view>
<view class="am_type">悦孚油站任你选</view>
</view>
</view>
</view>
<!--福利结束-->
<view class="am_result" style="{{'padding-left:' + winWidth}}">
<canvas class="canvas-poster" id="mycanvas" canvas-id="mycanvas"></canvas>
</view>
<view class="am_sub_title">油好 省钱 去悦孚</view>
<view class='am_Mselect'>
<button open-type="share" id="btn" size="mini">
<image src="/images/share01@2x.png'" mode="aspectFill" class="am_wx"></image>
<text class="am_wxhy">微信好友</text>
</button>
<view class="am_share" catchtap="clickSaveImg">
<image src="/images/savepic.png" mode="aspectFill" class="am_wx"></image>
<text class="am_wxhy">生成海报</text>
</view>
</view>
</view>
<!--分享开始-->
<view class="sign_success_popup" wx:if="{{canvasType}}">
<view class="popup_mask"></view>
<view class="popup_content">
<canvas class='canvas' canvas-id="hbmycanvas" id="hbmycanvas" />
<view class="bottom-dialog-body">
<view class='Mcancel' bindtap='mCancel'><text>取消</text></view>
<view class="am_save" catchtap="saveImg">保存到本地相册</view>
</view>
</view>
</view>
<!--分享介绍-->
二、页面样式(wxss)
.am_box {
width:100%;
height: 100%;
position: fixed;
top:0;
box-sizing: border-box;
padding:170rpx 40rpx 10rpx 40rpx;
display: flex;
flex-direction: column;
align-items: center;
background:url('背景图片') no-repeat;
background-size: 100% 100%;
overflow: hidden;
}
.am_hysn {
color:#ffffff;
font-family: 'FZY3B';
font-size: 104rpx;
}
.am_jyq {
color:#ffffff;
font-family: 'FZY3B';
font-weight: bold;
font-size: 120rpx;
line-height: 136rpx;
text-shadow: 2rpx 3rpx 0rpx #FFAC3E;
}
.am_img {
width:100%;
margin:0 auto;
text-align: center;
box-sizing: border-box;
}
.am_img > image {
width:100%;
height:505px;
}
.canvas {
width: 100%;
height: -webkit-calc(100% - 44px);
height: -moz-calc(100% - 44px);
height: calc(100% - 44px);
}
.am_Mselect{
width:100%;
background:#ffffff;
display: flex;
justify-content: space-around;
align-items: center;
border-radius: 10rpx;
}
.am_wxhy {
color:#323232;
font-size:28rpx;
font-weight: 550;
}
.am_wx {
width:80rpx;
height:80rpx;
}
#btn {
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
/* padding:25rpx;*/
background:#ffffff;
}
.am_share {
width:50%;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
padding:25rpx;
}
.bottom-positon{-webkit-transform:translateY(100%);transform:translateY(100%);}
.modal{position:fixed; top:0; right:0; bottom:0; left:0; z-index:1000;}
.modal-cancel{position:absolute; z-index:2000; top:0; right:0; bottom: 0; left:0; background:rgba(0,0,0,0.3);}
.bottom-dialog-body{
width:100%;
box-sizing:border-box;
display:flex;
justify-content: space-around;
align-items: center;
margin-top:-5rpx;
}
.Mcancel{
width:50%;
text-align: center;
background: #fff;
line-height: 80rpx;
height: 80rpx;
color:#333333;
}
/**弹窗开始**/
.sign_success_popup {
position: fixed;
top: 0;
left: 0;
z-index: 100;
width: 100vw;
height: 100vh;
}
.popup_mask {
position: absolute;
width: 100%;
height: 100%;
z-index: -1;
background: rgba(0, 0, 0, .33);
}
.am_save {
width:50%;
box-sizing: border-box;
background:#19BE6B;
color:#FFFFFF;
text-align: center;
line-height: 80rpx;
height: 80rpx;
}
.popup_content {
position: relative;
width: 90%;
height: 90%;
margin: 7vh auto;
padding: 20rpx 16rpx 0;
text-align: center;
outline:none;
background:transparent;
}
/**弹窗结束**/
/**福利开始**/
.am_fuli {
width:100%;
box-sizing: border-box;
background: #FFFFFF;
border-radius: 20rpx;
margin-top:50rpx;
}
.am_bk {
width:100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
background:url('背景图片') no-repeat;
background-size: 100% 100%;
padding:50rpx 25rpx 50rpx 25rpx;
}
.am_title {
font-size: 40rpx;
font-family: 'FZY3JW','FZY3B';
font-weight: 400;
color: #FF4200;
margin-bottom:50rpx;
}
.am_fltype {
width:100%;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
}
.am_type {
width:48%;
box-sizing: border-box;
text-align: center;
height: 86rpx;
line-height: 86rpx;
background: linear-gradient(180deg, #FDF0C4, #FDBE7A);
border-radius: 13rpx;
color:#6E3F1A;
font-size: 28rpx;
margin-bottom:25rpx;
}
/**福利结束**/
.am_result {
width: 240rpx;
height: 240rpx;
/* background: #FFFFFF;
border: 2px solid #9FCA4C;
border-radius: 25rpx;
box-sizing: border-box; */
margin-top:30rpx;
text-align: center;
padding-left:20rpx;
}
.canvas-poster {
height:200rpx;
}
.am_sub_title {
width:100%;
box-sizing: border-box;
text-align: center;
font-size: 32rpx;
font-family: FZZhunYuan-M02;
font-weight: 400;
color: #FFFFFF;
line-height: 45rpx;
text-shadow: 1rpx 1rpx 0rpx #393939;
margin-top:0rpx;
margin-bottom:20rpx;
}
三、页面JS处理(js)
const app = getApp();
const util = require('../../../utils/util.js');
const moment = require('../../../utils/moment.js'); //时间处理,可以从网上下载
const baseUrl = getApp().globalData.baseUrl;
const qrcode = require('../../../utils/weapp.qrcode'); //生成二维码,可以从网上下载
Page({
/**
* 页面的初始数据
*/
data: {
title:'邀请好友得加油券',
money:15,
imgUrl:getApp().globalData.imgUrl,
_width: 0, //手机屏宽
_heigth: 0,//手机屏高
swiperHeight: 300,//主图图片高度
canvasType: false,//canvas是否显示
loadImagePath: '',//下载的图片
imageUrl: 'https://www.xx.com/uploadPath/miniapppic/fx_bg002.png', //主图网络路径
picUrl: 'https://www.xx.com/uploadPath/miniapppic/fx_pic0.png',//福利网络图片
codeUrl: '',//二维码网络路径
localImageUrl: '', //主图本地路径
localCodeUrl: '', //绘制的二维码图片本地路径
localPicUrl:'', //绘制福利图片本地路径
animationData: {},
tel:'',
winWidth:'',
},
/**
* 生成二维码带LOGO
*/
formSubmit(mobile) {
if (mobile) {
var that = this;
wx.showToast({
title: '二维码生成中...',
icon: 'loading',
duration: 1000
});
qrcode({
width:100,
height:100,
canvasId:'mycanvas',
text:'https://www.xxx.com/inviteRegister?mobile=' + mobile,
image:{
imageResource:'../../../images/am_logo.png', //logo图片
dx: 35,
dy: 35,
dWidth: 30,
dHeight: 30
},
cbResult: function(res) {
console.log('回调:',res)
}
});
setTimeout(function () {
wx.hideToast()
wx.canvasToTempFilePath({
canvasId: 'mycanvas',
success: function (res) {
console.log('临时二维码地址:',res)
var codeUrl = res.tempFilePath;
that.setData({
codeUrl: codeUrl,
});
},
fail: function (res) {
console.log(res);
}
});
}, 1000);
}
},
/**
* 关闭弹窗
*/
mCancel() {
this.setData({
canvasType:false,
});
},
//生成海报
clickSaveImg() {
let that = this
// 获取屏幕宽高
wx.showLoading({
title: '正在生成海报',
})
/*获取手机宽高*/
let imgHeigth = this.data.swiperHeight
let imgUrl = this.data.imageUrl
let qrcodeUrl = this.data.codeUrl
wx.getSystemInfo({
success(res) {
that.setData({
_width: res.windowWidth,
_heigth: res.windowHeight,
canvasType: true,
})
// 获取图片信息生成canvas
that.getImginfo([imgUrl, qrcodeUrl], 0);
}
})
},
//把福利图片变成本地图片
getPicImgInfo() {
let that = this;
wx.getImageInfo({
src: that.data.picUrl,
success:function(res) {
console.log('把福利图片变成本地图片',res)
that.setData({
localPicUrl:res.path,
});
},
fail:function(err) {
console.log('把福利图片变成本地图片失败了:', err)
}
})
},
// 获取图片信息
getImginfo(urlArr, _type) {
let that = this;
wx.getImageInfo({
src: urlArr[_type],
success: function (res) {
console.log('是网络图片的本地地址',res)
//res.path是网络图片的本地地址
if (_type === 0) { //背景图片
that.setData({
localImageUrl: res.path,
})
that.getImginfo(urlArr, 1)
} else {
that.setData({ //二维码
localCodeUrl: res.path,
})
// 创建canvas图片
that.createNewImg();
}
},
fail: function (res) {
//失败回调
console.log('Fail:', _type, res)
}
});
},
//绘制canvas
createNewImg: function () {
let _width = this.data._width,
_heigth = this.data._heigth; //屏幕宽与高
let imgHeigth = this.data.swiperHeight, //原图片高度
scale = (_width - 40) / _width, //缩小比例
that = this;
let imgH = imgHeigth * scale; //绘制时图片显示高度
let ctx = wx.createCanvasContext('hbmycanvas');
//绘制图片
ctx.drawImage(that.data.localImageUrl, 0, 0, util.rpxToPx(685), util.rpxToPx(1285));
// 绘制标题
ctx.setFontSize(35);
ctx.setFillStyle('#ffffff');
ctx.fillText('好友送您', util.rpxToPx(190), 80, imgH + 40, txtWidth);
let txtWidth = _width - 60 + 30 - 100 - 50; //文字的宽度
let bigTitle = that.data.money + '元加油券';
// 绘制大标题
ctx.setFontSize(50);
ctx.setFillStyle('#ffffff');
ctx.fillText(bigTitle, util.rpxToPx(90), 150, imgH + 65, txtWidth);
//绘制福利图片
ctx.drawImage(that.data.localPicUrl, util.rpxToPx(60),util.rpxToPx(350), util.rpxToPx(505), 220);
// 绘制二维码
ctx.drawImage(this.data.localCodeUrl, util.rpxToPx(210), util.rpxToPx(800), 300, 100);
// 绘制小程序名称
ctx.setFontSize(15);
ctx.setFillStyle('#ffffff');
ctx.fillText('油好 省钱 去悦孚', util.rpxToPx(190), util.rpxToPx(1030), imgH + 105, txtWidth);
// 显示绘制
ctx.draw();
//将生成好的图片保存到本地,需要延迟一会,绘制期间耗时
setTimeout(function () {
wx.canvasToTempFilePath({
canvasId: 'hbmycanvas',
success: function (res) {
var tempFilePath = res.tempFilePath;
that.setData({
loadImagePath: tempFilePath,
});
},
fail: function (res) {
console.log(res);
}
});
}, 500);
//关闭提示
wx.hideLoading();
},
//保存图片
saveImg() {
let that = this
wx.getSetting({
success(res) {
if (res.authSetting['scope.writePhotosAlbum']) {
// 用户已经授权
that.saveImage();
} else {
//未授权
wx.authorize({
scope: 'scope.writePhotosAlbum',
success() {
that.saveImage();
},
fail(err) {
if (err && err.errMsg.endsWith("auth deny")) {
wx.showModal({
title: '授权添加到相册',
content: '需要获取您的添加相册权限,请确认授权,否则分享功能无法正常使用',
success: function (resolve) {
if (resolve.confirm) { // 用户同意设置授权
wx.openSetting({
success(res) {
if (res && res.authSetting['scope.writePhotosAlbum']) {
that.saveImage(); // 执行保存函数
}
},
fail(res) { // 用户拒绝设置授权
console.log(res)
wx.showToast({
title: '没有权限,保存失败',
icon:'none'
})
}
})
} else { // 用户拒绝设置
wx.showToast({
title: '没有权限,保存失败',
icon:'none'
})
}
}
})
} else {
wx.showModal({
title: '提示',
content: '获取权限失败,将无法保存到相册哦~',
showCancel: false,
})
}
},
});
}
},
});
},
saveImage() {
let that = this;
//不知道是什么原因,手机环境能正常显示
wx.saveImageToPhotosAlbum({ //保存图片到相册
filePath: that.data.loadImagePath, //生成图片临时路径
success: function () {
wx.showToast({
title: "图片已保存至相册!",
duration: 2000
})
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
let userInfo = wx.getStorageSync('userInfo');
let that = this;
console.log('用户:',userInfo)
if (userInfo) {
this.formSubmit(userInfo.mobile); //生成二维码
this.getPicImgInfo();
this.setData({
tel:userInfo.mobile
});
} else {
util.isLogin(); //登录判断
}
wx.getSystemInfo({
success (res) {
console.log('屏幕宽度',res)
that.setData({
winWidth:res.windowWidth/7 + 'rpx'
});
}
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
return {
title: this.data.title||'邀请好友得加油券',
path: "/pages/xx/xx?mobile=" + this.data.tel + '&lx=1&id=klk',
success: function (res) {
},
};
}
})
四、utils相关函数
//utils相关函数
/**
* 判断用户是否登录
*/
function isLogin() {
wx.showModal({
title:'提示',
content:'请先登录,然后进行后续操作!',
showCancel: false,
success:function(res) {
if (res.confirm) {
wx.reLaunch({
url:'/pages/index/index'
})
}
}
})
}
//尺寸转换
function rpxToPx(data = 0) {
return ((data * wx.getSystemInfoSync().windowWidth)) / 700
}
module.exports = {
isLogin,
rpxToPx
}
以上就是微信小程序生成海报的过程,本人亲测有效。里面涉及到的图片地址自己替换