vislite 1.12.0-alpha.1 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/AUTHORS.txt +6 -6
  2. package/CHANGELOG +402 -401
  3. package/LICENSE +20 -20
  4. package/README-en.md +245 -245
  5. package/README.md +245 -245
  6. package/bin/formatArgv.js +30 -30
  7. package/bin/help.js +17 -17
  8. package/bin/run +21 -21
  9. package/bin/skills.js +26 -26
  10. package/lib/BarLayout/index.es.js +348 -348
  11. package/lib/Buffer/index.es.js +34 -34
  12. package/lib/Canvas/index.es.js +804 -789
  13. package/lib/Canvas/index.es.min.js +1 -1
  14. package/lib/Cardinal/index.es.js +89 -89
  15. package/lib/Eoap/index.es.js +32 -32
  16. package/lib/Hermite/index.es.js +34 -34
  17. package/lib/MapCoordinate/index.es.js +199 -199
  18. package/lib/Matrix4/index.es.js +123 -123
  19. package/lib/Mercator/index.es.js +18 -18
  20. package/lib/PieLayout/index.es.js +115 -115
  21. package/lib/RawCanvas/index.es.js +736 -721
  22. package/lib/RawCanvas/index.es.min.js +1 -1
  23. package/lib/SVG/index.es.js +626 -626
  24. package/lib/Shader/index.es.js +34 -34
  25. package/lib/Texture/index.es.js +52 -52
  26. package/lib/TreeLayout/index.es.js +301 -301
  27. package/lib/animation/index.es.js +2 -2
  28. package/lib/assemble/index.es.js +19 -19
  29. package/lib/getLoopColors/index.es.js +34 -34
  30. package/lib/getWebGLContext/index.es.js +61 -61
  31. package/lib/index.umd.js +2797 -2782
  32. package/lib/index.umd.min.js +2 -2
  33. package/lib/initOption/index.es.js +5 -5
  34. package/lib/mergeOption/index.es.js +34 -34
  35. package/lib/move/index.es.js +6 -6
  36. package/lib/rotate/index.es.js +6 -6
  37. package/lib/ruler/index.es.js +136 -136
  38. package/lib/scale/index.es.js +5 -5
  39. package/minialipay/ui-canvas/drawImage.js +35 -35
  40. package/minialipay/ui-canvas/index.acss +4 -4
  41. package/minialipay/ui-canvas/index.axml +3 -3
  42. package/minialipay/ui-canvas/index.d.ts +1 -1
  43. package/minialipay/ui-canvas/index.js +100 -100
  44. package/minialipay/ui-canvas/index.json +6 -6
  45. package/miniprogram/ui-canvas/drawImage.js +35 -35
  46. package/miniprogram/ui-canvas/index.js +125 -125
  47. package/miniprogram/ui-canvas/index.json +4 -4
  48. package/miniprogram/ui-canvas/index.wxml +4 -4
  49. package/miniprogram/ui-canvas/index.wxss +5 -5
  50. package/package/BarLayout/index.ts +2 -2
  51. package/package/Buffer/index.ts +2 -2
  52. package/package/Canvas/index.ts +2 -2
  53. package/package/Cardinal/index.ts +2 -2
  54. package/package/Eoap/index.ts +2 -2
  55. package/package/Hermite/index.ts +2 -2
  56. package/package/MapCoordinate/index.ts +2 -2
  57. package/package/Matrix4/index.ts +2 -2
  58. package/package/Mercator/index.ts +2 -2
  59. package/package/PieLayout/index.ts +2 -2
  60. package/package/RawCanvas/index.ts +2 -2
  61. package/package/SVG/index.ts +2 -2
  62. package/package/Shader/index.ts +2 -2
  63. package/package/Texture/index.ts +2 -2
  64. package/package/TreeLayout/index.ts +2 -2
  65. package/package/animation/index.ts +5 -5
  66. package/package/assemble/index.ts +2 -2
  67. package/package/getLoopColors/index.ts +2 -2
  68. package/package/getWebGLContext/index.ts +40 -40
  69. package/package/index.ts +84 -84
  70. package/package/initOption/index.ts +2 -2
  71. package/package/mergeOption/index.ts +2 -2
  72. package/package/move/index.ts +2 -2
  73. package/package/rotate/index.ts +2 -2
  74. package/package/ruler/index.ts +2 -2
  75. package/package/scale/index.ts +2 -2
  76. package/package/throttle/index.ts +2 -2
  77. package/package.json +79 -79
  78. package/skills/vislite-lib/BarLayout.md +117 -117
  79. package/skills/vislite-lib/Canvas.md +183 -183
  80. package/skills/vislite-lib/Interpolation.md +129 -129
  81. package/skills/vislite-lib/Matrix.md +174 -174
  82. package/skills/vislite-lib/PieLayout.md +131 -131
  83. package/skills/vislite-lib/Projections.md +158 -158
  84. package/skills/vislite-lib/SKILL.md +179 -179
  85. package/skills/vislite-lib/SVG.md +137 -137
  86. package/skills/vislite-lib/TreeLayout.md +176 -176
  87. package/skills/vislite-lib/Utilities.md +261 -261
  88. package/skills/vislite-lib/WebGL.md +106 -106
  89. package/skills/vislite-lib/minialipay/ui-canvas.md +95 -95
  90. package/skills/vislite-lib/miniprogram/ui-canvas.md +98 -98
  91. package/skills/vislite-lib/uniapp/ui-canvas.md +113 -113
  92. package/src/Canvas.ts +89 -89
  93. package/src/Eoap.ts +66 -66
  94. package/src/Matrix4/index.ts +84 -84
  95. package/src/Matrix4/move.ts +12 -12
  96. package/src/Matrix4/rotate.ts +15 -15
  97. package/src/Matrix4/scale.ts +11 -11
  98. package/src/Matrix4/transform.ts +64 -64
  99. package/src/Mercator.ts +27 -27
  100. package/src/SVG.ts +86 -86
  101. package/src/common/assemble.ts +30 -30
  102. package/src/common/canvas/arc.ts +51 -51
  103. package/src/common/canvas/config.ts +176 -176
  104. package/src/common/canvas/default.ts +64 -64
  105. package/src/common/canvas/gradient.ts +31 -31
  106. package/src/common/canvas/index.ts +189 -189
  107. package/src/common/canvas/painter.ts +475 -454
  108. package/src/common/canvas/texts.ts +18 -18
  109. package/src/common/map/getBoundary.ts +15 -15
  110. package/src/common/map/tool.ts +29 -29
  111. package/src/common/option.ts +31 -31
  112. package/src/common/setStyle.ts +5 -5
  113. package/src/common/svg/config.ts +213 -213
  114. package/src/common/svg/default.ts +29 -29
  115. package/src/common/svg/gradient.ts +53 -53
  116. package/src/common/svg/index.ts +420 -420
  117. package/src/common/svg/tool.ts +51 -51
  118. package/src/common/tree/index.ts +25 -25
  119. package/src/common/tree/toInnerTree.ts +61 -61
  120. package/src/common/tree/toPlainTree.ts +135 -135
  121. package/src/common/type.ts +26 -26
  122. package/src/common/webgl/buffer.ts +79 -79
  123. package/src/common/webgl/getWebGLContext.ts +45 -45
  124. package/src/common/webgl/shader.ts +75 -75
  125. package/src/common/webgl/texture.ts +98 -98
  126. package/src/coordinate/MapCoordinate.ts +80 -80
  127. package/src/getLoopColors.ts +42 -42
  128. package/src/interpolation/Cardinal.ts +110 -110
  129. package/src/interpolation/Hermite.ts +65 -65
  130. package/src/layout/BarLayout.ts +249 -249
  131. package/src/layout/PieLayout.ts +146 -146
  132. package/src/layout/TreeLayout.ts +200 -200
  133. package/src/move.ts +7 -7
  134. package/src/rotate.ts +7 -7
  135. package/src/ruler.ts +209 -209
  136. package/src/scale.ts +6 -6
  137. package/types/Bar.d.ts +91 -91
  138. package/types/BarConfig.d.ts +4 -4
  139. package/types/BarLayout.d.ts +48 -48
  140. package/types/BarOption.d.ts +31 -31
  141. package/types/Buffer.d.ts +30 -30
  142. package/types/Canvas.d.ts +379 -379
  143. package/types/CanvasConfig.d.ts +61 -61
  144. package/types/CanvasOption.d.ts +13 -13
  145. package/types/CanvasOpts.d.ts +9 -9
  146. package/types/Cardinal.d.ts +20 -20
  147. package/types/Gradient.d.ts +20 -20
  148. package/types/Hermite.d.ts +25 -25
  149. package/types/Map.d.ts +9 -9
  150. package/types/MapConfig.d.ts +27 -27
  151. package/types/MapCoordinate.d.ts +22 -22
  152. package/types/Matrix4.d.ts +79 -79
  153. package/types/Pie.d.ts +73 -73
  154. package/types/PieConfig.d.ts +26 -26
  155. package/types/PieLayout.d.ts +40 -40
  156. package/types/PieOption.d.ts +21 -21
  157. package/types/SVG.d.ts +282 -282
  158. package/types/SVGConfig.d.ts +54 -54
  159. package/types/Shader.d.ts +22 -22
  160. package/types/Texture.d.ts +22 -22
  161. package/types/Tree.d.ts +74 -74
  162. package/types/TreeConfig.d.ts +52 -52
  163. package/types/TreeLayout.d.ts +71 -71
  164. package/types/TreeOption.d.ts +48 -48
  165. package/types/animation.d.ts +26 -26
  166. package/types/assemble.d.ts +14 -14
  167. package/types/getLoopColors.d.ts +13 -13
  168. package/types/getWebGLContext.d.ts +7 -7
  169. package/types/index.d.ts +220 -221
  170. package/types/module.d.ts +110 -110
  171. package/types/move.d.ts +15 -15
  172. package/types/option.d.ts +12 -12
  173. package/types/painterConfig.d.ts +14 -14
  174. package/types/rotate.d.ts +15 -15
  175. package/types/ruler.d.ts +24 -24
  176. package/types/scale.d.ts +15 -15
  177. package/types/throttle.d.ts +6 -6
  178. package/types/ui-canvas.d.ts +4 -4
  179. package/types/uni-canvas.d.ts +3 -3
  180. package/uni-app/drawImage.js +19 -19
  181. package/uni-app/ui-canvas.vue +295 -295
@@ -1,455 +1,476 @@
1
- import type CanvasOptsType from '../../../types/CanvasOpts'
2
-
3
- import { initText, initArc, initCircle, initRect } from './config'
4
- import texts from './texts'
5
- import defaultFactory from "./default"
6
-
7
- class Painter {
8
-
9
- painter: CanvasRenderingContext2D
10
- __region: Painter | null | undefined = null
11
-
12
- __onlyRegion: boolean = false
13
- __onlyView: boolean = false
14
-
15
- __isPainter: boolean
16
-
17
- // 用于记录配置
18
- // 因为部分配置的设置比较特殊,只先记录意图
19
- __specialConfig = defaultFactory("special") as {
20
- [key: string]: any
21
- }
22
-
23
- private __initConfig = defaultFactory("init")
24
-
25
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
- constructor(canvas: HTMLCanvasElement, opts: CanvasOptsType = {}, region?: Painter, isPainter = false, scaleSize = 1) {
27
- this.painter = canvas.getContext("2d", opts) as CanvasRenderingContext2D
28
- this.__region = region
29
- this.__isPainter = isPainter
30
-
31
- // 默认配置canvas2D对象已经存在的属性
32
- this.painter.textBaseline = 'middle'
33
- this.painter.textAlign = 'left'
34
- this.painter.shadowColor = 'black'
35
- }
36
-
37
- useConfig(key: string, value: any) {
38
- if (this.__region && !this.__onlyView) {
39
- if (['fillStyle', 'strokeStyle', 'shadowBlur', 'shadowColor'].indexOf(key) < 0) {
40
- this.__region.useConfig(key, value)
41
- }
42
- }
43
-
44
- if (this.__isPainter && this.__onlyRegion) return this
45
-
46
- /**
47
- * -----------------------------
48
- * 特殊的设置开始
49
- * -----------------------------
50
- */
51
-
52
- if (key == 'lineDash') {
53
- if (this.painter.setLineDash) this.painter.setLineDash(value)
54
- }
55
-
56
- /**
57
- * -----------------------------
58
- * 常规的配置开始
59
- * -----------------------------
60
- */
61
-
62
- // 如果已经存在默认配置中,说明只需要缓存起来即可
63
- else if (key in this.__specialConfig) {
64
-
65
- // 文字非整数可能存在问题,修复一下
66
- if (key == 'fontSize') {
67
- value = Math.round(value)
68
- }
69
-
70
- this.__specialConfig[key] = value
71
- }
72
-
73
- // 其它情况直接生效即可
74
- else if (key in this.__initConfig) {
75
- (this.painter as any)[key] = value
76
- }
77
-
78
- // 如果属性未被定义
79
- else {
80
- throw new Error('Illegal configuration item of painter : ' + key + " !")
81
- }
82
-
83
- return this
84
- }
85
-
86
- // 文字
87
- fillText(text: string, x: number, y: number, deg: number = 0) {
88
- if (this.__region && !this.__onlyView) this.__region.fillText(text, x, y, deg)
89
-
90
- if (this.__isPainter && this.__onlyRegion) return this
91
-
92
- this.painter.save()
93
- initText(this.painter, this.__specialConfig, x, y, deg).fillText(text, 0, 0)
94
- this.painter.restore()
95
- return this
96
- }
97
- strokeText(text: string, x: number, y: number, deg: number = 0) {
98
- if (this.__region && !this.__onlyView) this.__region.strokeText(text, x, y, deg)
99
-
100
- if (this.__isPainter && this.__onlyRegion) return this
101
-
102
- this.painter.save()
103
- initText(this.painter, this.__specialConfig, x, y, deg).strokeText(text, 0, 0)
104
- this.painter.restore()
105
- return this
106
- }
107
- fullText(text: string, x: number, y: number, deg: number = 0) {
108
- if (this.__region && !this.__onlyView) this.__region.fullText(text, x, y, deg)
109
-
110
- if (this.__isPainter && this.__onlyRegion) return this
111
-
112
- this.painter.save()
113
- initText(this.painter, this.__specialConfig, x, y, deg)
114
- this.painter.fillText(text, 0, 0)
115
- this.painter.strokeText(text, 0, 0)
116
- this.painter.restore()
117
- return this
118
- }
119
-
120
- // 多行文字
121
- fillTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
122
- let h = 0
123
- if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
124
-
125
- if (this.__isPainter && this.__onlyRegion) return h
126
-
127
- this.painter.save()
128
- initText(this.painter, this.__specialConfig, x, y, deg)
129
-
130
- const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
131
- this.painter.fillText(content, 0, top)
132
- })
133
-
134
- this.painter.restore()
135
- return height
136
- }
137
- strokeTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
138
- let h = 0
139
- if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
140
-
141
- if (this.__isPainter && this.__onlyRegion) return h
142
-
143
- this.painter.save()
144
- initText(this.painter, this.__specialConfig, x, y, deg)
145
-
146
- const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
147
- this.painter.strokeText(content, 0, top)
148
- })
149
-
150
- this.painter.restore()
151
- return height
152
- }
153
- fullTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
154
- let h = 0
155
- if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
156
-
157
- if (this.__isPainter && this.__onlyRegion) return h
158
-
159
- this.painter.save()
160
- initText(this.painter, this.__specialConfig, x, y, deg)
161
-
162
- const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
163
- this.painter.fillText(content, 0, top)
164
- this.painter.strokeText(content, 0, top)
165
- })
166
-
167
- this.painter.restore()
168
- return height
169
- }
170
-
171
- // 路径
172
- beginPath() {
173
- if (this.__region && !this.__onlyView) this.__region.beginPath()
174
-
175
- if (this.__isPainter && this.__onlyRegion) return this
176
-
177
- this.painter.beginPath()
178
- return this
179
- }
180
- closePath() {
181
- if (this.__region && !this.__onlyView) this.__region.closePath()
182
-
183
- if (this.__isPainter && this.__onlyRegion) return this
184
-
185
- this.painter.closePath()
186
- return this
187
- }
188
- moveTo(x: number, y: number) {
189
- if (this.__region && !this.__onlyView) this.__region.moveTo(x, y)
190
-
191
- if (this.__isPainter && this.__onlyRegion) return this
192
-
193
- // 解决1px模糊问题,别的地方类似原因
194
- this.painter.moveTo(Math.round(x) + 0.5, Math.round(y) + 0.5)
195
- return this
196
- }
197
- lineTo(x: number, y: number) {
198
- if (this.__region && !this.__onlyView) this.__region.lineTo(x, y)
199
-
200
- if (this.__isPainter && this.__onlyRegion) return this
201
-
202
- this.painter.lineTo(Math.round(x) + 0.5, Math.round(y) + 0.5)
203
- return this
204
- }
205
- arc(x: number, y: number, r: number, beginDeg: number, deg: number) {
206
- if (this.__region && !this.__onlyView) this.__region.arc(x, y, r, beginDeg, deg)
207
-
208
- if (this.__isPainter && this.__onlyRegion) return this
209
-
210
- this.painter.arc(x, y, r, beginDeg, beginDeg + deg, deg < 0)
211
- return this
212
- }
213
- fill() {
214
- if (this.__region && !this.__onlyView) this.__region.fill()
215
-
216
- if (this.__isPainter && this.__onlyRegion) return this
217
-
218
- this.painter.fill()
219
- return this
220
- }
221
- stroke() {
222
- if (this.__region && !this.__onlyView) this.__region.stroke()
223
-
224
- if (this.__isPainter && this.__onlyRegion) return this
225
-
226
- this.painter.stroke()
227
- return this
228
- }
229
- full() {
230
- if (this.__region && !this.__onlyView) this.__region.full()
231
-
232
- if (this.__isPainter && this.__onlyRegion) return this
233
-
234
- this.painter.fill()
235
- this.painter.stroke()
236
- return this
237
- }
238
-
239
- save() {
240
- if (this.__region && !this.__onlyView) this.__region.save()
241
-
242
- if (this.__isPainter && this.__onlyRegion) return this
243
-
244
- this.painter.save()
245
- return this
246
- }
247
- restore() {
248
- if (this.__region && !this.__onlyView) this.__region.restore()
249
-
250
- if (this.__isPainter && this.__onlyRegion) return this
251
-
252
- this.painter.restore()
253
- return this
254
- }
255
- clip() {
256
- if (this.__region && !this.__onlyView) this.__region.clip()
257
-
258
- if (this.__isPainter && this.__onlyRegion) return this
259
-
260
- this.painter.clip()
261
- return this
262
- }
263
-
264
- // 路径 - 贝塞尔曲线
265
- quadraticCurveTo(cpx: number, cpy: number, x: number, y: number) {
266
- if (this.__region && !this.__onlyView) this.__region.quadraticCurveTo(cpx, cpy, x, y)
267
-
268
- if (this.__isPainter && this.__onlyRegion) return this
269
-
270
- this.painter.quadraticCurveTo(cpx, cpy, x, y)
271
- return this
272
- }
273
- bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number) {
274
- if (this.__region && !this.__onlyView) this.__region.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
275
-
276
- if (this.__isPainter && this.__onlyRegion) return this
277
-
278
- this.painter.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
279
- return this
280
- }
281
-
282
- // 擦除画面
283
- clearRect(x: number, y: number, w: number, h: number) {
284
- if (this.__region && !this.__onlyView) this.__region.clearRect(x, y, w, h)
285
-
286
- if (this.__isPainter && this.__onlyRegion) return this
287
-
288
- this.painter.clearRect(x, y, w, h)
289
- return this
290
- }
291
- clearCircle(cx: number, cy: number, r: number) {
292
- if (this.__region && !this.__onlyView) this.__region.clearCircle(cx, cy, r)
293
-
294
- if (this.__isPainter && this.__onlyRegion) return this
295
-
296
- this.painter.beginPath()
297
- this.painter.globalCompositeOperation = "destination-out"
298
- this.painter.arc(cx, cy, r, 0, Math.PI * 2)
299
- this.painter.fill()
300
- this.painter.globalCompositeOperation = "source-over"
301
- this.painter.closePath()
302
- return this
303
- }
304
-
305
- // 弧
306
- fillArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
307
- if (this.__region && !this.__onlyView) this.__region.fillArc(cx, cy, r1, r2, beginDeg, deg)
308
-
309
- if (this.__isPainter && this.__onlyRegion) return this
310
-
311
- initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg).fill()
312
- return this
313
- }
314
- strokeArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
315
- if (this.__region && !this.__onlyView) this.__region.strokeArc(cx, cy, r1, r2, beginDeg, deg)
316
-
317
- if (this.__isPainter && this.__onlyRegion) return this
318
-
319
- initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg).stroke()
320
- return this
321
- }
322
- fullArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
323
- if (this.__region && !this.__onlyView) this.__region.fullArc(cx, cy, r1, r2, beginDeg, deg)
324
-
325
- if (this.__isPainter && this.__onlyRegion) return this
326
-
327
- initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg)
328
- this.painter.fill()
329
- this.painter.stroke()
330
- return this
331
- }
332
-
333
- // 圆形
334
- fillCircle(cx: number, cy: number, r: number) {
335
- if (this.__region && !this.__onlyView) this.__region.fillCircle(cx, cy, r)
336
-
337
- if (this.__isPainter && this.__onlyRegion) return this
338
-
339
- initCircle(this.painter, cx, cy, r).fill()
340
- return this
341
- }
342
- strokeCircle(cx: number, cy: number, r: number) {
343
- if (this.__region && !this.__onlyView) this.__region.strokeCircle(cx, cy, r)
344
-
345
- if (this.__isPainter && this.__onlyRegion) return this
346
-
347
- initCircle(this.painter, cx, cy, r).stroke()
348
- return this
349
- }
350
- fullCircle(cx: number, cy: number, r: number) {
351
- if (this.__region && !this.__onlyView) this.__region.fullCircle(cx, cy, r)
352
-
353
- if (this.__isPainter && this.__onlyRegion) return this
354
-
355
- initCircle(this.painter, cx, cy, r)
356
- this.painter.fill()
357
- this.painter.stroke()
358
- return this
359
- }
360
-
361
- // 矩形
362
- fillRect(x: number, y: number, width: number, height: number) {
363
- if (this.__region && !this.__onlyView) this.__region.fillRect(x, y, width, height)
364
-
365
- if (this.__isPainter && this.__onlyRegion) return this
366
-
367
- initRect(this.painter, this.__specialConfig, x, y, width, height).fill()
368
- return this
369
- }
370
- strokeRect(x: number, y: number, width: number, height: number) {
371
- if (this.__region && !this.__onlyView) this.__region.strokeRect(x, y, width, height)
372
-
373
- if (this.__isPainter && this.__onlyRegion) return this
374
-
375
- initRect(this.painter, this.__specialConfig, x, y, width, height).stroke()
376
- return this
377
- }
378
- fullRect(x: number, y: number, width: number, height: number) {
379
- if (this.__region && !this.__onlyView) this.__region.fullRect(x, y, width, height)
380
-
381
- if (this.__isPainter && this.__onlyRegion) return this
382
-
383
- initRect(this.painter, this.__specialConfig, x, y, width, height)
384
- this.painter.fill()
385
- this.painter.stroke()
386
- return this
387
- }
388
-
389
- // 渲染绘制(uniapp独有)
390
- draw() {
391
-
392
- // 兼容非uniapp环境,防止误用
393
- // 2024年4月3日 于南京
394
- return Promise.resolve()
395
- }
396
-
397
- // 绘制图片
398
- drawImage(img: CanvasImageSource | string, x: number, y: number, w: number, h: number, isImage: boolean = false) {
399
- return new Promise((resolve) => {
400
- if (this.__region && !this.__onlyView) {
401
- this.__region.fillRect(x, y, w, h)
402
- }
403
-
404
- if (this.__isPainter && this.__onlyRegion) {
405
- resolve({})
406
- return
407
- }
408
-
409
- if (typeof img == 'string' && !isImage) {
410
- const imgInstance = new Image()
411
- imgInstance.onload = () => {
412
- this.painter.drawImage(imgInstance, x, y, w, h)
413
- resolve({})
414
- }
415
- imgInstance.src = img
416
- } else {
417
- this.painter.drawImage(img as CanvasImageSource, x, y, w, h)
418
- resolve({})
419
- }
420
-
421
- })
422
- }
423
-
424
- // 转换画布
425
- translate(dx: number, dy: number) {
426
- this.painter.translate(dx, dy)
427
- return this
428
- }
429
- rotate(deg: number) {
430
- this.painter.rotate(deg)
431
- return this
432
- }
433
-
434
- // 扩展绘制方法
435
- install(methods: {
436
- [key: string]: Function
437
- }): any {
438
- for (const key in methods) {
439
-
440
- if (key in this) {
441
- throw new Error("VISLite Canvas:Method already exists and cannot be overwritten.")
442
- } else {
443
- (this as any)[key] = (...args: any) => {
444
- const value = methods[key].apply(this, args)
445
- if (value != void 0) return value
446
- return this
447
- }
448
- }
449
-
450
- }
451
- return this
452
- }
453
- }
454
-
1
+ import type CanvasOptsType from '../../../types/CanvasOpts'
2
+
3
+ import { initText, initArc, initCircle, initRect } from './config'
4
+ import texts from './texts'
5
+ import defaultFactory from "./default"
6
+
7
+ class Painter {
8
+
9
+ painter: CanvasRenderingContext2D
10
+ __region: Painter | null | undefined = null
11
+
12
+ __onlyRegion: boolean = false
13
+ __onlyView: boolean = false
14
+
15
+ __isPainter: boolean
16
+
17
+ // 用于记录配置
18
+ // 因为部分配置的设置比较特殊,只先记录意图
19
+ __specialConfig = defaultFactory("special") as {
20
+ [key: string]: any
21
+ }
22
+
23
+ private __initConfig = defaultFactory("init")
24
+
25
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
26
+ constructor(canvas: HTMLCanvasElement, opts: CanvasOptsType = {}, region?: Painter, isPainter = false, scaleSize = 1) {
27
+ this.painter = canvas.getContext("2d", opts) as CanvasRenderingContext2D
28
+ this.__region = region
29
+ this.__isPainter = isPainter
30
+
31
+ // 默认配置canvas2D对象已经存在的属性
32
+ this.painter.textBaseline = 'middle'
33
+ this.painter.textAlign = 'left'
34
+ this.painter.shadowColor = 'black'
35
+ }
36
+
37
+ useConfig(key: string, value: any) {
38
+ if (this.__region && !this.__onlyView) {
39
+ if (['fillStyle', 'strokeStyle', 'shadowBlur', 'shadowColor'].indexOf(key) < 0) {
40
+ this.__region.useConfig(key, value)
41
+ }
42
+ }
43
+
44
+ if (this.__isPainter && this.__onlyRegion) return this
45
+
46
+ /**
47
+ * -----------------------------
48
+ * 特殊的设置开始
49
+ * -----------------------------
50
+ */
51
+
52
+ if (key == 'lineDash') {
53
+ if (this.painter.setLineDash) this.painter.setLineDash(value)
54
+ }
55
+
56
+ /**
57
+ * -----------------------------
58
+ * 常规的配置开始
59
+ * -----------------------------
60
+ */
61
+
62
+ // 如果已经存在默认配置中,说明只需要缓存起来即可
63
+ else if (key in this.__specialConfig) {
64
+
65
+ // 文字非整数可能存在问题,修复一下
66
+ if (key == 'fontSize') {
67
+ value = Math.round(value)
68
+ }
69
+
70
+ this.__specialConfig[key] = value
71
+ }
72
+
73
+ // 其它情况直接生效即可
74
+ else if (key in this.__initConfig) {
75
+ (this.painter as any)[key] = value
76
+ }
77
+
78
+ // 如果属性未被定义
79
+ else {
80
+ throw new Error('Illegal configuration item of painter : ' + key + " !")
81
+ }
82
+
83
+ return this
84
+ }
85
+
86
+ // 文字
87
+ fillText(text: string, x: number, y: number, deg: number = 0) {
88
+ if (this.__region && !this.__onlyView) this.__region.fillText(text, x, y, deg)
89
+
90
+ if (this.__isPainter && this.__onlyRegion) return this
91
+
92
+ this.painter.save()
93
+ initText(this.painter, this.__specialConfig, x, y, deg).fillText(text, 0, 0)
94
+ this.painter.restore()
95
+ return this
96
+ }
97
+ strokeText(text: string, x: number, y: number, deg: number = 0) {
98
+ if (this.__region && !this.__onlyView) this.__region.strokeText(text, x, y, deg)
99
+
100
+ if (this.__isPainter && this.__onlyRegion) return this
101
+
102
+ this.painter.save()
103
+ initText(this.painter, this.__specialConfig, x, y, deg).strokeText(text, 0, 0)
104
+ this.painter.restore()
105
+ return this
106
+ }
107
+ fullText(text: string, x: number, y: number, deg: number = 0) {
108
+ if (this.__region && !this.__onlyView) this.__region.fullText(text, x, y, deg)
109
+
110
+ if (this.__isPainter && this.__onlyRegion) return this
111
+
112
+ this.painter.save()
113
+ initText(this.painter, this.__specialConfig, x, y, deg)
114
+ this.painter.fillText(text, 0, 0)
115
+ this.painter.strokeText(text, 0, 0)
116
+ this.painter.restore()
117
+ return this
118
+ }
119
+
120
+ // 多行文字
121
+ fillTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
122
+ let h = 0
123
+ if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
124
+
125
+ if (this.__isPainter && this.__onlyRegion) return h
126
+
127
+ this.painter.save()
128
+ initText(this.painter, this.__specialConfig, x, y, deg)
129
+
130
+ const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
131
+ this.painter.fillText(content, 0, top)
132
+ })
133
+
134
+ this.painter.restore()
135
+ return height
136
+ }
137
+ strokeTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
138
+ let h = 0
139
+ if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
140
+
141
+ if (this.__isPainter && this.__onlyRegion) return h
142
+
143
+ this.painter.save()
144
+ initText(this.painter, this.__specialConfig, x, y, deg)
145
+
146
+ const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
147
+ this.painter.strokeText(content, 0, top)
148
+ })
149
+
150
+ this.painter.restore()
151
+ return height
152
+ }
153
+ fullTexts(contents: string, x: number, y: number, width: number, lineHeight: number = 1.2, deg: number = 0) {
154
+ let h = 0
155
+ if (this.__region && !this.__onlyView) h = this.__region.fillTexts(contents, x, y, width, lineHeight)
156
+
157
+ if (this.__isPainter && this.__onlyRegion) return h
158
+
159
+ this.painter.save()
160
+ initText(this.painter, this.__specialConfig, x, y, deg)
161
+
162
+ const height = texts(this.painter, contents, width, this.__specialConfig.fontSize * lineHeight, (content, top) => {
163
+ this.painter.fillText(content, 0, top)
164
+ this.painter.strokeText(content, 0, top)
165
+ })
166
+
167
+ this.painter.restore()
168
+ return height
169
+ }
170
+
171
+ // 路径
172
+ beginPath() {
173
+ if (this.__region && !this.__onlyView) this.__region.beginPath()
174
+
175
+ if (this.__isPainter && this.__onlyRegion) return this
176
+
177
+ this.painter.beginPath()
178
+ return this
179
+ }
180
+ closePath() {
181
+ if (this.__region && !this.__onlyView) this.__region.closePath()
182
+
183
+ if (this.__isPainter && this.__onlyRegion) return this
184
+
185
+ this.painter.closePath()
186
+ return this
187
+ }
188
+ moveTo(x: number, y: number) {
189
+ if (this.__region && !this.__onlyView) this.__region.moveTo(x, y)
190
+
191
+ if (this.__isPainter && this.__onlyRegion) return this
192
+
193
+ // 解决1px模糊问题,别的地方类似原因
194
+ this.painter.moveTo(Math.round(x) + 0.5, Math.round(y) + 0.5)
195
+ return this
196
+ }
197
+ lineTo(x: number, y: number) {
198
+ if (this.__region && !this.__onlyView) this.__region.lineTo(x, y)
199
+
200
+ if (this.__isPainter && this.__onlyRegion) return this
201
+
202
+ this.painter.lineTo(Math.round(x) + 0.5, Math.round(y) + 0.5)
203
+ return this
204
+ }
205
+ arc(x: number, y: number, r: number, beginDeg: number, deg: number) {
206
+ if (this.__region && !this.__onlyView) this.__region.arc(x, y, r, beginDeg, deg)
207
+
208
+ if (this.__isPainter && this.__onlyRegion) return this
209
+
210
+ this.painter.arc(x, y, r, beginDeg, beginDeg + deg, deg < 0)
211
+ return this
212
+ }
213
+ fill() {
214
+ if (this.__region && !this.__onlyView) this.__region.fill()
215
+
216
+ if (this.__isPainter && this.__onlyRegion) return this
217
+
218
+ this.painter.fill()
219
+ return this
220
+ }
221
+ stroke() {
222
+ if (this.__region && !this.__onlyView) this.__region.stroke()
223
+
224
+ if (this.__isPainter && this.__onlyRegion) return this
225
+
226
+ this.painter.stroke()
227
+ return this
228
+ }
229
+ full() {
230
+ if (this.__region && !this.__onlyView) this.__region.full()
231
+
232
+ if (this.__isPainter && this.__onlyRegion) return this
233
+
234
+ this.painter.fill()
235
+ this.painter.stroke()
236
+ return this
237
+ }
238
+
239
+ save() {
240
+ if (this.__region && !this.__onlyView) this.__region.save()
241
+
242
+ if (this.__isPainter && this.__onlyRegion) return this
243
+
244
+ this.painter.save()
245
+ return this
246
+ }
247
+ restore() {
248
+ if (this.__region && !this.__onlyView) this.__region.restore()
249
+
250
+ if (this.__isPainter && this.__onlyRegion) return this
251
+
252
+ this.painter.restore()
253
+ return this
254
+ }
255
+ clip() {
256
+ if (this.__region && !this.__onlyView) this.__region.clip()
257
+
258
+ if (this.__isPainter && this.__onlyRegion) return this
259
+
260
+ this.painter.clip()
261
+ return this
262
+ }
263
+
264
+ // 路径 - 贝塞尔曲线
265
+ quadraticCurveTo(cpx: number, cpy: number, x: number, y: number) {
266
+ if (this.__region && !this.__onlyView) this.__region.quadraticCurveTo(cpx, cpy, x, y)
267
+
268
+ if (this.__isPainter && this.__onlyRegion) return this
269
+
270
+ this.painter.quadraticCurveTo(cpx, cpy, x, y)
271
+ return this
272
+ }
273
+ bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number) {
274
+ if (this.__region && !this.__onlyView) this.__region.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
275
+
276
+ if (this.__isPainter && this.__onlyRegion) return this
277
+
278
+ this.painter.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
279
+ return this
280
+ }
281
+
282
+ // 擦除画面
283
+ clearRect(x: number, y: number, w: number, h: number) {
284
+ if (this.__region && !this.__onlyView) this.__region.clearRect(x, y, w, h)
285
+
286
+ if (this.__isPainter && this.__onlyRegion) return this
287
+
288
+ this.painter.clearRect(x, y, w, h)
289
+ return this
290
+ }
291
+ clearCircle(cx: number, cy: number, r: number) {
292
+ if (this.__region && !this.__onlyView) this.__region.clearCircle(cx, cy, r)
293
+
294
+ if (this.__isPainter && this.__onlyRegion) return this
295
+
296
+ this.painter.beginPath()
297
+ this.painter.globalCompositeOperation = "destination-out"
298
+ this.painter.arc(cx, cy, r, 0, Math.PI * 2)
299
+ this.painter.fill()
300
+ this.painter.globalCompositeOperation = "source-over"
301
+ this.painter.closePath()
302
+ return this
303
+ }
304
+
305
+ // 弧
306
+ fillArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
307
+ if (this.__region && !this.__onlyView) this.__region.fillArc(cx, cy, r1, r2, beginDeg, deg)
308
+
309
+ if (this.__isPainter && this.__onlyRegion) return this
310
+
311
+ initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg).fill()
312
+ return this
313
+ }
314
+ strokeArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
315
+ if (this.__region && !this.__onlyView) this.__region.strokeArc(cx, cy, r1, r2, beginDeg, deg)
316
+
317
+ if (this.__isPainter && this.__onlyRegion) return this
318
+
319
+ initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg).stroke()
320
+ return this
321
+ }
322
+ fullArc(cx: number, cy: number, r1: number, r2: number, beginDeg: number, deg: number) {
323
+ if (this.__region && !this.__onlyView) this.__region.fullArc(cx, cy, r1, r2, beginDeg, deg)
324
+
325
+ if (this.__isPainter && this.__onlyRegion) return this
326
+
327
+ initArc(this.painter, this.__specialConfig, cx, cy, r1, r2, beginDeg, deg)
328
+ this.painter.fill()
329
+ this.painter.stroke()
330
+ return this
331
+ }
332
+
333
+ // 圆形
334
+ fillCircle(cx: number, cy: number, r: number) {
335
+ if (this.__region && !this.__onlyView) this.__region.fillCircle(cx, cy, r)
336
+
337
+ if (this.__isPainter && this.__onlyRegion) return this
338
+
339
+ initCircle(this.painter, cx, cy, r).fill()
340
+ return this
341
+ }
342
+ strokeCircle(cx: number, cy: number, r: number) {
343
+ if (this.__region && !this.__onlyView) this.__region.strokeCircle(cx, cy, r)
344
+
345
+ if (this.__isPainter && this.__onlyRegion) return this
346
+
347
+ initCircle(this.painter, cx, cy, r).stroke()
348
+ return this
349
+ }
350
+ fullCircle(cx: number, cy: number, r: number) {
351
+ if (this.__region && !this.__onlyView) this.__region.fullCircle(cx, cy, r)
352
+
353
+ if (this.__isPainter && this.__onlyRegion) return this
354
+
355
+ initCircle(this.painter, cx, cy, r)
356
+ this.painter.fill()
357
+ this.painter.stroke()
358
+ return this
359
+ }
360
+
361
+ // 矩形
362
+ fillRect(x: number, y: number, width: number, height: number) {
363
+ if (this.__region && !this.__onlyView) this.__region.fillRect(x, y, width, height)
364
+
365
+ if (this.__isPainter && this.__onlyRegion) return this
366
+
367
+ initRect(this.painter, this.__specialConfig, x, y, width, height).fill()
368
+ return this
369
+ }
370
+ strokeRect(x: number, y: number, width: number, height: number) {
371
+ if (this.__region && !this.__onlyView) this.__region.strokeRect(x, y, width, height)
372
+
373
+ if (this.__isPainter && this.__onlyRegion) return this
374
+
375
+ initRect(this.painter, this.__specialConfig, x, y, width, height).stroke()
376
+ return this
377
+ }
378
+ fullRect(x: number, y: number, width: number, height: number) {
379
+ if (this.__region && !this.__onlyView) this.__region.fullRect(x, y, width, height)
380
+
381
+ if (this.__isPainter && this.__onlyRegion) return this
382
+
383
+ initRect(this.painter, this.__specialConfig, x, y, width, height)
384
+ this.painter.fill()
385
+ this.painter.stroke()
386
+ return this
387
+ }
388
+
389
+ // 渲染绘制(uniapp独有)
390
+ draw() {
391
+
392
+ // 兼容非uniapp环境,防止误用
393
+ // 2024年4月3日 于南京
394
+ return Promise.resolve()
395
+ }
396
+
397
+ // 绘制图片
398
+ drawImage(img: CanvasImageSource | string, x: number, y: number, w: number, h: number, isImage: boolean = false) {
399
+ return new Promise((resolve) => {
400
+ if (this.__region && !this.__onlyView) {
401
+ this.__region.fillRect(x, y, w, h)
402
+ }
403
+
404
+ if (this.__isPainter && this.__onlyRegion) {
405
+ resolve({})
406
+ return
407
+ }
408
+
409
+ if (typeof img == 'string' && !isImage) {
410
+ const imgInstance = new Image()
411
+
412
+ let mat: any = null // 变换矩阵
413
+ if (this.painter.getTransform) mat = this.painter.getTransform()
414
+
415
+ const alpha = this.painter.globalAlpha // 透明度
416
+ const compOp = this.painter.globalCompositeOperation // 混合模式
417
+ const smoothEnable = this.painter.imageSmoothingEnabled // 图像平滑开关
418
+ const smoothQuality = this.painter.imageSmoothingQuality // 图像平滑质量
419
+
420
+ imgInstance.onload = () => {
421
+
422
+ // 修复图片绘制和真正绘制时变换信息不一致问题
423
+ // 2026年10月3日 于大理
424
+ this.painter.save()
425
+ if (mat) this.painter.setTransform(mat)
426
+ this.painter.globalAlpha = alpha
427
+ this.painter.globalCompositeOperation = compOp
428
+ this.painter.imageSmoothingEnabled = smoothEnable
429
+ this.painter.imageSmoothingQuality = smoothQuality
430
+
431
+ this.painter.drawImage(imgInstance, x, y, w, h)
432
+
433
+ this.painter.restore()
434
+ resolve({})
435
+ }
436
+ imgInstance.src = img
437
+ } else {
438
+ this.painter.drawImage(img as CanvasImageSource, x, y, w, h)
439
+ resolve({})
440
+ }
441
+
442
+ })
443
+ }
444
+
445
+ // 转换画布
446
+ translate(dx: number, dy: number) {
447
+ this.painter.translate(dx, dy)
448
+ return this
449
+ }
450
+ rotate(deg: number) {
451
+ this.painter.rotate(deg)
452
+ return this
453
+ }
454
+
455
+ // 扩展绘制方法
456
+ install(methods: {
457
+ [key: string]: Function
458
+ }): any {
459
+ for (const key in methods) {
460
+
461
+ if (key in this) {
462
+ throw new Error("VISLite Canvas:Method already exists and cannot be overwritten.")
463
+ } else {
464
+ (this as any)[key] = (...args: any) => {
465
+ const value = methods[key].apply(this, args)
466
+ if (value != void 0) return value
467
+ return this
468
+ }
469
+ }
470
+
471
+ }
472
+ return this
473
+ }
474
+ }
475
+
455
476
  export default Painter