当前位置:   article > 正文

小程序-uni-app:将页面(html+css)生成图片/海报/名片,进行下载 保存到手机_uniapp页面生成图片

uniapp页面生成图片

一、需要描述

本文实现,uniapp微信小程序,把页面内容保存为图片,并且下载到手机上。
说实话网上找了很多资料,但是效果不理想,直到看了一个开源项目,我知道可以实现了。
本文以开源项目uniapp-wxml-to-canvas 为蓝本 记录集成的步骤,以供参考。
详细内容可以下载并启动 uniapp-wxml-to-canvas项目,详细学习。

GitHub - ThaneYang/uniapp-wxml-to-canvas

二、代码实现

2.1、wxcomponents目录

将”开源项目“的这两个目录及包含的文件复制到自己项目的同名目录下。

2.2、pages.json

在pages.json文件,globalStyle 配置 usingComponents

  1. globalStyle: {
  2. "usingComponents": {
  3. "wxml-to-canvas": "/wxcomponents/wxml-to-canvas/index"
  4. }
  5. }

2.3、utils/DomData.js

wxml 定义html

style 定义样式

  1. /**
  2. *
  3. *
  4. * @param {*} number 第几位
  5. * @param {*} src 名片头像
  6. * @param {*} name 名片名字
  7. * @param {*} qrCodeUrl 小程序codeURL图片
  8. */
  9. /**
  10. 下边的内容可以自己定义,这样就可以定制属于自己的海报了
  11. */
  12. const wxml = (name, pic, c1, c2) =>`
  13. <view class="container">
  14. <image src="`+pic+`" class="pic"/>
  15. <text class="name">`+ name +`</text>
  16. <text class="content">`+ c1 +`</text>
  17. <text class="content">`+ c2 +`</text>
  18. <view class="bottom">
  19. <image src="`+pic+`" class="qr"/>
  20. <text class="msg">扫码一起加入学习吧</text>
  21. </view>
  22. </view>
  23. `
  24. /**
  25. *
  26. *
  27. * @param {*} screenWidth 屏幕宽度
  28. * @param {*} canvasWidth 画布宽度
  29. * @param {*} canvasHeight 画布高度
  30. * @param {*} numberWidth 数字宽度,动态设置
  31. * @return {*}
  32. */
  33. const style = (screenWidth, canvasWidth, canvasHeight) => {
  34. return {
  35. "container": {
  36. width: canvasWidth,
  37. height: canvasHeight,
  38. position: 'relative',
  39. overflow: 'hidden',
  40. backgroundColor: '#ffffff',
  41. },
  42. "name":{
  43. fontSize: 20,
  44. color: '#333',
  45. marginLeft: canvasWidth * 0.08,
  46. width: canvasWidth * 0.84,
  47. height: screenWidth * 0.18,
  48. textAlign: 'center',
  49. },
  50. "content": {
  51. fontSize: 14,
  52. color: '#333',
  53. width: canvasWidth * 0.84,
  54. height: screenWidth * 0.15,
  55. marginLeft: canvasWidth * 0.08,
  56. },
  57. "pic": {
  58. width: canvasWidth * 0.3,
  59. height: screenWidth * 0.28,
  60. marginTop: canvasWidth * 0.1,
  61. marginLeft: canvasWidth * 0.35,
  62. marginBottom: canvasWidth * 0.05,
  63. borderRadius: screenWidth * 0.14,
  64. overflow: 'hidden',
  65. },
  66. "bottom":{
  67. width: canvasWidth,
  68. height: screenWidth * 0.2,
  69. flexDirection: 'row',
  70. justifyContent: 'self-start',
  71. alignItems: 'center',
  72. backgroundColor: '#fafafa',
  73. position: 'absolute',
  74. bottom: 0,
  75. left: 0,
  76. },
  77. "qr": {
  78. width: canvasWidth * 0.14,
  79. height: screenWidth * 0.14,
  80. marginLeft: canvasWidth * 0.04,
  81. marginRight: canvasWidth * 0.04,
  82. },
  83. "msg": {
  84. fontSize: 14,
  85. color: '#a1a1a1',
  86. width: canvasWidth * 0.74,
  87. height: 14,
  88. textAlign: 'left'
  89. },
  90. }
  91. }
  92. module.exports = {
  93. wxml,
  94. style
  95. }

2.4、业务页面

  1. <template>
  2. <view class="share-page">
  3. <view class="share-page-box" id="box" v-if="show" :style="{width: canvasWidth + 'px', height: canvasHeight + 'px' }">
  4. <wxml-to-canvas class="widget" :width="canvasWidth" :height="canvasHeight"></wxml-to-canvas>
  5. </view>
  6. <view class="share-page-box msg-box" v-else :style="{width: canvasWidth + 'px', height: canvasHeight + 'px' }">
  7. {{msg}}
  8. </view>
  9. <view class="share-page-btn" @tap="extraImage">
  10. <button class="btn-big" :style="getBtnStyle">保存图片</button>
  11. </view>
  12. </view>
  13. </template>
  14. <script>
  15. const { wxml, style } = require('@/utils/DomData.js')
  16. export default {
  17. name: '',
  18. data () {
  19. return {
  20. show: false, // 是否显示canvas
  21. canvasWidth: 320, // 默认canvas宽高
  22. canvasHeight: 480,
  23. screenWidth: null, // 设备宽度
  24. name: '',
  25. pic: '',
  26. chapter1: '',
  27. chapter2: '',
  28. widget: null,
  29. msg: '加载中,请稍等...', // 提示语
  30. }
  31. },
  32. onLoad (options) {
  33. console.log('options', options);
  34. this.name = 'Willam Yang'
  35. this.pic = 'https://pic1.zhimg.com/80/v2-58fe538a59f870407b1435bfd45893ed_720w.jpeg'
  36. this.chapter1 = '第一段'
  37. this.chapter2 = '第二段'
  38. // 获取设备信息
  39. wx.getSystemInfo({
  40. success: (res) =>{
  41. this.screenWidth = res.screenWidth
  42. this.canvasWidth = this.screenWidth * 0.9
  43. this.canvasHeight = this.screenWidth * 1.1
  44. console.log('screenWidth', this.screenWidth)
  45. this.show = true
  46. // 数字容器宽度 动态设置
  47. setTimeout(() => {
  48. wx.showLoading({title: '海报生成中...'})
  49. this.widget = this.selectComponent('.widget')
  50. this.renderToCanvas()
  51. }, 1000)
  52. }
  53. });
  54. },
  55. methods: {
  56. // wxml 转 canvas
  57. renderToCanvas () {
  58. console.log('this.widget', this.widget)
  59. const _wxml = wxml(this.name, this.pic, this.chapter1, this.chapter2)
  60. const _style = style(this.screenWidth, this.canvasWidth, this.canvasHeight)
  61. const p1 = this.widget.renderToCanvas({ wxml: _wxml, style: _style })
  62. p1.then((res) => {
  63. console.log('海报生成成功');
  64. wx.hideLoading()
  65. // this.container = res
  66. }).catch((err) => {
  67. console.log('生成失败')
  68. })
  69. },
  70. // 保存到朋友圈
  71. extraImage() {
  72. if (!this.show) {
  73. wx.showToast({title: '海报生成失败,无法分享到朋友圈', icon: 'none'})
  74. return
  75. }
  76. const p2 = this.widget.canvasToTempFilePath()
  77. let that = this
  78. p2.then(result => {
  79. let path = result.tempFilePath
  80. wx.getSetting({
  81. success: res => {
  82. // 非初始化且未授权的情况,需要再次弹窗提示授权
  83. if (res.authSetting['scope.writePhotosAlbum'] != undefined && res.authSetting['scope.writePhotosAlbum'] != true) {
  84. wx.showModal({
  85. title: '是否授权相册权限',
  86. content: '需要获取相册权限,请确认授权,否则无法使用相关功能',
  87. success: res => {
  88. if (res.confirm) {
  89. wx.openSetting({
  90. success: dataAu => {
  91. if (dataAu.authSetting["scope.writePhotosAlbum"] == true) {
  92. wx.showToast({
  93. title: '授权成功',
  94. icon: 'none',
  95. duration: 1000
  96. });
  97. that.saveIMg(path);
  98. } else {
  99. wx.showToast({
  100. title: '授权失败',
  101. icon: 'success',
  102. duration: 1000
  103. });
  104. }
  105. }
  106. });
  107. }
  108. }
  109. });
  110. } else {
  111. // 初始化且未授权,系统默认会弹窗提示授权
  112. // 非初始化且已授权,也会进入这里
  113. that.saveIMg(path);
  114. }
  115. }
  116. });
  117. })
  118. },
  119. // 保存到相册
  120. async saveIMg (tempFilePath) {
  121. wx.saveImageToPhotosAlbum({
  122. filePath: tempFilePath,
  123. success: async (res) => {
  124. wx.showModal({
  125. content: '图片已保存,分享给好友吧!',
  126. showCancel: false,
  127. confirmText: '好的',
  128. confirmColor: '#333',
  129. success: function (res) {
  130. wx.navigateBack({
  131. //返回
  132. delta: 1
  133. });
  134. },
  135. fail: function (res) {
  136. console.log('res', res);
  137. }
  138. });
  139. },
  140. fail: function (res) {
  141. wx.showToast({
  142. title: '您取消了授权',
  143. icon: 'none',
  144. duration: 2000
  145. })
  146. }
  147. });
  148. }
  149. }
  150. }
  151. </script>
  152. <style lang="scss" scoped>
  153. .share-page {
  154. background: #fff;
  155. position: relative;
  156. overflow: hidden;
  157. min-height: 100vh;
  158. .msg-box {
  159. display: flex;
  160. align-items: center;
  161. text-align: center;
  162. justify-content: center;
  163. }
  164. .share-page-box {
  165. margin: 40rpx auto;
  166. position: relative;
  167. overflow: hidden;
  168. box-shadow: 0rpx 6rpx 20rpx 6rpx rgba(0, 0, 0, 0.2);
  169. }
  170. .share-page-btn {
  171. margin: 0 40rpx 50rpx;
  172. img {
  173. width: 100%;
  174. height: 100%;
  175. }
  176. }
  177. }
  178. </style>

到此功能实现,集成步骤也比较简单,

三、过程记录

3.1、小程序 wxcomponents 目录干啥的

小程序的 wxcomponents 目录一般用来放置自定义组件或第三方组件。这些组件可以在小程序中多次使用,提高代码的复用性和开发效率。在这个目录下的组件包括两种类型: 

1.  小程序官方提供的基础组件库,比如 button、 swiper 等;
2.  开发者自定义的组件,比如自定义图标、模板、模态框等。

这些组件可以通过 require 方法引入并使用,也可以在页面的 json 配置文件中进行全局注册,被所有页面调用。通过创建自定义组件,可以让开发者更加方便地完成复杂的交互效果和组件封装,从而提高小程序的可维护性和开发效率。

3.2、微信小程序selectComponent返回null的问题排查与分析

微信小程序selectComponent返回null的问题排查与分析-CSDN博客

四、欢迎交流指正

五、参考连接

微信小程序插件--wxml-to-canvas(生成图片)_微信小程序生成海报插件-CSDN博客

【微信小程序】解决canvas组件层级最高问题_微信小程序canvas层级_大大。的博客-CSDN博客

用小程序·云开发打造功能全面的博客小程序丨实战 - 知乎

wxa-plugin-canvas-语言吧

浅谈html2canvas实现浏览器截图的原理_invalid element provided as first argument-CSDN博客

GitHub - ThaneYang/uniapp-wxml-to-canvas

uniapp 微信小程序 实现 将base64图片保存相册和转发分享微信好友功能记录 直接cv就能用!!!!_uniapp分享图片到微信_柑橘乌云_的博客-CSDN博客

uni-app小程序生成海报wxml-to-canvas_西瓜霜的技术博客_51CTO博客

uniapp 、微信小程序使用canvas生成海报 - 知乎

uni.canvasToTempFilePath(object, component) | uni-app官网

uni-app 微信小程序如何把图片保存到本地相册? · 杂记 · 看云

html2canvas简单使用 - 简书

Painter: 小程序生成海报组件,非常好用,json配置,一下生成

微信小程序实现生成分享海报案例_微信小程序生成海报-CSDN博客

uniapp中使用html2canvas做H5端的海报生成功能 - 简书

uni-app 中使用 html2canvas 生成图片(支持多端)_uniapp html2canvas_不想搬砖。的博客-CSDN博客

uni-app APP、html引入html2canvas截图以及截长图_html2canvas npm-CSDN博客

uni-app 中使用 html2canvas 生成图片(支持多端)_uniapp html2canvas_不想搬砖。的博客-CSDN博客

小程序页面生成图片保存分享——笔记 - 简书

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

闽ICP备14008679号