微信小程序中把页面生成图片
这个问题我上网搜了一下,答案有多种,但是真正能用的没有几何。很多答案都是雷同,有的网友也不负责任,直接拿来照抄,自己也不跑一遍看看。哎,不说了,说多了全是泪。希望我们的技术达人在分享的时候,能够真实的走一遍代码,尽量能让我等小白看的懂啊。闹骚发过了,下面我们就进入正题吧(__) 嘻嘻……
今天分享的是不仅仅把页面生成图片,同时,也要满足能够识别图中的二维码。我们先来看看效果图
canvas组件
要想把页面生成图片,canvas是必不可少的,网上很多朋友说,页面生成的图片背景是空白,这个问题我遇到过,产生背景的原因是因为我们背景图片不能是本地地址,必须是网络地址,而且这个地址必须是https开头的,否则图片调用失败。由于我写的这个案例没有涉及到网络图片,所以我这个代码基本上没有出现问题。具体操作如下。
新建wxml页面
<canvas canvas-id='share' style='width:375px;height:580px' hidden='{{canvasHidden}}'></canvas>
<view class='container-main'>
<view class='am-title'>点击图片预览后,长按或点击右上角保存分享</view> <view class='point-img'>
<image src='../../images/bj.png' class='bjt'></image>
<view class="point-container">
<view class="am-img"><image src='{{imgurl}}'></image></view>
<view class='am-cname'>姓名:<text>{{cname}}</text></view>
<view class='am-yuyan'>近期预言:<text>{{yuyan}}</text></view>
<view class='am-renwu'>人物匹配:<text>{{renwu}}</text></view>
<view class='am-fan'>前世烦恼:<text>{{fan}}</text></view>
<view class='am-xg'>人物性格:<text>{{xg}}</text></view>
<view class="content"><image src='../../images/11.png' class='seal'></image>
</view>
</view>
<view class='am-div'></view>
</view>
</view> <view class='am-footer'>
<button open-type="share" data-tag="share1" id="btn_share1">转发</button>
<button bindtap='saveImageToPhotosAlbum'>保存图片</button> </view>
备注:在页面开头我们创建一下 canvas组件,因为我们生成图片是依赖它。
新建样式(wxss)
好的页面需要好的样式来搭配,下面是页面的样式,大家可以自行修改
.container-main {width:100%;}
.am-title {background-color:#96c9ca; height:70rpx;line-height:70rpx; text-align: center; color:#ffffff;
font-family: PingFangSC-Light,helvetica,'Heiti SC';font-size:.9rem;} .point-img { width:100%;height:100%;}
.bjt {width:100%; height:85%; position: absolute; z-index: -1;}
.am-title2 {font-size:1.6rem;padding-top:20px;padding-bottom:20px;font-weight:bold; text-align: center;color:#ffffff;}
.seal {width:284px;height:80px;position: absolute;left:5%;} .point-container {top:20vh;text-align: left;font-size:1.0rem;border-radius: 10rpx; position: absolute;
margin:10px;padding:10px;margin-top:0px;color:#5e7436;}
.am-img {text-align: center;left:35vw;}
.am-img image {width:200rpx;height:200rpx;}
.point-container text {font-weight:bold;}
.point-container .am-cname {padding-top:15rpx; padding-left:20rpx;padding-right:20rpx;}
.point-container .am-yuyan {padding-top:15rpx; padding-left:20rpx;padding-right:20rpx;}
.point-container .am-renwu {padding-top:15rpx;padding-left:20rpx;padding-right:20rpx;}
.point-container .am-fan {padding-top:15rpx;padding-left:20rpx;padding-right:20rpx;}
.point-container .am-xg {padding-top:15rpx;padding-left:20rpx;padding-right:20rpx;} .content {margin:15rpx auto; text-align: left;}
.am-div {height:20rpx;}
.am-footer {display:flex;height: 100rpx;width: 100%; text-align: center;position: absolute;bottom:-5px;left:0;}
.am-footer button {border:#ff6a38 1px solid; border-radius:20rpx; width:300rpx;
height: 70rpx; text-align: center; line-height:70rpx;
font-size: 30rpx;background-color:#ffffff; letter-spacing:2px;color: #E97855;}
页面JS
这是关键部分,所有的实现效果就全靠它啦,具体如下:
const app = getApp(); /*
小程序利用canvas实现一键保存图片功能
https://blog.csdn.net/Charles_Tian/article/details/80910616 */
Page({ /**
* 页面的初始数据
*/
data: {
cname: '',
renwu: '',
yuyan: '',
fan: '',
xg: '',
imgurl: '', //人物头像
canvasHidden: true, //设置画板的显示与隐藏,画板不隐藏会影响页面正常显示
wxappName: '页面生成图片', //小程序名称
shareImgPath: '',
screenWidth: '', //设备屏幕宽度
shareImgSrc: '', },
infoShow: function () {
var that = this;
wx.request({
url: app.globalData.api_url + 'rest/findProgram/36',
method: 'GET',
header: { 'Accept': 'application/json' },
success: function (res) { WxParse.wxParse('article_content', 'html', res.data.errMsg.s_remark, that, 5) //获取详细信息 res.data.content详细信息数据
that.setData({
info: res.data.errMsg
// article_content: WxParse.wxParse('article_content', 'html', res.data.errMsg.n_remark, that, 5) //获取详细信息 res.data.content详细信息数据
})
wx.setStorageSync('cmsinfo', res.data.errMsg) },
//接口调用失败的回调函数
fail: function (res) {
var newData = wx.getStorageInfoSync('cmsinfo')
if (newData) {
obj.setData({ info: newData })
}
that.setData({ toastHidden: false, msg: '当前网格异常,请稍后再试' })
},
//口调用结束的回调函数(调用成功、失败都会执行)
complete: function () {
//显示出加载中的提示
that.setData({ loadHidden: true })
}
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) { this.infoShow();
var that = this; wx.getImageInfo({
src: '../../images/bj.png',
success: function (res) {
console.log(res)
that.setData({
shareImgSrc: '../../' + res.path
});
}
}) wx.getImageInfo({
src: '../../images/11.png',
success: function (res) {
console.log(res)
that.setData({
shareImgPath: '../../' + res.path
});
}
}) //获取用户设备信息,屏幕宽度
wx.getSystemInfo({
success: res => {
that.setData({
screenWidth: res.screenWidth
})
console.log(that.data.screenWidth)
}
}) that.setData({
cname: options.id
});
var yuyan = new Array('多注意外表,近期将有桃花运', '不要留钱在手,近期将走财运', '留意新认识的人,将遇改变人生的贵人', '走路留意,可能会走狗屎运', '放开吃喝,三个月内你不会发胖', '身边有人正在准备一个惊喜给你');
var c = Math.floor(Math.random() * 6);
var renwu = new Array('富察容音', '弘历', '魏璎珞', '娴妃', '高贵妃', '叶太医', '富察·傅恒', '海兰察', '陆晚晚', '明玉');
var a = Math.floor(Math.random() * 6);
var fan = new Array('因皇子去世一直耿耿于怀,内心苦闷。富察容音常有胸闷、乳房疼痛的症状,是情志失意导致的乳腺问题。', '前朝政务繁多,后宫妃嫔争宠,后宫女人几乎都有乳腺困扰,皇上命叶太医制出乳丹,帮助解决嫔妃的乳腺问题。', '长期想着复仇,情志不畅,所以月经紊乱,乳房有肿块都不知道。幸得叶太医乳丹相助,帮其解决乳腺问题。', '不能保家人周全,无奈黑化,也一直深受乳腺问题的烦恼。', '唯恐失去皇上宠爱,天天苦于宫斗,饱受乳腺问题烦恼。', '苦于没有疑难杂症给他医治,后被皇上指派解决嫔妃的乳腺问题,研发出乳丹。', '因为没有和心爱的女人在一起,从而抱恨终身。', '心爱的女人在成亲当天自杀,让海兰察心痛一生。', '自身实力与家庭背景都很薄弱,不求富贵,只求安保。', '因体内被纯贵妃扎的针重伤加之受顺嫔挑唆,以金剪插心,自尽而亡。');
var xg = new Array('内心温柔,心胸宽广,最终别人,也能得到别人尊重。', '爱憎分明、内心骄傲,做人做事不会选择将就。', '客观理智、内心透彻,内心善良富有正义,重视承诺。', '追求单纯但是内心又自卑,遇到失望的事情,会变得偏执。', '喜形于色,为人处世情绪化,从不压抑内心想法。', '本是江湖游医却救阿哥、激皇上(治病)、怼太医,萌萌的外表下藏着一颗济世救人的医者仁心。', '深得皇上的宠爱和重视,表面上看是一个冷清的人,实际上是一个专情热血的男子。', '心性善良,智勇双全,屡经战阵,注重研习兵法,受众尊崇的将领。', '温婉贤淑的大家闺秀,才貌出众,天性善良,不争名利,清新脱俗。', '性格直爽,忠肝义胆,说话毒舌但是心地善良。');
var img = new Array('http://login.pink333.com/uploads/20180828/4c9b626b59d6a0b38a03089d1da4d906.jpg',
'http://login.pink333.com/uploads/20180828/d942b0f1bccc4e6c6081bd5f3398fd4e.jpg',
'http://login.pink333.com/uploads/20180828/29af4184e336f82a38ecd3de07a01569.jpg',
'http://login.pink333.com/uploads/20180828/eacea6d98f57fdcda835003fd8734c14.jpg',
'http://login.pink333.com/uploads/20180828/9416f7ac87e99efd8a179dedec15d0c0.jpg',
'http://login.pink333.com/uploads/20180828/1ee16bba3d950f8fce32d8e6d01025b3.jpg',
'http://login.pink333.com/uploads/20180828/2114ed95f319b23afa498b6064b90517.jpg',
'http://login.pink333.com/uploads/20180828/07682aa82440bd48bec9cfcdf8830fb0.jpg',
'http://login.pink333.com/uploads/20180828/2f71cd25f32922035c08071042cda134.jpg',
'http://login.pink333.com/uploads/20180828/ff6f46a6ad3c15200f1d380aa1ccde25.jpg'); if (a == 0) {
that.setData({
fan: fan[0],
xg: xg[0],
});
wx.getImageInfo({
src: '../../images/fcry.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 1) {
that.setData({
fan: fan[1],
xg: xg[1]
});
wx.getImageInfo({
src: '../../images/hl.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 2) {
that.setData({
fan: fan[2],
xg: xg[2]
});
wx.getImageInfo({
src: '../../images/wyl.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 3) {
that.setData({
fan: fan[3],
xg: xg[3]
});
wx.getImageInfo({
src: '../../images/xf.jpg',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 4) {
that.setData({
fan: fan[4],
xg: xg[4]
});
wx.getImageInfo({
src: '../../images/ggf.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 5) {
that.setData({
fan: fan[5],
xg: xg[5]
});
wx.getImageInfo({
src: '../../images/yty.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 6) {
that.setData({
fan: fan[6],
xg: xg[6]
});
wx.getImageInfo({
src: '../../images/fcfh.jpg',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 7) {
that.setData({
fan: fan[7],
xg: xg[7]
});
wx.getImageInfo({
src: '../../images/hnc.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 8) {
that.setData({
fan: fan[8],
xg: xg[8]
});
wx.getImageInfo({
src: '../../images/lww.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
if (a == 9) {
that.setData({
fan: fan[9],
xg: xg[9]
});
wx.getImageInfo({
src: '../../images/my.png',
success: function (res) {
console.log(res)
that.setData({
imgurl: '../../' + res.path
});
}
})
}
that.setData({
yuyan:yuyan[c],
renwu: renwu[a]
}); }, /**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
var that = this;
var context = wx.createCanvasContext('share')
context.setStrokeStyle("#00ff00")
context.setLineWidth(1)
context.stroke()
context.draw(false, this.getTempFilePath)
}, //获取临时路径
getTempFilePath: function () {
wx.canvasToTempFilePath({
canvasId: 'share',
success: (res) => {
this.setData({
shareTempFilePath: res.tempFilePath
})
}
})
},
/**
* 绘制多行文本,考虑到内容过多可能会显示不全,这里增加一个函数
*/
drawText: function (ctx, str, leftWidth, initHeight, titleHeight, canvasWidth) {
var lineWidth = 0;
var lastSubStrIndex = 0; //每次开始截取的字符串的索引
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > canvasWidth) {
ctx.fillText(str.substring(lastSubStrIndex, i), leftWidth, initHeight); //绘制截取部分
initHeight += 16; //16为字体的高度
lineWidth = 0;
lastSubStrIndex = i;
titleHeight += 30;
}
if (i == str.length - 1) { //绘制剩余部分
ctx.fillText(str.substring(lastSubStrIndex, i + 1), leftWidth, initHeight);
}
}
// 标题border-bottom 线距顶部距离
titleHeight = titleHeight + 10;
return titleHeight
}, //保存至相册
saveImageToPhotosAlbum: function () {
var that = this;
var unit = that.data.screenWidth / 375
//2. canvas绘制文字和图片
const ctx = wx.createCanvasContext('share');
var bgImgPath = that.data.shareImgSrc;
var fanstr = '前世烦恼:' + that.data.fan;
var rwxg = '人物性格:' + that.data.xg;
//这里是把页面上的数据写入到画布里,具体的坐标需要各位自行调整
ctx.drawImage(bgImgPath, 0, 0, 375, 580);
ctx.drawImage(that.data.shareImgPath, 50, 450, 284, 80);
ctx.drawImage(that.data.imgurl, 146, 100, 100, 100);
ctx.setFontSize(13)
ctx.setFillStyle('#5e7436')
ctx.fillText('姓名:' + that.data.cname, 50, 241)
ctx.fillText('人物匹配:' + that.data.renwu, 50, 271);
ctx.fillText('近期预言:' + that.data.yuyan, 50, 300); this.drawText(ctx, fanstr, 50, 330, 145, 280);
this.drawText(ctx, rwxg, 50, 400, 145, 280);
//ctx.fillText('前世烦恼:' + that.data.fan, 50, 330);
//ctx.fillText('人物性格:' + that.data.xg, 50, 360);
ctx.stroke()
ctx.draw(false, function() {
// 3. canvas画布转成图片
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: 375,
height: 580,
destWidth: 375,
destHeight: 580,
canvasId: 'share',
success: function (res) {
console.log(res);
that.setData({
shareImgSrc: res.tempFilePath
})
if (!res.tempFilePath) {
wx.showModal({
title: '提示',
content: '图片绘制中,请稍后重试',
showCancel: false
})
}
//4. 当用户点击分享到朋友圈时,将图片保存到相册
wx.saveImageToPhotosAlbum({
filePath: that.data.shareImgSrc,
success(res) {
console.log(res);
wx.showModal({
title: '图片保存成功',
content: '图片成功保存到相册了,去发圈噻~',
showCancel: false,
confirmText: '好哒',
confirmColor: '#72B9C3',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
}
that.setData({
canvasHidden: true
})
}
})
}
})
},
fail: function (res) {
console.log(res)
}
})
});
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
const that = this;
wx.downloadFile({
url: that.data.shareImgSrc,
success: function (res) {
that.data.shareImgSrc = res.tempFilePath
}, fail: function (res) {
}
})
}, /**
* 生命周期函数--监听页面隐藏
*/
onHide: function () { }, /**
* 生命周期函数--监听页面卸载
*/
onUnload: function () { }, /**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () { }, /**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () { }, /**
* 用户点击右上角分享
*/
onShareAppMessage: function () { }
})
通过以上方式我们就能轻松的把页面转换成图片。希望本次教程对你有所帮助。如果有不明白的地方,可以扫描下面的二维码加入我们的群,我会在群里给予指导,由于案例中出现很多图片,具体的内容可以到群里下载。
微信小程序中把页面生成图片的更多相关文章
- 微信小程序中在页面中实现下拉刷新显示提醒语后在消失
最近在做小程序的时候遇见一个问题,就是页面要下拉刷新给客户一个提醒语,查看了小程序的官方文档 这里有个注意点:如果你是一页进行下拉刷新就在那个文件夹的json里面加上"enablePullD ...
- 微信小程序中不同页面间的参数传递
从样式页面WXML向逻辑页面JS传递点击事件的响应函数中传递参数 <!--此为样式页面--> <block wx:for="{{postList}}" wx:fo ...
- 微信小程序中公用内容
微信小程序中各个页面调用公用的js 在util.js文件中 // 跳转哪里 function go(where) { wx.reLaunch({ url: where, }) } // 将方法暴露出去 ...
- 在微信小程序中使用富文本转化插件wxParse
在微信小程序中我们往往需要展示一些丰富的页面内容,包括图片.文本等,基本上要求能够解析常规的HTML最好,由于微信的视图标签和HTML标签不一样,但是也有相对应的关系,因此有人把HTML转换做成了一个 ...
- 微信小程序之实现页面缩放式侧滑效果
效果图: 实现原理:点击按钮,往需要动画的div中添加或移除拥有动画效果的class. 由于微信小程序中不能操作page这个根节点,所以,只有用一个div(view)来模仿page根节点. 1.结构 ...
- 微信小程序中用户登录和登录态维护
提供用户登录以及维护用户的登录状态,是一个拥有用户系统的软件应用普遍需要做的事情.像微信这样的一个社交平台,如果做一个小程序应用,我们可能很少会去做一个完全脱离和舍弃连接用户信息的纯工具软件. 让用户 ...
- 微信小程序中的组件使用1
不管是vue还是react中,都在强调组件思想,同样,在微信小程序中也是使用组件思想来实现页面复用的,下面就简单介绍一下微信小程序中的组件思想. 组件定义与使用 要使用组件,首先需要有组件页面和使用组 ...
- 全栈开发工程师微信小程序-中(下)
全栈开发工程师微信小程序-中(下) 微信小程序视图层 wxml用于描述页面的结构,wxss用于描述页面的样式,组件用于视图的基本组成单元. // 绑定数据 index.wxml <view> ...
- 全栈开发工程师微信小程序-中(中)
全栈开发工程师微信小程序-中(中) 开放能力 open-data 用于展示微信开放的数据 type 开放数据类型 open-gid 当 type="groupName" 时生效, ...
随机推荐
- Django学习笔记之URL与视图cookie和session
cookie和session cookie:在网站中,http请求是无状态的.也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户.cookie的出现就是为了 ...
- Docker系列(四)Centos6.5 搭建私人镜像仓库 v2
.下载.运行registry 下载registry镜像: $ docker pull hub.c.163.com/library/registry 这个下载的过程有点长,耐心等待一下.O(∩_∩)O哈 ...
- 【凡尘】---react-redux---【react】
一.Redux与组件 react-redux是一个第三方插件使我们在react上更方便的来使用redux这个数据架构 React-Redux提供connect方法,用于从UI组件生成容器组件,conn ...
- python 画图工具matplotlib 去掉坐标轴和坐标的方法
1. 去掉坐标轴的方法: plt.axis('off') 2.去掉刻度的方法: plt.xticks([]) plt.yticks([]) 以上语句需要将其置于 plt.show() 之前,plt.i ...
- 使用 random() 生成礼包码
需求:生成100个游戏礼包码 具体如下 # 1.构造100个5位随机数 listNumA = [] for n in range(100): listNumA.append(random.randin ...
- 使用Excel自动生成sql语句
在近一段日子里,进入了新的项目组,由于项目需要,经常要将一些Excel表中的数据导入数据库中,以前并没有过多的接触过数据导入与数据处理,对于我来说比较痛苦,今天下午花了几个小时处理数据,但是同事给我提 ...
- TCP/IP学习20180710-数据链路层-ICMP协议
1.ICMP协议IP协议不保证数据送达.则应有协议保证数据送达.ICMP就是其中的重要协议.ICMP:(Internet Control Messages Protocol)因特网信报控制协议当传送I ...
- 洛谷P1040 加分二叉树(树形dp)
加分二叉树 时间限制: 1 Sec 内存限制: 125 MB提交: 11 解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...
- snmp服务中snmpwalk命令常用方法总结
在日常监控中,经常会用到snmp服务,而snmpwalk命令则是测试系统各种信息最有效的方法,命令格式: snmpwalk -c SNMP读密码 -v 1或2(代表SNMP版本) 交换机或路由器IP ...
- 7.7 wordcnt.c 程序
wordcnt.c 程序 #include <stdio.h> #include <ctype.h> // 为isspace() 函数提供原型 #include <std ...