宜轩到家/服务到家第三版,换个颜色
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.

276 lines
8.2 KiB

7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
7 months ago
  1. <template>
  2. <view class="placard">
  3. <view class="placard-content">
  4. <view class="img-box" :style="{ width: canvasW + 'px', height: canvasH + 'px' }">
  5. <img v-show="tempFilePath" :style="{ width: canvasW + 'px', height: canvasH + 'px' }" :src="tempFilePath" alt="" />
  6. </view>
  7. <div class="qrcode" style="display: none;">
  8. <vue-qrcode :value="qrCodeValue" :width="qrCodeSize"
  9. :color="{ dark: qrCodeDarkColor, light: qrCodeLightColor }" :margin="margin"
  10. type="image/png"></vue-qrcode>
  11. </div>
  12. <canvas :style="{ width: canvasW + 'px', height: canvasH + 'px' }"
  13. canvas-id="myCanvas" id="myCanvas"></canvas>
  14. <view class="add-btn">
  15. <view class="btn">
  16. 长按图片保存到手机
  17. </view>
  18. </view>
  19. </view>
  20. </view>
  21. </template>
  22. <script>
  23. import drawTextVertical from '@/utils/Canvas.js'
  24. import VueQrcode from 'vue-qrcode'
  25. export default {
  26. name: 'Placard',
  27. components : { VueQrcode },
  28. props : ['userInfo'],
  29. data() {
  30. return {
  31. qrCodeValue: import.meta.env.VITE_REDIRECT_URI + `?vid=${this.getUserInfo()}`,
  32. qrCodeSize: 180 * (window.innerWidth / 750),
  33. qrCodeDarkColor: '#000',
  34. qrCodeLightColor: '#fff',
  35. margin: 0,
  36. //画布信息
  37. canvasW: 299,
  38. canvasH: 403,
  39. //设备信息
  40. systemInfo: {},
  41. //图片路径
  42. tempFilePath: '',
  43. _rpx: 0,
  44. _center: 0,
  45. }
  46. },
  47. methods: {
  48. async draw() { //绘制海报
  49. let self = this
  50. //获取设备信息
  51. self.systemInfo = await self.getSystemInfo();
  52. //转换相对单位
  53. let rpx = self.systemInfo.windowWidth / 750
  54. self._rpx = rpx
  55. //设置画布宽高
  56. self.canvasW = 542 * rpx
  57. self.canvasH = 731 * rpx
  58. //海报背景
  59. let bg = new Image();
  60. bg.src = import.meta.env.VITE_REDIRECT_URI + '/static/placard/placard-bg.png'
  61. //logo
  62. let logo = new Image();
  63. logo.src = import.meta.env.VITE_REDIRECT_URI + '/static/login/logo.png'
  64. bg.onload = () => {
  65. logo.onload = () => { //确保背景和logo加载完成(不然海报可能会少logo)
  66. setTimeout(() => {
  67. let ctx = document.querySelector('canvas').getContext('2d')
  68. let img = document.querySelector('.qrcode img')
  69. let center = self.canvasW / 2; //画布中心位置
  70. self._center = center
  71. //绘制图片
  72. ctx.drawImage(bg, 0, 0, self.canvasW, self.canvasH)
  73. ctx.drawImage(img, center - (self.qrCodeSize / 2), 295 * rpx, self.qrCodeSize, self
  74. .qrCodeSize)
  75. ctx.drawImage(logo, center - (100 * rpx / 2) , 60 * rpx , 100 * rpx, 100 * rpx)
  76. //绘制文字
  77. ctx.font = `bold ${40 * rpx}px 楷体`
  78. ctx.textAlign = 'center'
  79. ctx.fillStyle = "#ecb978";
  80. ctx.fillText('上门服务', center, 200 * rpx, 400)
  81. ctx.fillStyle = "#0A543B";
  82. ctx.font = `100 ${25 * rpx}px 楷体`
  83. ctx.fillText(`一扫疲劳 舒服入眠`, center, 240 * rpx, 400)
  84. ctx.font = `100 ${25 * rpx}px 宋体`
  85. ctx.fillStyle = "#0A543B";
  86. ctx.textAlign = 'center';
  87. drawTextVertical(ctx, '微信扫码下单', 130 * rpx, 315 * rpx, self.qrCodeSize);
  88. ctx.textAlign = 'center';
  89. drawTextVertical(ctx, '在线选择技师', 400 * rpx, 315 * rpx, self.qrCodeSize);
  90. ctx.font = `100 ${18 * rpx}px 宋体`
  91. ctx.fillStyle = '#053323'
  92. ctx.fillText(`长按扫一扫下单可领取`, center, 525 * rpx, 400)
  93. ctx.font = `bold ${43 * rpx}px 宋体`
  94. ctx.fillStyle = '#EC8D44'
  95. ctx.fillText(`200元`, center, 580 * rpx, 400)
  96. ctx.font = `100 ${18 * rpx}px 宋体`
  97. ctx.fillText(`百万明星技师在线接单`, center, 625 * rpx, 400)
  98. //画图形
  99. this.paintingCapsule(ctx, center - (90 * rpx / 2), 250 * rpx, 90 * rpx, 25 * rpx,
  100. 13 * rpx, '#ecb978', 'time')
  101. this.paintingCapsule(ctx, center + (130 * rpx / 2), 530 * rpx, 25 * rpx, 70 * rpx,
  102. 13 * rpx, '#ffe6ed', 'coupon')
  103. ////画海报最后的标签列表
  104. this.drawList(ctx, 135 * rpx, 650 * rpx, 60 * rpx, 20 * rpx, 10 * rpx, '#ecb978')
  105. uni.canvasToTempFilePath({
  106. x: 0, // 起点坐标
  107. y: 0,
  108. width: self.canvasW, // canvas 宽
  109. height: self.canvasH, // canvas 高
  110. canvasId: 'myCanvas', // canvas id
  111. success(res) {
  112. self.tempFilePath = res.tempFilePath //相对路径
  113. }
  114. })
  115. })
  116. }
  117. }
  118. },
  119. // 获取设备信息
  120. getSystemInfo() {
  121. return new Promise((req, rej) => {
  122. uni.getSystemInfo({
  123. success: function(res) {
  124. req(res)
  125. }
  126. });
  127. })
  128. },
  129. paintingCapsule(ctx, x, y, width, height, radius, color, current) { //画椭圆(胶囊)
  130. // 开始新的路径
  131. ctx.beginPath();
  132. // 绘制左上角圆角
  133. ctx.moveTo(x + radius, y);
  134. ctx.arcTo(x + width, y, x + width, y + height, radius);
  135. // 绘制右上角圆角
  136. ctx.arcTo(x + width, y + height, x, y + height, radius);
  137. // 绘制右下角圆角
  138. ctx.arcTo(x, y + height, x, y, radius);
  139. // 绘制左下角圆角
  140. ctx.arcTo(x, y, x + width, y, radius);
  141. // 闭合路径(实际上在arcTo后已经是闭合的,但显式调用可以增加可读性)
  142. ctx.closePath();
  143. // 设置填充颜色
  144. ctx.fillStyle = color;
  145. // 填充路径
  146. ctx.fill();
  147. //下面是再写不同区域的内容
  148. if (current == 'time') {
  149. ctx.fillStyle = "#fff";
  150. ctx.font = `100 ${17 * this._rpx}px 楷体`
  151. ctx.fillText(`24小时`, this._center, 267 * this._rpx);
  152. } else if (current == 'coupon') {
  153. ctx.fillStyle = "#EC8D44";
  154. ctx.font = `100 ${13 * this._rpx}px 楷体`
  155. let offset = 13 * this._rpx
  156. drawTextVertical(ctx, '优惠券', 349 * this._rpx, 555 * this._rpx, height - offset);
  157. }
  158. },
  159. drawList(ctx, x, y, width, height, radius, color) { //画海报最后的标签列表
  160. let list = ['安全', '正规', '健康', '便捷']
  161. let offset = 15 //偏移量
  162. let currentTagInfo = {
  163. x
  164. }
  165. list.forEach(item => {
  166. // 开始新的路径
  167. ctx.beginPath();
  168. // 绘制左上角圆角
  169. ctx.moveTo(currentTagInfo.x + radius, y);
  170. ctx.arcTo(currentTagInfo.x + width, y, currentTagInfo.x + width, y + height, radius);
  171. // 绘制右上角圆角
  172. ctx.arcTo(currentTagInfo.x + width, y + height, currentTagInfo.x, y + height, radius);
  173. // 绘制右下角圆角
  174. ctx.arcTo(currentTagInfo.x, y + height, currentTagInfo.x, y, radius);
  175. // 绘制左下角圆角
  176. ctx.arcTo(currentTagInfo.x, y, currentTagInfo.x + width, y, radius);
  177. // 设置边框颜色
  178. ctx.strokeStyle = color;
  179. // 设置边框宽度(可选)
  180. ctx.lineWidth = 1; // 或者你想要的任何宽度
  181. // 闭合路径(实际上在arcTo后已经是闭合的,但显式调用可以增加可读性)
  182. ctx.closePath();
  183. // 绘制边框
  184. ctx.stroke();
  185. //圆点
  186. ctx.beginPath();
  187. ctx.fillStyle = color;
  188. ctx.arc(currentTagInfo.x + (10 * this._rpx), y + (10 * this._rpx), 2, 0,360)
  189. ctx.fill()
  190. //绘制文本
  191. ctx.font = `100 ${13 * this._rpx}px 楷体`
  192. ctx.fillText(item, currentTagInfo.x + (33 * this._rpx), y + (15 * this._rpx), 400)
  193. let next = currentTagInfo.x + width + offset; //下一个标签的位置
  194. currentTagInfo = { x : next }
  195. })
  196. },
  197. getUserInfo(){
  198. // if(localStorage.getItem('userInfo')){
  199. // return JSON.parse(localStorage.getItem('userInfo')).id
  200. // }else{
  201. // uni.navigateTo({
  202. // url: '/pages/login/login'
  203. // })
  204. // }
  205. return this.userInfo.id
  206. }
  207. }
  208. }
  209. </script>
  210. <style lang="scss" scoped>
  211. .placard {
  212. display: flex;
  213. min-height: 100vh;
  214. align-items: center;
  215. justify-content: center;
  216. .placard-content{
  217. display: flex;
  218. flex-direction: column;
  219. align-items: center;
  220. .add-btn {
  221. display: flex;
  222. justify-content: center;
  223. align-items: center;
  224. height: 100rpx;
  225. width: 750rpx;
  226. .btn {
  227. display: flex;
  228. align-items: center;
  229. justify-content: center;
  230. width: 72%;
  231. height: 80rpx;
  232. border-radius: 40rpx;
  233. font-size: 28rpx;
  234. margin-top: 40rpx;
  235. background: linear-gradient(178deg, #ffe6ed, #ecb978);
  236. color: #6e3009;
  237. }
  238. }
  239. }
  240. }
  241. canvas{
  242. opacity: 0;
  243. position: fixed;
  244. top: 100%;
  245. left: 0;
  246. }
  247. </style>