drawCanvas.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. class DrawCanvas {
  2. constructor() {
  3. this._ctx = null
  4. this._canvas = null
  5. this._executionArr = [] //每移动一笔的数据
  6. this._pathArr = [] //抬起落下为一笔
  7. this._style = null
  8. this._matrix = null
  9. this._path = null
  10. }
  11. _init({ width, height, canvas, dicTypePath = '', callBack }) {
  12. if (!width || !height || !canvas) return
  13. const ctx = canvas.getContext('2d')
  14. canvas.width = width
  15. canvas.height = height
  16. this._canvas = canvas
  17. this._ctx = ctx
  18. this._matrix = ctx.getTransform() //IOS真机矩阵没有返回完整参数,导致无法旋转
  19. this._executionArr = []
  20. this._pathArr = []
  21. // 加个背景
  22. this._ctx.fillStyle = "#FFFFFF";
  23. this._ctx.fillRect(0, 0, width, height);
  24. // 添加路径底图
  25. const path = this.sPath2cPath(dicTypePath)
  26. if (path) {
  27. this._ctx.stroke(path)
  28. this._ctx.clip(path) //IOS真机裁切后,导致无法画图
  29. this._path = path
  30. }
  31. callBack()
  32. console.log('初始化完成');
  33. }
  34. mouseStart() {
  35. console.log('开始移动');
  36. this._executionArr = []
  37. }
  38. mouseMove({ x = 0, y = 0 }) {
  39. console.log('移动中');
  40. this._executionArr.push([x, y])
  41. this._ctx.fillStyle = this._style.fillStyle
  42. const X = x - (this._style.w / 2)
  43. const Y = y - (this._style.h / 2)
  44. this._ctx.fillRect(X, Y, this._style.w, this._style.h)
  45. }
  46. mouseEnd() {
  47. if (!this._style) return
  48. this._pathArr.push({
  49. ...this._style,
  50. path: this._executionArr
  51. })
  52. }
  53. mouseBack() {
  54. // 删除每个移动数据
  55. if (!this._pathArr.length || !this._ctx) return
  56. // 清空画布
  57. this._ctx.clearRect(0, 0, this._ctx.canvas.width, this._ctx.canvas.height)
  58. this._ctx.fillStyle = "#FFFFFF";
  59. this._ctx.fillRect(0, 0, this._ctx.canvas.width, this._ctx.canvas.height);
  60. if (this._path) this._ctx.stroke(this._path)
  61. this._pathArr.pop()
  62. // 重画
  63. for (let k = 0; k < this._pathArr.length; k++) {
  64. const el = this._pathArr[k];
  65. for (let j = 0; j < el.path.length; j++) {
  66. const es = el.path[j];
  67. this._ctx.fillStyle = el.fillStyle
  68. const X = es[0] - (el.w / 2)
  69. const Y = es[1] - (el.h / 2)
  70. this._ctx.fillRect(X, Y, el.w, el.h)
  71. }
  72. }
  73. }
  74. // 切换画笔
  75. changeBrush({ url = '', w = 10, h = 10, angle = 0 }) {
  76. if (!url || !this._ctx || !this._canvas) return
  77. const img = this._canvas.createImage()
  78. img.src = url
  79. img.onload = () => {
  80. const fillStyle = this._ctx.createPattern(img, 'repeat')
  81. console.log('画笔样式', fillStyle, this._matrix);
  82. // 旋转 + 矩阵变化
  83. if (angle && this._matrix && this._matrix.rotateSelf) {
  84. this._matrix.rotateSelf(angle)
  85. fillStyle.setTransform(this._matrix)
  86. }
  87. this._style = { fillStyle, w, h }
  88. }
  89. }
  90. // svg 路径转 canvas 路径
  91. sPath2cPath(path = '') {
  92. if (!path || !this._canvas) return null
  93. const arr = path.split(/(^|\s+)(?=[A-Z])/).filter(el => el !== ' ')
  94. const PATH = this._canvas.createPath2D();
  95. for (let k = 0; k < arr.length; k++) {
  96. const el = arr[k].replace(/\s+/g, ',');
  97. const key = el.replace(/[^A-Z]/g, '')
  98. const value = el.replace(/[A-Z]/g, '').split(',')
  99. if (key === 'M') {
  100. PATH.moveTo(value[0], value[1]);
  101. } else if (key === 'C') {
  102. PATH.bezierCurveTo(value[0], value[1], value[2], value[3], value[4], value[5]);
  103. } else if (key === 'L') {
  104. PATH.lineTo(value[0], value[1]);
  105. }
  106. }
  107. return PATH
  108. }
  109. // 清除画布
  110. clear() {
  111. if (!this._ctx) return
  112. // 清空画布
  113. this._ctx.clearRect(0, 0, this._ctx.canvas.width, this._ctx.canvas.height)
  114. // 画上背景
  115. this._ctx.fillStyle = "#FFFFFF";
  116. this._ctx.fillRect(0, 0, this._ctx.canvas.width, this._ctx.canvas.height);
  117. if (this._path) this._ctx.stroke(this._path)
  118. // 清除路径数据
  119. this._pathArr = []
  120. this._executionArr = []
  121. }
  122. // 销毁
  123. destory() {
  124. this._ctx = null
  125. this._canvas = null
  126. this._executionArr = []
  127. this._pathArr = []
  128. this._style = null
  129. this._matrix = null
  130. this._path = null
  131. }
  132. // 保存
  133. save(callBack) {
  134. if (!this._canvas) return callBack('')
  135. wx.canvasToTempFilePath({
  136. canvas: this._canvas,
  137. success(res) {
  138. callBack(res)
  139. }
  140. })
  141. }
  142. }
  143. export { DrawCanvas }