saveQrPoster.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. const POSTER_W = 750
  2. const POSTER_H = 640
  3. const QR_SIZE = 480
  4. const TITLE_COLOR = '#165DFF'
  5. function resolveLocalImage(url) {
  6. return new Promise((resolve, reject) => {
  7. if (!url) {
  8. reject(new Error('empty url'))
  9. return
  10. }
  11. if (url.startsWith('data:') || url.startsWith('blob:') || url.startsWith('wxfile:') || url.startsWith('file:')) {
  12. resolve(url)
  13. return
  14. }
  15. if (!/^https?:\/\//i.test(url)) {
  16. resolve(url)
  17. return
  18. }
  19. uni.downloadFile({
  20. url,
  21. success: (res) => {
  22. if (res.statusCode === 200) resolve(res.tempFilePath)
  23. else reject(new Error('download fail'))
  24. },
  25. fail: reject
  26. })
  27. })
  28. }
  29. function drawPoster(ctx, tableNo, imagePath) {
  30. const titleY = 80
  31. const qrTop = 130
  32. ctx.setFillStyle('#ffffff')
  33. ctx.fillRect(0, 0, POSTER_W, POSTER_H)
  34. ctx.setFillStyle(TITLE_COLOR)
  35. ctx.setFontSize(32)
  36. ctx.setTextAlign('center')
  37. ctx.fillText(`${tableNo}桌号二维码`, POSTER_W / 2, titleY)
  38. ctx.drawImage(imagePath, (POSTER_W - QR_SIZE) / 2, qrTop, QR_SIZE, QR_SIZE)
  39. }
  40. function drawPoster2d(ctx, tableNo, img) {
  41. const titleY = 80
  42. const qrTop = 130
  43. ctx.fillStyle = '#ffffff'
  44. ctx.fillRect(0, 0, POSTER_W, POSTER_H)
  45. ctx.fillStyle = TITLE_COLOR
  46. ctx.font = '500 32px PingFang SC, sans-serif'
  47. ctx.textAlign = 'center'
  48. ctx.textBaseline = 'alphabetic'
  49. ctx.fillText(`${tableNo}桌号二维码`, POSTER_W / 2, titleY)
  50. ctx.drawImage(img, (POSTER_W - QR_SIZE) / 2, qrTop, QR_SIZE, QR_SIZE)
  51. }
  52. function savePosterH5(tableNo, imagePath) {
  53. return new Promise((resolve, reject) => {
  54. const img = new Image()
  55. img.crossOrigin = 'anonymous'
  56. img.onload = () => {
  57. try {
  58. const canvas = document.createElement('canvas')
  59. canvas.width = POSTER_W
  60. canvas.height = POSTER_H
  61. const ctx = canvas.getContext('2d')
  62. drawPoster2d(ctx, tableNo, img)
  63. canvas.toBlob((blob) => {
  64. if (!blob) {
  65. reject(new Error('export fail'))
  66. return
  67. }
  68. const link = document.createElement('a')
  69. const objectUrl = URL.createObjectURL(blob)
  70. link.href = objectUrl
  71. link.download = `${tableNo}-桌号二维码.png`
  72. document.body.appendChild(link)
  73. link.click()
  74. document.body.removeChild(link)
  75. URL.revokeObjectURL(objectUrl)
  76. resolve()
  77. }, 'image/png')
  78. } catch (err) {
  79. reject(err)
  80. }
  81. }
  82. img.onerror = () => reject(new Error('image load fail'))
  83. img.src = imagePath
  84. })
  85. }
  86. function savePosterApp(tableNo, imagePath, canvasId, vm) {
  87. return new Promise((resolve, reject) => {
  88. const ctx = uni.createCanvasContext(canvasId, vm)
  89. drawPoster(ctx, tableNo, imagePath)
  90. ctx.draw(false, () => {
  91. setTimeout(() => {
  92. uni.canvasToTempFilePath({
  93. canvasId,
  94. x: 0,
  95. y: 0,
  96. width: POSTER_W,
  97. height: POSTER_H,
  98. destWidth: POSTER_W,
  99. destHeight: POSTER_H,
  100. fileType: 'png',
  101. success: (res) => {
  102. uni.saveImageToPhotosAlbum({
  103. filePath: res.tempFilePath,
  104. success: resolve,
  105. fail: reject
  106. })
  107. },
  108. fail: reject
  109. }, vm)
  110. }, 300)
  111. })
  112. })
  113. }
  114. /**
  115. * 合成桌号标题 + 小程序二维码海报并保存
  116. * 布局:蓝色「XXX桌号二维码」+ 下方二维码,白底
  117. */
  118. export function saveQrPoster({ tableNo, qrUrl, canvasId = 'qrPosterCanvas', vm }) {
  119. return resolveLocalImage(qrUrl).then((localPath) => {
  120. // #ifdef H5
  121. return savePosterH5(tableNo, localPath)
  122. // #endif
  123. // #ifndef H5
  124. return savePosterApp(tableNo, localPath, canvasId, vm)
  125. // #endif
  126. })
  127. }
  128. export const posterSize = {
  129. width: POSTER_W,
  130. height: POSTER_H
  131. }