耀实惠小程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

307 lines
10 KiB

2 years ago
  1. <template>
  2. <view class="pages">
  3. <!-- 海报 -->
  4. <view class="">
  5. <canvas :style="{ width: canvasW + 'px', height: canvasH + 'px' }" canvas-id="myCanvas" id="myCanvas"></canvas>
  6. </view>
  7. <!-- 按钮生成图片 -->
  8. <cover-view class="btn flex align-center justify-center" @click="saveImg_btn">
  9. <button class="btn_save">{{tbn_text}}</button>
  10. </cover-view>
  11. </view>
  12. </template>
  13. <script>
  14. import {
  15. IMG_URL_SHARE,
  16. IMG_URL
  17. } from '@/env.js';
  18. export default {
  19. data() {
  20. return {
  21. IMG_URL_SHARE, //图片二维码主路径
  22. IMG_URL, // 正常商品图片路径
  23. tbn_text: '保存图片',
  24. canvasW: 0, // 画布宽
  25. canvasH: 0, // 画布高
  26. SystemInfo: {}, // 设备信息
  27. goodsId: '', // 商品id 用于请求二维码
  28. pageTitleImg: 'goods/share_title.png', //页面内容标题的图片
  29. pageTitleImgH: 0, //页面内容标题的图片高度
  30. pagesTitle: "", //页面内容标题
  31. goodsImg: '', // 商品主图
  32. goodsImgH: 0, //商品主图高度
  33. ewmImg: '', // 二维码图片
  34. ewmImgH: 0, //二维码图片高度
  35. ewmW: 120, // 二维码大小
  36. title: '', // 商品标题
  37. price: '', // 价格
  38. Oldprice: '', // 原价
  39. name: '', // 推荐人
  40. nameURL: '', // 推荐人头像
  41. nameURLW: 0, // 推荐人头像宽度
  42. nameURLH: 0, // 推荐人头像高度
  43. alt: '', //推荐语,
  44. price_new: '', //本网价
  45. price_old: "", //市价
  46. SystemInfo:null, // 设备信息
  47. }
  48. },
  49. async onLoad(option) {
  50. uni.showToast({
  51. icon: 'loading',
  52. mask: true,
  53. duration: 10000,
  54. title: '海报绘制中',
  55. });
  56. this.getSystemInfo().then(res => {
  57. // console.log(res, "设备信息");
  58. this.SystemInfo = res;
  59. });
  60. this.SystemInfo = uni.getSystemInfoSync()
  61. // 商品信息
  62. const goodsInfo = JSON.parse(decodeURIComponent(option.goodsInfo));
  63. const shareInfo = JSON.parse(decodeURIComponent(option.shareInfo));
  64. // console.log(goodsInfo, '商品信息')
  65. // 用户信息
  66. this.userInfo = uni.getStorageSync("__user_info");
  67. // console.log(this.userInfo, "userINfo")
  68. this.nameURL = this.userInfo.headUrl; // 推荐人头像
  69. this.name = this.userInfo.nickName; // 推荐人姓名
  70. this.goodsImg = goodsInfo.pic[0]; // 商品图片
  71. this.goodsId = goodsInfo.id; // 商品id
  72. this.price = goodsInfo.payMoney // 价格
  73. this.Oldprice = goodsInfo.price // 原价
  74. this.title = `${goodsInfo.subTitle}${goodsInfo.title}` // 商品标题
  75. // 获取推荐信息
  76. this.alt = shareInfo.alt;
  77. this.pagesTitle = shareInfo.title;
  78. this.ewmImg = shareInfo.img
  79. //页面标题图片
  80. const pageTitleImgH = await this.getImageInfo(this.IMG_URL + this.pageTitleImg);
  81. this.pageTitleImgH = pageTitleImgH.height / 2;
  82. // 推荐人头像
  83. const nameURLH = await this.getImageInfo(this.nameURL);
  84. // console.log(nameURLH, "toxxzczx")
  85. this.nameURLW = nameURLH.width / 2
  86. this.nameURLH = nameURLH.height / 2;
  87. // 商品主图高度
  88. // console.log(this.goodsImg, '商品主图高度')
  89. const goodsImgH = await this.getImageInfo(this.goodsImg);
  90. this.goodsImgH = goodsImgH.height / 2;
  91. // 二维码图片高度
  92. const ewmImgH = await this.getImageInfo(this.IMG_URL_SHARE+this.ewmImg);
  93. this.ewmImgH = ewmImgH.height/ 2;
  94. // 获取文字的宽度 本网价
  95. this.price_new = '本网价' + this.price + "元"
  96. this.price_old = '市场价' + this.Oldprice + "元"
  97. // const price_new = await this.getImageInfo(this.price_new);
  98. // const price_newW = price_new.width
  99. // 设置画布的宽高
  100. this.canvasW = this.SystemInfo.windowWidth; // 画布宽度等于设备宽度
  101. // nameURLH.height
  102. this.canvasH = (+ goodsImgH.height + pageTitleImgH.height + ewmImgH.height + 90 + 120) /
  103. 2; // 画布高度 = 推荐人头像高度 主图高度 + 页面标题高度 +二维码高度 + 文字图片的间距(大概50 不止等会调整)+ 于底部的距离
  104. // this.canvasH = goodsImgH.height + pageTitleImgH.height + ewmImgH.height+ ewmImgH.height + 50; // 画布高度 = 主图高度 + 页面标题高度 +二维码高度 + 文字图片的间距(大概50 不止等会调整)
  105. // 开始画画
  106. if(goodsImgH.errMsg == 'getImageInfo:ok'
  107. && pageTitleImgH.errMsg == 'getImageInfo:ok'
  108. && ewmImgH.errMsg == 'getImageInfo:ok'
  109. && this.SystemInfo){
  110. setTimeout(() => {
  111. var ctx = uni.createCanvasContext('myCanvas', this);
  112. // 填充背景色,白色
  113. ctx.setFillStyle('#fff'); // 默认白色
  114. ctx.fillRect(0, 0, this.canvasW, this.canvasH) // fillRect(x,y,宽度,高度)
  115. // ctx.fillRect(0, 0, this.canvasW, ) // fillRect(x,y,宽度,高度)
  116. // 绘制页面标题主图
  117. ctx.drawImage(pageTitleImgH.path, 0, 0, this.canvasW, this.pageTitleImgH) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
  118. // 绘制页面标题文字
  119. ctx.setFontSize(16) // 字号
  120. ctx.setFillStyle('#fff') // 颜色
  121. ctx.font = 'normal bold 18px sans-serif'
  122. ctx.fillText(this.pagesTitle, 120, 32); // (文字,x,y)
  123. ctx.font = 'normal 18px sans-serif'
  124. // 绘制 用户头像
  125. // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
  126. ctx.drawImage(nameURLH.path, 17.5, this.pageTitleImgH + 7, this.nameURLW, this.nameURLH)
  127. // ctx.arc(图片宽度+图片X,图片高度+图片Y, 图片宽,0, Math.PI * 2, false) 画圆 clip()裁切
  128. // ctx.arc( 17.5, 7 + this.pageTitleImgH, this.nameURLW/2, 0, Math.PI * 2, false);
  129. // ctx.clip();
  130. // 绘制 文字
  131. ctx.setFontSize(14)
  132. ctx.setFillStyle('#000')
  133. ctx.fillText('我是 ' + this.name, this.nameURLW + 20, this.nameURLH + 12);
  134. // 绘制 文字
  135. ctx.setFontSize(13)
  136. ctx.setFillStyle('#707070')
  137. ctx.fillText(this.alt, this.nameURLW + 20, this.nameURLH + 30 + 12);
  138. // 绘制商品主图
  139. ctx.drawImage(goodsImgH.path, 0, this.pageTitleImgH + this.nameURLH + 17, this.canvasW, this.goodsImgH) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
  140. //4、商品价格
  141. ctx.setFontSize(18) // 字号
  142. ctx.setFillStyle('#DB0618') // 颜色
  143. ctx.fillText(this.price_new, 10, this.pageTitleImgH + this.nameURLH + 34 + this.goodsImgH +10 + 30); // (文字,x,y)
  144. // 价格划横线
  145. ctx.beginPath()
  146. const text_w = ctx.measureText('市场价' + this.Oldprice + "元").width + 30
  147. ctx.setFontSize(12)
  148. ctx.setFillStyle('#707070')
  149. ctx.fillText('市场价' + this.Oldprice + "元", (this.price_new.length+1)*12 + 10+20, this.pageTitleImgH + this.nameURLH + 34 + this.goodsImgH +10 +30);
  150. ctx.rect((this.price_new.length+1)*12 + 10+20, this.pageTitleImgH + this.nameURLH + 28.5 + this.goodsImgH +10 +30, this.price_old.length * 9 , 1)
  151. ctx.fill()
  152. ctx.closePath()
  153. // 3、绘制商品标题,多余文字自动换行
  154. ctx.setFontSize(16); // setFontSize() 设置字体字号
  155. ctx.setFillStyle('#333'); // setFillStyle() 设置字体颜色
  156. /* str 这段代码是我百度找的,参考别人的。canvas不能自动换行,需要自行计算 */
  157. let _strlineW = 0;
  158. let _strLastIndex = 0; //每次开始截取的字符串的索引
  159. let _strHeight = this.pageTitleImgH + this.nameURLH +34 + this.goodsImgH +
  160. 25 +10 +30; //绘制字体距离canvas顶部的初始高度
  161. let _num = 1;
  162. for (let i = 0; i < this.title.length; i++) {
  163. _strlineW += ctx.measureText(this.title[i]).width;
  164. if (_strlineW > this.canvasW - 155) {
  165. if (_num == 2 && 2) {
  166. //文字换行数量大于二进行省略号处理
  167. ctx.fillText(this.title.substring(_strLastIndex, i - 5) + '...', 10, _strHeight);
  168. _strlineW = 0;
  169. _strLastIndex = i;
  170. _num++;
  171. break;
  172. } else {
  173. ctx.fillText(this.title.substring(_strLastIndex, i), 10, _strHeight);
  174. _strlineW = 0;
  175. _strHeight += 20;
  176. _strLastIndex = i;
  177. _num++;
  178. }
  179. } else if (i == this.title.length - 1) {
  180. ctx.fillText(this.title.substring(_strLastIndex, i + 1), 10, _strHeight);
  181. _strlineW = 0;
  182. }
  183. }
  184. // 绘制 二维码
  185. // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
  186. ctx.drawImage(ewmImgH.path, uni.upx2px(530), this.pageTitleImgH + this.nameURLH + uni.upx2px(58) + this.goodsImgH, ewmImgH.width/3, ewmImgH.height/3)
  187. ctx.draw(true, () => { // draw方法 把以上内容画到 canvas 中。
  188. // console.log(ret,12311123132)
  189. uni.showToast({
  190. icon: 'success',
  191. mask: true,
  192. title: '绘制完成',
  193. });
  194. }, this);
  195. }, 1500)
  196. }else{
  197. this.$Toast('海报生成失败')
  198. }
  199. },
  200. methods: {
  201. // 获取设备信息
  202. getSystemInfo() {
  203. return new Promise((req, rej) => {
  204. uni.getSystemInfo({
  205. success: function(res) {
  206. req(res)
  207. }
  208. });
  209. })
  210. },
  211. // 获取图片的高度
  212. getImageInfo(image) {
  213. // console.log(image)
  214. return new Promise((req, rej) => {
  215. uni.getImageInfo({
  216. src: image,
  217. success: function(res) {
  218. req(res)
  219. },
  220. });
  221. })
  222. },
  223. // 保存图片
  224. saveImg_btn() {
  225. var that = this
  226. uni.canvasToTempFilePath({
  227. canvasId: 'myCanvas',
  228. // width: this.width * 3,
  229. // height: this.height * 3,
  230. // destWidth: this.width * 3,
  231. // destHeight: this.height * 3,
  232. quality: 1,
  233. complete: (res) => {
  234. // console.log('保存到相册', res);
  235. uni.saveImageToPhotosAlbum({
  236. filePath: res.tempFilePath,
  237. success(res) {
  238. uni.showToast({
  239. title: '已保存到相册',
  240. icon: 'success',
  241. duration: 2000
  242. })
  243. setTimeout(() => {
  244. that.isShow = false
  245. }, 2000)
  246. }
  247. })
  248. }
  249. }, this);
  250. }
  251. }
  252. }
  253. </script>
  254. <style scoped lang="scss">
  255. .pages {
  256. width: 100%;
  257. height: 100%;
  258. background-color: #F5F5F5;
  259. padding-bottom: 129rpx;
  260. // 按钮
  261. .btn {
  262. position: fixed;
  263. bottom: 0;
  264. display: flex;
  265. width: 100%;
  266. height: 129rpx;
  267. margin-top: 15rpx;
  268. background-color: #fff;
  269. display: flex;
  270. justify-content: center;
  271. align-items: center;
  272. .btn_save {
  273. display: flex;
  274. justify-content: center;
  275. align-items: center;
  276. background-color: #01AEEA;
  277. display: block;
  278. width: 591rpx;
  279. height: 88rpx;
  280. border-radius: 38rpx;
  281. color: #fff;
  282. font-size: 36rpx;
  283. }
  284. }
  285. }
  286. </style>