index.vue 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <template>
  2. <view>
  3. <view class='poster-poster' v-if="posterStatus">
  4. <view class='poster-pop'>
  5. <image src='../../../static/images/poster-close.png' class='close' @click="posterImageClose"></image>
  6. <view class="user-code">
  7. <image class="canvas" :style="{width:wd+'px', height:hg+'px'}" :src="posterImage" v-if="posterImage"></image>
  8. <canvas class="canvas" :style="{width:wd+'px',height:hg+'px'}" canvas-id="myCanvas" v-else></canvas>
  9. </view>
  10. <!-- #ifndef H5 -->
  11. <view v-if="posterImage" class='save-poster' @click="savePosterPath(posterImage)">保存到手机</view>
  12. <!-- #endif -->
  13. <!-- #ifdef H5 -->
  14. <view v-if="posterImage" class="keep">长按图片可以保存到手机</view>
  15. <!-- #endif -->
  16. </view>
  17. </view>
  18. <view class='mask' v-if="posterImage"></view>
  19. </view>
  20. </template>
  21. <script>
  22. import {
  23. imgToBase
  24. } from '@/api/user.js';
  25. export default {
  26. data() {
  27. return {
  28. wd: 225,
  29. hg: 357,
  30. posterImage: "",
  31. posterBag: '../static/images/poster-bag.png',
  32. }
  33. },
  34. props: {
  35. picData: {
  36. type: Object
  37. },
  38. posterStatus: {
  39. type: Boolean,
  40. default: false
  41. }
  42. },
  43. watch: {
  44. posterStatus(data) {
  45. if (data) {
  46. this.posterShow()
  47. }
  48. },
  49. },
  50. onLoad() {
  51. },
  52. methods: {
  53. async posterShow() {
  54. uni.showLoading({
  55. title: '海报生成中',
  56. mask: true
  57. });
  58. console.log(this.picData)
  59. let arr, bag_pic, goods_img, mp_code
  60. goods_img = await this.imgToBase(this.picData.goodsPic)
  61. mp_code = await this.imgToBase(this.picData.codePic)
  62. console.log(goods_img,mp_code)
  63. // #ifdef H5
  64. arr = [this.posterBag, goods_img, mp_code]
  65. // #endif
  66. // #ifdef MP
  67. arr = [this.posterBag, await this.downloadFilestoreImage(this.picData.goodsPic), await this.downloadFilestoreImage(
  68. this.picData.codePic)]
  69. // #endif
  70. this.bargainPosterCanvas(arr, this.picData.title, this.picData.label, this.picData.msg, this.picData.price,
  71. this.wd,
  72. this.hg,
  73. (tempFilePath) => {
  74. this.posterImage = tempFilePath
  75. });
  76. },
  77. async imgToBase(url) {
  78. let res = await imgToBase({
  79. image: url
  80. })
  81. return res.data.image
  82. },
  83. savePosterPath(url) {
  84. let that = this;
  85. uni.getSetting({
  86. success(res) {
  87. if (!res.authSetting['scope.writePhotosAlbum']) {
  88. uni.authorize({
  89. scope: 'scope.writePhotosAlbum',
  90. success() {
  91. uni.saveImageToPhotosAlbum({
  92. filePath: url,
  93. success: function(res) {
  94. that.$util.Tips({
  95. title: '保存成功',
  96. icon: 'success'
  97. });
  98. },
  99. fail: function(res) {
  100. that.$util.Tips({
  101. title: '保存失败'
  102. });
  103. }
  104. });
  105. }
  106. });
  107. } else {
  108. uni.saveImageToPhotosAlbum({
  109. filePath: url,
  110. success: function(res) {
  111. that.$util.Tips({
  112. title: '保存成功',
  113. icon: 'success'
  114. });
  115. },
  116. fail: function(res) {
  117. that.$util.Tips({
  118. title: '保存失败'
  119. });
  120. }
  121. });
  122. }
  123. }
  124. });
  125. },
  126. posterImageClose() {
  127. this.$emit('update:posterStatus', false)
  128. this.posterImage = ""
  129. },
  130. //图片转符合安全域名路径
  131. downloadFilestoreImage(url) {
  132. // #ifdef MP
  133. let ishttps = url.split('//')[0] == 'https:'
  134. if (!ishttps) {
  135. url = 'https://'+url.split('//')[1]
  136. }
  137. // #endif
  138. return new Promise((resolve, reject) => {
  139. let that = this;
  140. uni.downloadFile({
  141. url: url,
  142. success: function(res) {
  143. resolve(res.tempFilePath);
  144. },
  145. fail: function() {
  146. return that.$util.Tips({
  147. title: ''
  148. });
  149. }
  150. });
  151. })
  152. },
  153. bargainPosterCanvas(arr2, title, label, msg, price, wd, hg, successFn) {
  154. let that = this;
  155. const ctx = uni.createCanvasContext('myCanvas', this);
  156. ctx.clearRect(0, 0, 0, 0);
  157. /**
  158. * 只能获取合法域名下的图片信息,本地调试无法获取
  159. *
  160. */
  161. ctx.fillStyle = '#ccc';
  162. ctx.fillRect(0, 0, wd, hg);
  163. uni.getImageInfo({
  164. src: arr2[0],
  165. success: (res) => {
  166. console.log(arr2)
  167. const WIDTH = res.width;
  168. const HEIGHT = res.height;
  169. console.log(wd, hg)
  170. ctx.drawImage(arr2[0], 0, 0, wd, hg);
  171. // 保证在不同机型对应坐标准确
  172. let labelx = 0.6656 //标签x
  173. let labely = 0.167 //标签y
  174. let pricex = 0.1847 //价格x
  175. let pricey = 0.175 //价格y
  176. let codex = 0.385 //二维码
  177. let codey = 0.77
  178. let picturex = 0.1571 //商品图左上点
  179. let picturey = 0.2916
  180. let picturebx = 0.6857 //商品图右下点
  181. let pictureby = 0.3916
  182. let msgx = 0.1036 //msg
  183. let msgy = 0.2306
  184. ctx.drawImage(arr2[1], wd * picturex, hg * picturey, wd * picturebx, hg * pictureby);
  185. ctx.save();
  186. ctx.drawImage(arr2[2], wd * codex, hg * codey, 55, 55);
  187. ctx.save();
  188. //标题
  189. const CONTENT_ROW_LENGTH = 25;
  190. let [contentLeng, contentArray, contentRows] = that.textByteLength(title, CONTENT_ROW_LENGTH);
  191. if (contentRows > 2) {
  192. contentRows = 2;
  193. let textArray = contentArray.slice(0, 2);
  194. textArray[textArray.length - 1] += '…';
  195. contentArray = textArray;
  196. }
  197. ctx.setTextAlign('left');
  198. ctx.setFillStyle('#000');
  199. if (contentArray.length < 2) {
  200. ctx.setFontSize(16);
  201. } else {
  202. ctx.setFontSize(14);
  203. }
  204. let contentHh = 3;
  205. console.log('222')
  206. for (let m = 0; m < contentArray.length; m++) {
  207. if (m) {
  208. ctx.fillText(contentArray[m], 20, 25 + contentHh * m + 13, 1100);
  209. } else {
  210. ctx.fillText(contentArray[m], 20, 25, 1100);
  211. }
  212. }
  213. // 标签内容
  214. ctx.setTextAlign('left')
  215. ctx.setFontSize(10);
  216. ctx.setFillStyle('#FFF');
  217. ctx.fillText(label, wd * labelx, hg * labely);
  218. ctx.save();
  219. // 价格
  220. ctx.setFillStyle('red');
  221. // ctx.setFontSize(16);
  222. ctx.font = "bold 18px Arial";
  223. ctx.fillText(price, wd * pricex, hg * pricey);
  224. ctx.save();
  225. // msg
  226. ctx.setFontSize(8);
  227. ctx.setFillStyle('#3F3F3F');
  228. ctx.fillText(msg, wd * msgx, hg * msgy);
  229. ctx.save();
  230. ctx.draw(true, () => {
  231. uni.canvasToTempFilePath({
  232. canvasId: 'myCanvas',
  233. fileType: 'png',
  234. quality: 1,
  235. success: (res) => {
  236. console.log(res)
  237. successFn && successFn(res.tempFilePath);
  238. uni.hideLoading();
  239. }
  240. }, this)
  241. });
  242. },
  243. fail: function(err) {
  244. console.log(err)
  245. uni.hideLoading();
  246. that.Tips({
  247. title: '无法获取图片信息'
  248. });
  249. }
  250. })
  251. },
  252. textByteLength(text, num) {
  253. let strLength = 0;
  254. let rows = 1;
  255. let str = 0;
  256. let arr = [];
  257. for (let j = 0; j < text.length; j++) {
  258. if (text.charCodeAt(j) > 255) {
  259. strLength += 2;
  260. if (strLength > rows * num) {
  261. strLength++;
  262. arr.push(text.slice(str, j));
  263. str = j;
  264. rows++;
  265. }
  266. } else {
  267. strLength++;
  268. if (strLength > rows * num) {
  269. arr.push(text.slice(str, j));
  270. str = j;
  271. rows++;
  272. }
  273. }
  274. }
  275. arr.push(text.slice(str, text.length));
  276. return [strLength, arr, rows] // [处理文字的总字节长度,每行显示内容的数组,行数]
  277. },
  278. }
  279. }
  280. </script>
  281. <style>
  282. .poster-poster {
  283. width: 100%;
  284. height: 100%;
  285. width: 450rpx;
  286. height: 714rpx;
  287. }
  288. .poster-pop {
  289. position: fixed;
  290. left: 50%;
  291. transform: translateX(-50%);
  292. top: 50%;
  293. margin: 0 auto;
  294. margin-top: -357rpx;
  295. z-index: 999;
  296. }
  297. .poster-pop image {
  298. width: 100%;
  299. height: 100%;
  300. display: block;
  301. }
  302. .poster-pop .close {
  303. width: 46rpx;
  304. height: 75rpx;
  305. position: fixed;
  306. right: 0;
  307. top: -73rpx;
  308. display: block;
  309. z-index: 3999;
  310. }
  311. .poster-pop .save-poster {
  312. background-color: #df2d0a;
  313. font-size: :22rpx;
  314. color: #fff;
  315. text-align: center;
  316. height: 76rpx;
  317. line-height: 76rpx;
  318. width: 100%;
  319. margin-top: 20rpx;
  320. }
  321. .poster-pop .keep {
  322. color: #fff;
  323. text-align: center;
  324. font-size: 25rpx;
  325. margin-top: 10rpx;
  326. }
  327. .mask {
  328. z-index: 300 !important;
  329. position: fixed;
  330. top: 0;
  331. left: 0;
  332. right: 0;
  333. bottom: 0;
  334. background-color: rgba(0, 0, 0, 0.6);
  335. z-index: 9;
  336. }
  337. </style>