微信小程序中把页面生成图片

article/2025/11/3 21:26:56

这个问题我上网搜了一下,答案有多种,但是真正能用的没有几何。很多答案都是雷同,有的网友也不负责任,直接拿来照抄,自己也不跑一遍看看。哎,不说了,说多了全是泪。希望我们的技术达人在分享的时候,能够真实的走一遍代码,尽量能让我等小白看的懂啊。闹骚发过了,下面我们就进入正题吧(*^__^*) 嘻嘻……

今天分享的是不仅仅把页面生成图片,同时,也要满足能够识别图中的二维码。我们先来看看效果图

其中左边的图片是页面,右边是生成的图片。具体实现代码如下:

一、页面布局(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,因此,我们需要在页面的头部增加canvas。

<canvas canvas-id='share' style='width:375px;height:580px' hidden='{{canvasHidden}}'></canvas>其中,canvas-id是ID,后面我们会用到,同时设置它的样式。这个没什么好说的,基本上都能看的懂。

二、页面样式(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处理(js)

const app = getApp();/*
小程序利用canvas实现一键保存图片功能 */
Page({/*** 页面的初始数据*/data: {cname: '',renwu: '',yuyan: '',fan: '',xg: '',imgurl: '', canvasHidden: true,     //设置画板的显示与隐藏,画板不隐藏会影响页面正常显示wxappName: '页面生成图片',    //小程序名称shareImgPath: '',screenWidth: '',       //设备屏幕宽度shareImgSrc: '',},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {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 () {}
})

通过以上方式我们就能轻松的把页面转换成图片。希望本次教程对你有所帮助。如果有不明白的地方,可以扫描下面的二维码加入我们的群,我会在群里给予指导。


http://chatgpt.dhexx.cn/article/ksGwFuQy.shtml

相关文章

微信小程序之海报生成

前言&#xff1a;2.9.0 起支持一套新 Canvas 2D 接口&#xff08;需指定 type 属性&#xff09;&#xff0c;同时支持同层渲染&#xff0c;原有接口不再维护 参考文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html <!-- 海报 --&…

如何自己制作小程序?

现在小程序非常流行&#xff0c;很多人都想制作一个自己的小程序来卖货。以前制作小程序通常需要请小程序开发公司&#xff0c;而且需要每年给多少钱&#xff08;通常几百到几千&#xff09;。但随着微信越来越完善&#xff0c;现在无需找小程序服务商搭建&#xff0c;无需懂代…

微信小程序链接快速生成方法

文章目录 前言一、如何生成微信小程序链接&#xff1f;二、生成微信小程序链接步骤1.获取 URL Scheme2.获取 URL Link3.获取 Short Link4.短信打开小程序5.NFC 标签打开小程序 总结 前言 微信官方更新了链接跳转微信小程序的功能&#xff0c;在点击链接后即可直接跳转到小程序…

小程序码的生成

一、生成方式 微信小程序提供了三个接口来生成小程序码&#xff0c;分别是wxacode.createQRCode()、wxacode.get()、wxacode.getUnlimited()&#xff0c;生成的小程序码永久有效&#xff0c;其中仅getUnlimited接口生成的小程序码数量暂无限制 二、接口详解 1、wxacode.creat…

微信小程序分享小程序码的生成(带参数)以及参数的获取

这篇文章主要介绍了微信小程序分享小程序码的生成&#xff08;带参数&#xff09;以及参数的获取&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧 1.小程序码介绍 从…

netlify 自动部署化工具

一、使用github或者gitlab登陆netlify 打开进入netlify官网 二、然后使用github或者gitlab账号登录。 三、登录成功后直接将自己build生成的dist 文件目录拖到虚线框中 四、可以看到netlify为我们随机生成了一个netlify下的域名&#xff0c;可以直接在浏览器访问。 五&…

Coolify: 一款超强大的开源自托管 Heroku / Netlify 替代方案

公众号关注 「奇妙的 Linux 世界」 设为「星标」&#xff0c;每天带你玩转 Linux &#xff01; Coolify 是一种可自我托管的综合解决方案&#xff0c;只需单击几下即可托管你的应用、数据库或其他开源服务。它是 Heroku 和 Netlify 的一个替代方案。 通过 Coolify 可以部署很多…

122.将实战网页部署到Netlify

● 本章我们将网站部署到Netlify ● 首先先点击右上角注册一个账号 ● 注册完成之后&#xff0c;点击sites&#xff0c;将我们的网站文件夹拖入 ● 上传成功 ● 之后就可以正常访问啦 ● 我们也可以修改我们的站点名称&#xff0c;让他更加好记

在netlify上部署golang web应用

介绍 Netlify是一个专门托管静态文件的云。这使得它非常适合托管开发人员博客、宣传册网站&#xff0c;甚至只是一个个人简历。它甚至内置了对Hugo的支持。但是Netlify也有各种动态托管解决方案&#xff0c;他们的functions服务是托管Go Web应用程序的一种非常简单的方法&…

利用Netlify/Vercel和Digitalpress搭建免费Ghost静态博客

第一步 先去https://www.digitalpress.blog/申请一个免费的Ghost博客。 当然你可以用自己的主机&#xff0c;或者digitalocean免费的学生包。只要是Ghost就可以。 第二步 注册Netlify或者Vercel(两个都可以&#xff0c;自己挑选,我自己测试Vercel链接更快) 自行测试&#…

NET Framework

NET Framework 是一个可以快速开发、部署网站服务及应用程序的开发平台&#xff0c;是 Windows 中的一个组件&#xff0c;包括公共语言运行时&#xff08;Common Language Runtime, CLR&#xff09;虚拟执行系统和 .NET Framework 类库。 .NET Framework 的特点如下。 提供标准…

使用Netlify部署博客

文章目录 github 项目部署自定义域名 原先博客是部署在 githubPages 上的&#xff0c;稍微设置一下就能实现自动化部署和启用 https&#xff0c;还是蛮方便的&#xff0c;但是使用国内网络访问 githubPages 上部署的网站速度太慢了&#xff0c;体验很差&#xff0c;因此&#x…

如何下载.NET Framework

下载网址&#xff1a; https://dotnet.microsoft.com/zh-cn/download/dotnet-framework 登录网址 选择适合的版本&#xff0c;如果你的版本太低可能要多尝试一个版本是否能够安装成功

【2022年】的网页转 App 教程

● 如何将网站转为 App&#xff1f; 使用 HopWeb 可以毫无技术成本的制作属于你的App。 HopWeb 官方网站&#xff1a;https://atreep.netlify.app/hopweb ● 网站转 App 适用于以下类型的网站&#xff1a;个人博客、工具类网站等 ● 本教程将以【百度】网站为例&#xff0c;引…

通过Netlify制作个人网站

个人主页的创建 本文主要介绍个人主页的创建过程&#xff0c;主要通过知乎回答的指导&#xff0c;参考本人制作的个人主页。 本人个人主页制作主要使用Netlify&#xff0c;参考该网站安装教程进行安装&#xff0c;直接在自己的github中创建一个仓库作为网站节点。在安装过程中…

【经验】静态博客部署 Hexo + Netlify-CMS + Vercel (在线构建)

目录 引入背景方案 步骤生成starter模板添加Netlify CMS在线管理添加Netlify身份验证组件启用git gateway身份验证换用Vercel作为CDN重新添加js添加身份验证器绑定oauth 定制404页面 模板已知问题 引入 背景 Hexo等静态博客相对于Wordpress等动态博客&#xff0c;可以白嫖很多…

.net framework 官方下载地址

.net framework 官方下载地址 https://dotnet.microsoft.com/zh-cn/download/dotnet-framework

使用Netlify部署静态网站

之前写了一篇文章是关于在树莓派上部署Hexo的博客&#xff0c;但树莓派难免会出故障&#xff0c;所以将网站放在另一个地方会更安全一点。 前一篇&#xff1a;https://fitswcblog.com/%E6%A0%91%E8%8E%93%E6%B4%BE%E6%90%AD%E5%BB%BAhexo%E5%8D%9A%E5%AE%A2/ 我在csdn上的所有…

123.HTML5+CSS3完结_使用Netlify收取表单

Netlify也可以做表单接受&#xff1a; 我们启动一下 修改下表单 ● 接着在我们的网站输入并提交表单 ● 之后会有一个提示&#xff0c;提示我们提交成功 然后就能在Netlify接受到用户的表单 ● 当然这个表单只能接受100个&#xff0c;但是作为实验也够用了 到此&a…

第七章:使用Netlify零成本部署组件文档

第七章&#xff1a;使用Netlify无成本发布组件文档 为什么使用Netlify&#xff1f; 一开始一共有三个方案&#xff1a; 1、Github Page 2、Netlify 3、Vercel Github Page只支持一个repo发布一个网站&#xff0c;而我们的项目是一个mononrepo项目&#xff0c;后续可能还有其他…