index.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. const xmlParse = require('./xml-parser')
  2. const {Widget} = require('./widget')
  3. const {Draw} = require('./draw')
  4. const {compareVersion} = require('./utils')
  5. const canvasId = 'weui-canvas'
  6. Component({
  7. properties: {
  8. width: {
  9. type: Number,
  10. value: 400
  11. },
  12. height: {
  13. type: Number,
  14. value: 300
  15. }
  16. },
  17. data: {
  18. use2dCanvas: false, // 2.9.2 后可用canvas 2d 接口
  19. },
  20. lifetimes: {
  21. attached() {
  22. const {SDKVersion, pixelRatio: dpr} = wx.getSystemInfoSync()
  23. const use2dCanvas = compareVersion(SDKVersion, '2.9.2') >= 0
  24. this.dpr = dpr
  25. this.setData({use2dCanvas}, () => {
  26. if (use2dCanvas) {
  27. const query = this.createSelectorQuery()
  28. query.select(`#${canvasId}`)
  29. .fields({node: true, size: true})
  30. .exec(res => {
  31. const canvas = res[0].node
  32. const ctx = canvas.getContext('2d')
  33. canvas.width = res[0].width * dpr
  34. canvas.height = res[0].height * dpr
  35. ctx.scale(dpr, dpr)
  36. this.ctx = ctx
  37. this.canvas = canvas
  38. })
  39. } else {
  40. this.ctx = wx.createCanvasContext(canvasId, this)
  41. }
  42. })
  43. }
  44. },
  45. methods: {
  46. async renderToCanvas(args) {
  47. const {wxml, style} = args
  48. const ctx = this.ctx
  49. const canvas = this.canvas
  50. const use2dCanvas = this.data.use2dCanvas
  51. if (use2dCanvas && !canvas) {
  52. return Promise.reject(new Error('renderToCanvas: fail canvas has not been created'))
  53. }
  54. ctx.clearRect(0, 0, this.data.width, this.data.height)
  55. const {root: xom} = xmlParse(wxml)
  56. const widget = new Widget(xom, style)
  57. const container = widget.init()
  58. this.boundary = {
  59. top: container.layoutBox.top,
  60. left: container.layoutBox.left,
  61. width: container.computedStyle.width,
  62. height: container.computedStyle.height,
  63. }
  64. const draw = new Draw(ctx, canvas, use2dCanvas)
  65. await draw.drawNode(container)
  66. if (!use2dCanvas) {
  67. await this.canvasDraw(ctx)
  68. }
  69. return Promise.resolve(container)
  70. },
  71. canvasDraw(ctx, reserve) {
  72. return new Promise(resolve => {
  73. ctx.draw(reserve, () => {
  74. resolve()
  75. })
  76. })
  77. },
  78. canvasToTempFilePath(args = {}) {
  79. const use2dCanvas = this.data.use2dCanvas
  80. return new Promise((resolve, reject) => {
  81. const {
  82. top, left, width, height
  83. } = this.boundary
  84. const copyArgs = {
  85. x: left,
  86. y: top,
  87. width,
  88. height,
  89. destWidth: width * this.dpr,
  90. destHeight: height * this.dpr,
  91. canvasId,
  92. fileType: args.fileType || 'png',
  93. quality: args.quality || 1,
  94. success: resolve,
  95. fail: reject
  96. }
  97. if (use2dCanvas) {
  98. delete copyArgs.canvasId
  99. copyArgs.canvas = this.canvas
  100. }
  101. wx.canvasToTempFilePath(copyArgs, this)
  102. })
  103. }
  104. }
  105. })