qrcode.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import QRCodeAlg from '../plugins/qrcodeAlg'
  2. /**
  3. * 绘制二维码
  4. */
  5. export default class DrawQrcode {
  6. constructor(params) {
  7. const { Context, commonUtilMethods, commonDrawMethods } = params
  8. this.Context = Context
  9. this.commonUtilMethods = commonUtilMethods
  10. this.commonDrawMethods = commonDrawMethods
  11. }
  12. /**
  13. * 获取绘制参数
  14. * @param { Object } params 参数
  15. * @param { Boolean } conversion 是否需要转换单位
  16. */
  17. getDrawParams(params = {}, conversion = true) {
  18. const globalDataParams = this.commonUtilMethods.getGlobalDataDrawParams(params)
  19. // 绘制二维码的参数
  20. const { text = '', image = {}, size = 100, lv = 3, background = '#ffffff', foreground = '#000000', pdground = '#000000' } = params
  21. const qrCodeParams = {
  22. ...globalDataParams,
  23. text: String(text) || '',
  24. image,
  25. size,
  26. // 容错级别 默认3
  27. correctLevel: lv,
  28. // 二维码背景色
  29. background,
  30. // 二维码前景色
  31. foreground,
  32. // 二维码角标色
  33. pdground,
  34. }
  35. return conversion ? this.commonUtilMethods.conversionUnit(qrCodeParams) : qrCodeParams
  36. }
  37. /**
  38. * 绘制二维码
  39. * @param { Object } params 矩形参数
  40. * @param { Boolean } conversion 是否需要转换单位
  41. */
  42. draw(params = {}, conversion = true) {
  43. const { Context, commonUtilMethods, commonDrawMethods } = this
  44. const { canvasWidth, is2d } = commonUtilMethods
  45. let { x, y, image, windowAlign, offsetRight, ...options } = this.getDrawParams(params, conversion)
  46. return new Promise(async resolve => {
  47. if (windowAlign !== 'none') {
  48. x = commonDrawMethods.computedCenterX(canvasWidth, options.size, windowAlign, offsetRight)
  49. }
  50. //使用QRCodeAlg创建二维码结构
  51. let qrcodeAlgObjCache = []
  52. let qrCodeAlg = null
  53. let l = qrcodeAlgObjCache.length
  54. let d = 0
  55. for (let i = 0;i < l; i++) {
  56. d = i
  57. if (qrcodeAlgObjCache[i].text == options.text && qrcodeAlgObjCache[i].text.correctLevel == options.correctLevel) {
  58. qrCodeAlg = qrcodeAlgObjCache[i].obj
  59. break
  60. }
  61. }
  62. if (d == l) {
  63. qrCodeAlg = new QRCodeAlg(options.text, options.correctLevel)
  64. qrcodeAlgObjCache.push({
  65. text: options.text,
  66. correctLevel: options.correctLevel,
  67. obj: qrCodeAlg
  68. })
  69. }
  70. /**
  71. * 计算矩阵点的前景色
  72. * @param {Obj} config
  73. * @param {Number} config.row 点x坐标
  74. * @param {Number} config.col 点y坐标
  75. * @param {Number} config.count 矩阵大小
  76. * @param {Number} config.options 组件的options
  77. * @return {String}
  78. */
  79. let getForeGround = function (config) {
  80. let options = config.options
  81. if (options.pdground && (
  82. (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
  83. (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
  84. (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
  85. )) {
  86. return options.pdground
  87. }
  88. return options.foreground
  89. }
  90. let count = qrCodeAlg.getModuleCount()
  91. let ratioSize = options.size
  92. let ratioImgSize = commonUtilMethods.getConvertedValue(image.size) || 30
  93. //计算每个点的长宽
  94. let tileW = (ratioSize / count).toPrecision(4)
  95. let tileH = (ratioSize / count).toPrecision(4)
  96. //绘制
  97. for (let row = 0; row < count; row++) {
  98. for (let col = 0; col < count; col++) {
  99. let w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW))
  100. let h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW))
  101. let foreground = getForeGround({
  102. row: row,
  103. col: col,
  104. count: count,
  105. options: options
  106. })
  107. commonDrawMethods.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background)
  108. Context.fillRect(x + Math.round(col * tileW), y + Math.round(row * tileH), w, h)
  109. }
  110. }
  111. if (image.src) {
  112. const { src, r, color, borderWidth, borderColor } = conversion ? this.commonUtilMethods.conversionUnit(image) : image
  113. const dx = x + Number(((ratioSize - ratioImgSize) / 2).toFixed(2))
  114. const dy = y + Number(((ratioSize - ratioImgSize) / 2).toFixed(2))
  115. const drawImage = await commonDrawMethods.drawParams.drawImage.draw({
  116. x: dx,
  117. y: dy,
  118. w: ratioImgSize,
  119. h: ratioImgSize,
  120. src,
  121. r,
  122. color,
  123. borderWidth,
  124. borderColor,
  125. drawType: 'rect',
  126. isCompressImage: false,
  127. }, false)
  128. if (!drawImage.success) {
  129. return resolve(drawImage)
  130. }
  131. }
  132. return resolve({
  133. success: true
  134. })
  135. })
  136. }
  137. }