当前位置:   article > 正文

微信小程序中把页面生成图片_lang="wxs"uni实现页面生成图片

lang="wxs"uni实现页面生成图片

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

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

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

一、页面布局(wxml

  1. <view class="am_box">
  2. <view class="am_hysn">好友送您</view>
  3. <view class="am_jyq">15元加油券</view>
  4. <!--福利开始-->
  5. <view class="am_fuli">
  6. <view class="am_bk">
  7. <view class="am_title">用悦孚加油 享四大福利</view>
  8. <view class="am_fltype">
  9. <view class="am_type">每次加油都省钱</view>
  10. <view class="am_type">实时查价更便捷</view>
  11. <view class="am_type">油品保障资质全</view>
  12. <view class="am_type">悦孚油站任你选</view>
  13. </view>
  14. </view>
  15. </view>
  16. <!--福利结束-->
  17. <view class="am_result" style="{{'padding-left:' + winWidth}}">
  18. <canvas class="canvas-poster" id="mycanvas" canvas-id="mycanvas"></canvas>
  19. </view>
  20. <view class="am_sub_title">油好 省钱 去悦孚</view>
  21. <view class='am_Mselect'>
  22. <button open-type="share" id="btn" size="mini">
  23. <image src="/images/share01@2x.png'" mode="aspectFill" class="am_wx"></image>
  24. <text class="am_wxhy">微信好友</text>
  25. </button>
  26. <view class="am_share" catchtap="clickSaveImg">
  27. <image src="/images/savepic.png" mode="aspectFill" class="am_wx"></image>
  28. <text class="am_wxhy">生成海报</text>
  29. </view>
  30. </view>
  31. </view>
  32. <!--分享开始-->
  33. <view class="sign_success_popup" wx:if="{{canvasType}}">
  34. <view class="popup_mask"></view>
  35. <view class="popup_content">
  36. <canvas class='canvas' canvas-id="hbmycanvas" id="hbmycanvas" />
  37. <view class="bottom-dialog-body">
  38. <view class='Mcancel' bindtap='mCancel'><text>取消</text></view>
  39. <view class="am_save" catchtap="saveImg">保存到本地相册</view>
  40. </view>
  41. </view>
  42. </view>
  43. <!--分享介绍-->

二、页面样式(wxss

  1. .am_box {
  2. width:100%;
  3. height: 100%;
  4. position: fixed;
  5. top:0;
  6. box-sizing: border-box;
  7. padding:170rpx 40rpx 10rpx 40rpx;
  8. display: flex;
  9. flex-direction: column;
  10. align-items: center;
  11. background:url('背景图片') no-repeat;
  12. background-size: 100% 100%;
  13. overflow: hidden;
  14. }
  15. .am_hysn {
  16. color:#ffffff;
  17. font-family: 'FZY3B';
  18. font-size: 104rpx;
  19. }
  20. .am_jyq {
  21. color:#ffffff;
  22. font-family: 'FZY3B';
  23. font-weight: bold;
  24. font-size: 120rpx;
  25. line-height: 136rpx;
  26. text-shadow: 2rpx 3rpx 0rpx #FFAC3E;
  27. }
  28. .am_img {
  29. width:100%;
  30. margin:0 auto;
  31. text-align: center;
  32. box-sizing: border-box;
  33. }
  34. .am_img > image {
  35. width:100%;
  36. height:505px;
  37. }
  38. .canvas {
  39. width: 100%;
  40. height: -webkit-calc(100% - 44px);
  41. height: -moz-calc(100% - 44px);
  42. height: calc(100% - 44px);
  43. }
  44. .am_Mselect{
  45. width:100%;
  46. background:#ffffff;
  47. display: flex;
  48. justify-content: space-around;
  49. align-items: center;
  50. border-radius: 10rpx;
  51. }
  52. .am_wxhy {
  53. color:#323232;
  54. font-size:28rpx;
  55. font-weight: 550;
  56. }
  57. .am_wx {
  58. width:80rpx;
  59. height:80rpx;
  60. }
  61. #btn {
  62. box-sizing: border-box;
  63. display: flex;
  64. flex-direction: column;
  65. align-items: center;
  66. /* padding:25rpx;*/
  67. background:#ffffff;
  68. }
  69. .am_share {
  70. width:50%;
  71. box-sizing: border-box;
  72. display: flex;
  73. flex-direction: column;
  74. align-items: center;
  75. padding:25rpx;
  76. }
  77. .bottom-positon{-webkit-transform:translateY(100%);transform:translateY(100%);}
  78. .modal{position:fixed; top:0; right:0; bottom:0; left:0; z-index:1000;}
  79. .modal-cancel{position:absolute; z-index:2000; top:0; right:0; bottom: 0; left:0; background:rgba(0,0,0,0.3);}
  80. .bottom-dialog-body{
  81. width:100%;
  82. box-sizing:border-box;
  83. display:flex;
  84. justify-content: space-around;
  85. align-items: center;
  86. margin-top:-5rpx;
  87. }
  88. .Mcancel{
  89. width:50%;
  90. text-align: center;
  91. background: #fff;
  92. line-height: 80rpx;
  93. height: 80rpx;
  94. color:#333333;
  95. }
  96. /**弹窗开始**/
  97. .sign_success_popup {
  98. position: fixed;
  99. top: 0;
  100. left: 0;
  101. z-index: 100;
  102. width: 100vw;
  103. height: 100vh;
  104. }
  105. .popup_mask {
  106. position: absolute;
  107. width: 100%;
  108. height: 100%;
  109. z-index: -1;
  110. background: rgba(0, 0, 0, .33);
  111. }
  112. .am_save {
  113. width:50%;
  114. box-sizing: border-box;
  115. background:#19BE6B;
  116. color:#FFFFFF;
  117. text-align: center;
  118. line-height: 80rpx;
  119. height: 80rpx;
  120. }
  121. .popup_content {
  122. position: relative;
  123. width: 90%;
  124. height: 90%;
  125. margin: 7vh auto;
  126. padding: 20rpx 16rpx 0;
  127. text-align: center;
  128. outline:none;
  129. background:transparent;
  130. }
  131. /**弹窗结束**/
  132. /**福利开始**/
  133. .am_fuli {
  134. width:100%;
  135. box-sizing: border-box;
  136. background: #FFFFFF;
  137. border-radius: 20rpx;
  138. margin-top:50rpx;
  139. }
  140. .am_bk {
  141. width:100%;
  142. box-sizing: border-box;
  143. display: flex;
  144. flex-direction: column;
  145. align-items: center;
  146. background:url('背景图片') no-repeat;
  147. background-size: 100% 100%;
  148. padding:50rpx 25rpx 50rpx 25rpx;
  149. }
  150. .am_title {
  151. font-size: 40rpx;
  152. font-family: 'FZY3JW','FZY3B';
  153. font-weight: 400;
  154. color: #FF4200;
  155. margin-bottom:50rpx;
  156. }
  157. .am_fltype {
  158. width:100%;
  159. box-sizing: border-box;
  160. display: flex;
  161. justify-content: space-between;
  162. align-items: center;
  163. flex-wrap: wrap;
  164. }
  165. .am_type {
  166. width:48%;
  167. box-sizing: border-box;
  168. text-align: center;
  169. height: 86rpx;
  170. line-height: 86rpx;
  171. background: linear-gradient(180deg, #FDF0C4, #FDBE7A);
  172. border-radius: 13rpx;
  173. color:#6E3F1A;
  174. font-size: 28rpx;
  175. margin-bottom:25rpx;
  176. }
  177. /**福利结束**/
  178. .am_result {
  179. width: 240rpx;
  180. height: 240rpx;
  181. /* background: #FFFFFF;
  182. border: 2px solid #9FCA4C;
  183. border-radius: 25rpx;
  184. box-sizing: border-box; */
  185. margin-top:30rpx;
  186. text-align: center;
  187. padding-left:20rpx;
  188. }
  189. .canvas-poster {
  190. height:200rpx;
  191. }
  192. .am_sub_title {
  193. width:100%;
  194. box-sizing: border-box;
  195. text-align: center;
  196. font-size: 32rpx;
  197. font-family: FZZhunYuan-M02;
  198. font-weight: 400;
  199. color: #FFFFFF;
  200. line-height: 45rpx;
  201. text-shadow: 1rpx 1rpx 0rpx #393939;
  202. margin-top:0rpx;
  203. margin-bottom:20rpx;
  204. }

三、页面JS处理(js)

  1. const app = getApp();
  2. const util = require('../../../utils/util.js');
  3. const moment = require('../../../utils/moment.js'); //时间处理,可以从网上下载
  4. const baseUrl = getApp().globalData.baseUrl;
  5. const qrcode = require('../../../utils/weapp.qrcode'); //生成二维码,可以从网上下载
  6. Page({
  7. /**
  8. * 页面的初始数据
  9. */
  10. data: {
  11. title:'邀请好友得加油券',
  12. money:15,
  13. imgUrl:getApp().globalData.imgUrl,
  14. _width: 0, //手机屏宽
  15. _heigth: 0,//手机屏高
  16. swiperHeight: 300,//主图图片高度
  17. canvasType: false,//canvas是否显示
  18. loadImagePath: '',//下载的图片
  19. imageUrl: 'https://www.xx.com/uploadPath/miniapppic/fx_bg002.png', //主图网络路径
  20. picUrl: 'https://www.xx.com/uploadPath/miniapppic/fx_pic0.png',//福利网络图片
  21. codeUrl: '',//二维码网络路径
  22. localImageUrl: '', //主图本地路径
  23. localCodeUrl: '', //绘制的二维码图片本地路径
  24. localPicUrl:'', //绘制福利图片本地路径
  25. animationData: {},
  26. tel:'',
  27. winWidth:'',
  28. },
  29. /**
  30. * 生成二维码带LOGO
  31. */
  32. formSubmit(mobile) {
  33. if (mobile) {
  34. var that = this;
  35. wx.showToast({
  36. title: '二维码生成中...',
  37. icon: 'loading',
  38. duration: 1000
  39. });
  40. qrcode({
  41. width:100,
  42. height:100,
  43. canvasId:'mycanvas',
  44. text:'https://www.xxx.com/inviteRegister?mobile=' + mobile,
  45. image:{
  46. imageResource:'../../../images/am_logo.png', //logo图片
  47. dx: 35,
  48. dy: 35,
  49. dWidth: 30,
  50. dHeight: 30
  51. },
  52. cbResult: function(res) {
  53. console.log('回调:',res)
  54. }
  55. });
  56. setTimeout(function () {
  57. wx.hideToast()
  58. wx.canvasToTempFilePath({
  59. canvasId: 'mycanvas',
  60. success: function (res) {
  61. console.log('临时二维码地址:',res)
  62. var codeUrl = res.tempFilePath;
  63. that.setData({
  64. codeUrl: codeUrl,
  65. });
  66. },
  67. fail: function (res) {
  68. console.log(res);
  69. }
  70. });
  71. }, 1000);
  72. }
  73. },
  74. /**
  75. * 关闭弹窗
  76. */
  77. mCancel() {
  78. this.setData({
  79. canvasType:false,
  80. });
  81. },
  82. //生成海报
  83. clickSaveImg() {
  84. let that = this
  85. // 获取屏幕宽高
  86. wx.showLoading({
  87. title: '正在生成海报',
  88. })
  89. /*获取手机宽高*/
  90. let imgHeigth = this.data.swiperHeight
  91. let imgUrl = this.data.imageUrl
  92. let qrcodeUrl = this.data.codeUrl
  93. wx.getSystemInfo({
  94. success(res) {
  95. that.setData({
  96. _width: res.windowWidth,
  97. _heigth: res.windowHeight,
  98. canvasType: true,
  99. })
  100. // 获取图片信息生成canvas
  101. that.getImginfo([imgUrl, qrcodeUrl], 0);
  102. }
  103. })
  104. },
  105. //把福利图片变成本地图片
  106. getPicImgInfo() {
  107. let that = this;
  108. wx.getImageInfo({
  109. src: that.data.picUrl,
  110. success:function(res) {
  111. console.log('把福利图片变成本地图片',res)
  112. that.setData({
  113. localPicUrl:res.path,
  114. });
  115. },
  116. fail:function(err) {
  117. console.log('把福利图片变成本地图片失败了:', err)
  118. }
  119. })
  120. },
  121. // 获取图片信息
  122. getImginfo(urlArr, _type) {
  123. let that = this;
  124. wx.getImageInfo({
  125. src: urlArr[_type],
  126. success: function (res) {
  127. console.log('是网络图片的本地地址',res)
  128. //res.path是网络图片的本地地址
  129. if (_type === 0) { //背景图片
  130. that.setData({
  131. localImageUrl: res.path,
  132. })
  133. that.getImginfo(urlArr, 1)
  134. } else {
  135. that.setData({ //二维码
  136. localCodeUrl: res.path,
  137. })
  138. // 创建canvas图片
  139. that.createNewImg();
  140. }
  141. },
  142. fail: function (res) {
  143. //失败回调
  144. console.log('Fail:', _type, res)
  145. }
  146. });
  147. },
  148. //绘制canvas
  149. createNewImg: function () {
  150. let _width = this.data._width,
  151. _heigth = this.data._heigth; //屏幕宽与高
  152. let imgHeigth = this.data.swiperHeight, //原图片高度
  153. scale = (_width - 40) / _width, //缩小比例
  154. that = this;
  155. let imgH = imgHeigth * scale; //绘制时图片显示高度
  156. let ctx = wx.createCanvasContext('hbmycanvas');
  157. //绘制图片
  158. ctx.drawImage(that.data.localImageUrl, 0, 0, util.rpxToPx(685), util.rpxToPx(1285));
  159. // 绘制标题
  160. ctx.setFontSize(35);
  161. ctx.setFillStyle('#ffffff');
  162. ctx.fillText('好友送您', util.rpxToPx(190), 80, imgH + 40, txtWidth);
  163. let txtWidth = _width - 60 + 30 - 100 - 50; //文字的宽度
  164. let bigTitle = that.data.money + '元加油券';
  165. // 绘制大标题
  166. ctx.setFontSize(50);
  167. ctx.setFillStyle('#ffffff');
  168. ctx.fillText(bigTitle, util.rpxToPx(90), 150, imgH + 65, txtWidth);
  169. //绘制福利图片
  170. ctx.drawImage(that.data.localPicUrl, util.rpxToPx(60),util.rpxToPx(350), util.rpxToPx(505), 220);
  171. // 绘制二维码
  172. ctx.drawImage(this.data.localCodeUrl, util.rpxToPx(210), util.rpxToPx(800), 300, 100);
  173. // 绘制小程序名称
  174. ctx.setFontSize(15);
  175. ctx.setFillStyle('#ffffff');
  176. ctx.fillText('油好 省钱 去悦孚', util.rpxToPx(190), util.rpxToPx(1030), imgH + 105, txtWidth);
  177. // 显示绘制
  178. ctx.draw();
  179. //将生成好的图片保存到本地,需要延迟一会,绘制期间耗时
  180. setTimeout(function () {
  181. wx.canvasToTempFilePath({
  182. canvasId: 'hbmycanvas',
  183. success: function (res) {
  184. var tempFilePath = res.tempFilePath;
  185. that.setData({
  186. loadImagePath: tempFilePath,
  187. });
  188. },
  189. fail: function (res) {
  190. console.log(res);
  191. }
  192. });
  193. }, 500);
  194. //关闭提示
  195. wx.hideLoading();
  196. },
  197. //保存图片
  198. saveImg() {
  199. let that = this
  200. wx.getSetting({
  201. success(res) {
  202. if (res.authSetting['scope.writePhotosAlbum']) {
  203. // 用户已经授权
  204. that.saveImage();
  205. } else {
  206. //未授权
  207. wx.authorize({
  208. scope: 'scope.writePhotosAlbum',
  209. success() {
  210. that.saveImage();
  211. },
  212. fail(err) {
  213. if (err && err.errMsg.endsWith("auth deny")) {
  214. wx.showModal({
  215. title: '授权添加到相册',
  216. content: '需要获取您的添加相册权限,请确认授权,否则分享功能无法正常使用',
  217. success: function (resolve) {
  218. if (resolve.confirm) { // 用户同意设置授权
  219. wx.openSetting({
  220. success(res) {
  221. if (res && res.authSetting['scope.writePhotosAlbum']) {
  222. that.saveImage(); // 执行保存函数
  223. }
  224. },
  225. fail(res) { // 用户拒绝设置授权
  226. console.log(res)
  227. wx.showToast({
  228. title: '没有权限,保存失败',
  229. icon:'none'
  230. })
  231. }
  232. })
  233. } else { // 用户拒绝设置
  234. wx.showToast({
  235. title: '没有权限,保存失败',
  236. icon:'none'
  237. })
  238. }
  239. }
  240. })
  241. } else {
  242. wx.showModal({
  243. title: '提示',
  244. content: '获取权限失败,将无法保存到相册哦~',
  245. showCancel: false,
  246. })
  247. }
  248. },
  249. });
  250. }
  251. },
  252. });
  253. },
  254. saveImage() {
  255. let that = this;
  256. //不知道是什么原因,手机环境能正常显示
  257. wx.saveImageToPhotosAlbum({ //保存图片到相册
  258. filePath: that.data.loadImagePath, //生成图片临时路径
  259. success: function () {
  260. wx.showToast({
  261. title: "图片已保存至相册!",
  262. duration: 2000
  263. })
  264. }
  265. })
  266. },
  267. /**
  268. * 生命周期函数--监听页面加载
  269. */
  270. onLoad(options) {
  271. let userInfo = wx.getStorageSync('userInfo');
  272. let that = this;
  273. console.log('用户:',userInfo)
  274. if (userInfo) {
  275. this.formSubmit(userInfo.mobile); //生成二维码
  276. this.getPicImgInfo();
  277. this.setData({
  278. tel:userInfo.mobile
  279. });
  280. } else {
  281. util.isLogin(); //登录判断
  282. }
  283. wx.getSystemInfo({
  284. success (res) {
  285. console.log('屏幕宽度',res)
  286. that.setData({
  287. winWidth:res.windowWidth/7 + 'rpx'
  288. });
  289. }
  290. })
  291. },
  292. /**
  293. * 生命周期函数--监听页面初次渲染完成
  294. */
  295. onReady() {
  296. },
  297. /**
  298. * 生命周期函数--监听页面显示
  299. */
  300. onShow() {
  301. },
  302. /**
  303. * 生命周期函数--监听页面隐藏
  304. */
  305. onHide() {
  306. },
  307. /**
  308. * 生命周期函数--监听页面卸载
  309. */
  310. onUnload() {
  311. },
  312. /**
  313. * 页面相关事件处理函数--监听用户下拉动作
  314. */
  315. onPullDownRefresh() {
  316. },
  317. /**
  318. * 页面上拉触底事件的处理函数
  319. */
  320. onReachBottom() {
  321. },
  322. /**
  323. * 用户点击右上角分享
  324. */
  325. onShareAppMessage() {
  326. return {
  327. title: this.data.title||'邀请好友得加油券',
  328. path: "/pages/xx/xx?mobile=" + this.data.tel + '&lx=1&id=klk',
  329. success: function (res) {
  330. },
  331. };
  332. }
  333. })

四、utils相关函数

  1. //utils相关函数
  2. /**
  3. * 判断用户是否登录
  4. */
  5. function isLogin() {
  6. wx.showModal({
  7. title:'提示',
  8. content:'请先登录,然后进行后续操作!',
  9. showCancel: false,
  10. success:function(res) {
  11. if (res.confirm) {
  12. wx.reLaunch({
  13. url:'/pages/index/index'
  14. })
  15. }
  16. }
  17. })
  18. }
  19. //尺寸转换
  20. function rpxToPx(data = 0) {
  21. return ((data * wx.getSystemInfoSync().windowWidth)) / 700
  22. }
  23. module.exports = {
  24. isLogin,
  25. rpxToPx
  26. }

以上就是微信小程序生成海报的过程,本人亲测有效。里面涉及到的图片地址自己替换

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/639657
推荐阅读
相关标签
  

闽ICP备14008679号