drawCanvas.js 3.8 KB

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