shareQrCode.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. <template>
  2. <view class="container">
  3. <view class="" style="height: 80rpx;">
  4. </view>
  5. <canvas :style="{ width: canvasW + 'px', height: canvasH + 'px',}" canvas-id="myCanvas" id="myCanvas" class="hb"></canvas>
  6. <!-- #ifndef MP -->
  7. <div class="preserve">
  8. <div class="line"></div>
  9. <div class="tip">长按保存图片</div>
  10. <div class="line"></div>
  11. </div>
  12. <!-- #endif -->
  13. <!-- #ifdef MP -->
  14. <view class='keep' @click='saveShareQrcode' v-if="!loading">保存海报</view>
  15. <!-- #endif -->
  16. </view>
  17. </template>
  18. <script>
  19. import {
  20. spreadBanner,
  21. getWxmpInviteQrcode
  22. } from '@/api/user.js';
  23. import {
  24. qrcode
  25. } from '@/api/user.js';
  26. import {
  27. mapState
  28. } from 'vuex';
  29. export default {
  30. // #ifdef MP
  31. onShareAppMessage: function(res) {
  32. // if (res.from === 'button') {
  33. // 保存邀请人
  34. let path = '/pages/index/index?' + 'spread=' + this.userInfo.uid;
  35. console.log('path', path)
  36. let data = {
  37. path: path,
  38. imageUrl: this.poster,
  39. title: this.userInfo.nickname + '邀请您进入母婴界严选'
  40. };
  41. console.log('---data---', data)
  42. return data;
  43. // }
  44. },
  45. // #endif
  46. data() {
  47. return {
  48. bl: 0.95,//画布比例
  49. canvasW: '',
  50. canvasH: '',
  51. bgimg: '',
  52. qrimg: '',
  53. shareList: [],
  54. swiperIndex: 0,
  55. poster: '', // 当前海报
  56. loading: true
  57. }
  58. },
  59. onLoad(option) {
  60. // console.log('---option---',option)
  61. // let path = '/pages/index/index?' + 'spread=' + this.userInfo.uid;
  62. // console.log('path',path)
  63. // if(option.scene){
  64. // // 存储邀请人
  65. // this.spread = opt.pid;
  66. // uni.setStorageSync('spread', opt.pid);
  67. // }
  68. this.loadData();
  69. },
  70. computed: {
  71. ...mapState('user',['userInfo']),
  72. },
  73. methods: {
  74. bindchange(e) {
  75. let shareList = this.shareList;
  76. this.swiperIndex = e.detail.current;
  77. // #ifdef MP
  78. this.poster = shareList[this.swiperIndex].poster;
  79. // #endif
  80. // // #ifndef MP
  81. // this.poster = shareList[this.swiperIndex].wap_poster;
  82. // // #endif
  83. console.log(this.poster)
  84. },
  85. // 保存海报
  86. savePosterPath: function() {
  87. let that = this;
  88. if (that.poster == '') {
  89. // that.poster = that.shareList[0].poster;
  90. that.poster = this.bgimg
  91. }
  92. uni.downloadFile({
  93. url: that.poster,
  94. success(resFile) {
  95. if (resFile.statusCode === 200) {
  96. uni.getSetting({
  97. success(res) {
  98. if (!res.authSetting['scope.writePhotosAlbum']) {
  99. uni.authorize({
  100. scope: 'scope.writePhotosAlbum',
  101. success() {
  102. uni.saveImageToPhotosAlbum({
  103. filePath: resFile.tempFilePath,
  104. success: function(res) {
  105. return that.$api.msg(
  106. '保存成功');
  107. },
  108. fail: function(res) {
  109. return that.$api.msg(res
  110. .errMsg);
  111. },
  112. complete: function(res) {},
  113. })
  114. },
  115. fail() {
  116. uni.showModal({
  117. title: '您已拒绝获取相册权限',
  118. content: '是否进入权限管理,调整授权?',
  119. success(res) {
  120. if (res.confirm) {
  121. uni.openSetting({
  122. success: function(
  123. res) {
  124. console
  125. .log(
  126. res
  127. .authSetting
  128. )
  129. }
  130. });
  131. } else if (res.cancel) {
  132. return that.$api.msg(
  133. '已取消!');
  134. }
  135. }
  136. })
  137. }
  138. })
  139. } else {
  140. uni.saveImageToPhotosAlbum({
  141. filePath: resFile.tempFilePath,
  142. success: function(res) {
  143. return that.$api.msg('保存成功');
  144. },
  145. fail: function(res) {
  146. return that.$api.msg(res.errMsg);
  147. },
  148. complete: function(res) {},
  149. })
  150. }
  151. },
  152. fail(res) {
  153. }
  154. })
  155. } else {
  156. return that.$api.msg(resFile.errMsg);
  157. }
  158. },
  159. fail(res) {
  160. return that.$api.msg(res.errMsg);
  161. }
  162. })
  163. },
  164. // #ifdef MP-WEIXIN
  165. // 保存画图图片到本地
  166. seav(url) {
  167. uni.showLoading({
  168. title: '生成中...',
  169. mask: true
  170. });
  171. uni.saveImageToPhotosAlbum({
  172. filePath: this.poster,
  173. complete(result) {
  174. uni.hideLoading();
  175. console.log(result);
  176. uni.showToast({
  177. title: '保存图片成功!',
  178. duration: 2000,
  179. icon: 'none'
  180. });
  181. }
  182. });
  183. },
  184. // #endif
  185. // 获取海报
  186. loadData() {
  187. let obj = this;
  188. uni.showLoading({
  189. title: '获取中',
  190. mask: true,
  191. });
  192. // spreadBanner({
  193. // // #ifdef H5
  194. // type: 2,
  195. // // #endif
  196. // // #ifdef MP
  197. // type: 1
  198. // // #endif
  199. // }).then(res =>{
  200. // uni.hideLoading();
  201. // obj.shareList = res.data;
  202. // console.log('obj.shareList',obj.shareList);
  203. // }).catch(err => {
  204. // uni.hideLoading();
  205. // });
  206. getWxmpInviteQrcode().then(res => {
  207. console.log(res)
  208. obj.bgimg = res.data.bgimg
  209. obj.qrcode = res.data.qrcode
  210. uni.hideLoading();
  211. obj.createPoster()
  212. })
  213. },
  214. async createPoster() {
  215. let that = this
  216. // 获取设备信息,主要获取宽度,赋值给canvasW 也就是宽度:100%
  217. this.SystemInfo = await this.getSystemInfo();
  218. // 获取商品主图,二维码信息,APP端会返回图片的本地路径(H5端只能返回原路径)
  219. this.goodsImg = await this.getImageInfo(that.bgimg);
  220. this.ewmImg = await this.getImageInfo(that.qrcode);
  221. this.canvasW = this.SystemInfo.windowWidth * that.bl; // 画布宽度
  222. this.ratio = this.SystemInfo.windowWidth / 750;
  223. let x = 750*this.goodsImg.height/this.goodsImg.width
  224. // this.canvasW =750 * this.ratio;
  225. this.canvasH = x * this.ratio * that.bl;
  226. this.ewmW = 220 * this.ratio;
  227. console.log(this.canvasH, 'this.canvasH')
  228. // this.canvasH = this.goodsImg.height + this.ewmW + 200; // 画布高度 = 主图高度+二维码高度 + 文字图片的间距(大概50)
  229. // 如果主图,二维码图片,设备信息都获取成功,开始绘制海报,这里需要用setTimeout延时绘制,否则可能会出现图片不显示。
  230. if (this.goodsImg.errMsg == 'getImageInfo:ok' && this.ewmImg.errMsg == 'getImageInfo:ok' && this
  231. .SystemInfo.errMsg == 'getSystemInfo:ok') {
  232. console.log('ok')
  233. uni.showToast({
  234. icon: 'loading',
  235. mask: true,
  236. duration: 10000,
  237. title: '海报绘制中',
  238. });
  239. setTimeout(() => {
  240. var ctx = uni.createCanvasContext('myCanvas', this);
  241. // 填充背景色,白色
  242. ctx.setFillStyle('#fff'); // 默认白色
  243. ctx.fillRect(0, 0, this.canvasW, this.canvasH) // fillRect(x,y,宽度,高度)
  244. // 绘制商品主图,二维码
  245. ctx.drawImage(this.goodsImg.path, 0, 0, this.canvasW, this.canvasH) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
  246. // ctx.drawImage(this.ewmImg.path, (this.canvasW / 2 - this.ewmW / 2),this.canvasH - 85*this.ratio - this.ewmW, this.ewmW, this.ewmW) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度,二维码的宽,高)
  247. ctx.drawImage(this.ewmImg.path,40*this.ratio,this.canvasH - 50*this.ratio - this.ewmW, this.ewmW, this.ewmW)
  248. // 3、绘制商品标题,多余文字自动换行
  249. ctx.setFontSize(16); // setFontSize() 设置字体字号
  250. ctx.setFillStyle('#555'); // setFillStyle() 设置字体颜色
  251. let name = this.userInfo.nickname
  252. let len = 8
  253. if(name.length > len) {
  254. name = name.substr(0,len) + '...'
  255. }
  256. ctx .fillText(name, 100*this.ratio + this.ewmW,this.canvasH- this.ewmW/2 - 80*this.ratio)
  257. ctx .fillText('邀请您加入母婴严选', 100*this.ratio + this.ewmW,this.canvasH- this.ewmW/2 -16*this.ratio)
  258. ctx.draw(false, (ret) => { // draw方法 把以上内容画到 canvas 中。
  259. console.log(ret)
  260. uni.showToast({
  261. icon: 'none',
  262. title: '生成成功!',
  263. });
  264. that.loading = false
  265. that.fina = true
  266. uni.canvasToTempFilePath({ // 保存canvas为图片
  267. canvasId: 'myCanvas',
  268. quality: 1,
  269. fileType: 'jpg',
  270. complete: function(res) {
  271. // 在H5平台下,tempFilePath 为 base64, // 图片提示跨域 H5保存base64失败,APP端正常输出临时路径
  272. console.log(res)
  273. that.canvasShow = false
  274. that.shareQrcodeUrl = res.tempFilePath
  275. that.$forceUpdate()
  276. setTimeout(function() {
  277. console.log(that.shareQrcodeUrl, that
  278. .canvasShow)
  279. }, 2000)
  280. },
  281. })
  282. });
  283. }, 1500)
  284. } else {
  285. console.log('err')
  286. }
  287. },
  288. // 获取设备信息
  289. getSystemInfo() {
  290. return new Promise((req, rej) => {
  291. uni.getSystemInfo({
  292. success: function(res) {
  293. req(res)
  294. }
  295. });
  296. })
  297. },
  298. // 获取图片信息
  299. getImageInfo(image) {
  300. return new Promise((req, rej) => {
  301. uni.getImageInfo({
  302. src: image,
  303. success: function(res) {
  304. req(res)
  305. },
  306. });
  307. })
  308. },
  309. //保存图片
  310. saveShareQrcode() {
  311. console.log(this.shareQrcodeUrl)
  312. uni.saveImageToPhotosAlbum({
  313. filePath: this.shareQrcodeUrl,
  314. success: (res) => {
  315. uni.showToast({
  316. icon: 'none',
  317. position: 'bottom',
  318. title: "成功保存到相册",
  319. });
  320. },
  321. fail: (err) => {
  322. //重新提示用户打开保存图片的授权
  323. if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
  324. uni.showModal({
  325. title: '提示',
  326. content: '需要您授权保存相册',
  327. showCancel: false,
  328. success(res) {
  329. if (res.confirm) {
  330. uni.openSetting({
  331. success(settingdata) {
  332. if (settingdata.authSetting[
  333. 'scope.writePhotosAlbum']) {
  334. uni.showModal({
  335. title: '提示',
  336. content: '获取权限成功,再次保存图片即可成功',
  337. showCancel: false,
  338. })
  339. } else {
  340. uni.showModal({
  341. title: '提示',
  342. content: '获取权限失败,无法保存到相册',
  343. showCancel: false
  344. })
  345. }
  346. }
  347. })
  348. }
  349. }
  350. })
  351. }
  352. },
  353. })
  354. }
  355. }
  356. }
  357. </script>
  358. <style lang="scss">
  359. page {
  360. background: #a3a3a3;
  361. height: 100%;
  362. }
  363. .container {
  364. width: 100%;
  365. padding-bottom: 100rpx;
  366. .posters-box {
  367. width: 100%;
  368. height: 1000rpx;
  369. margin-top: 40rpx;
  370. .slide-image {
  371. width: 100%;
  372. height: 100%;
  373. border-radius: 15rpx;
  374. }
  375. }
  376. .posters-box .slide-image.active {
  377. transform: none;
  378. transition: all 0.2s ease-in 0s;
  379. }
  380. .posters-box .slide-image.quiet {
  381. transform: scale(0.8333333);
  382. transition: all 0.2s ease-in 0s;
  383. }
  384. .keep {
  385. font-size: 30rpx;
  386. background: $base-color;
  387. color: #fff;
  388. width: 750rpx;
  389. position: fixed;
  390. height: 100rpx;
  391. text-align: center;
  392. line-height: 100rpx;
  393. bottom: 0;
  394. left: 0;
  395. }
  396. }
  397. .preserve {
  398. color: #fff;
  399. text-align: center;
  400. margin-top: 38rpx;
  401. display: flex;
  402. align-items: center;
  403. justify-content: center;
  404. .line {
  405. width: 100rpx;
  406. height: 1px;
  407. background-color: #fff;
  408. }
  409. .tip {
  410. margin: 0 20rpx;
  411. font-size: 28rpx;
  412. }
  413. }
  414. .hb {
  415. margin: auto;
  416. border-radius: 20rpx;
  417. overflow: hidden;
  418. }
  419. </style>