vislite 1.12.0-alpha.0 → 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 (183) hide show
  1. package/AUTHORS.txt +6 -6
  2. package/CHANGELOG +402 -394
  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 -800
  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 -732
  22. package/lib/RawCanvas/index.es.min.js +1 -1
  23. package/lib/SVG/index.es.js +626 -631
  24. package/lib/SVG/index.es.min.js +1 -1
  25. package/lib/Shader/index.es.js +34 -34
  26. package/lib/Texture/index.es.js +52 -52
  27. package/lib/TreeLayout/index.es.js +301 -315
  28. package/lib/animation/index.es.js +2 -2
  29. package/lib/assemble/index.es.js +19 -16
  30. package/lib/assemble/index.es.min.js +1 -1
  31. package/lib/getLoopColors/index.es.js +34 -34
  32. package/lib/getWebGLContext/index.es.js +61 -61
  33. package/lib/index.umd.js +2797 -2784
  34. package/lib/index.umd.min.js +2 -2
  35. package/lib/initOption/index.es.js +5 -5
  36. package/lib/mergeOption/index.es.js +34 -34
  37. package/lib/move/index.es.js +6 -6
  38. package/lib/rotate/index.es.js +6 -6
  39. package/lib/ruler/index.es.js +136 -136
  40. package/lib/scale/index.es.js +5 -5
  41. package/minialipay/ui-canvas/drawImage.js +35 -35
  42. package/minialipay/ui-canvas/index.acss +4 -4
  43. package/minialipay/ui-canvas/index.axml +3 -3
  44. package/minialipay/ui-canvas/index.d.ts +1 -1
  45. package/minialipay/ui-canvas/index.js +100 -100
  46. package/minialipay/ui-canvas/index.json +6 -6
  47. package/miniprogram/ui-canvas/drawImage.js +35 -35
  48. package/miniprogram/ui-canvas/index.js +125 -125
  49. package/miniprogram/ui-canvas/index.json +4 -4
  50. package/miniprogram/ui-canvas/index.wxml +4 -4
  51. package/miniprogram/ui-canvas/index.wxss +5 -5
  52. package/package/BarLayout/index.ts +2 -2
  53. package/package/Buffer/index.ts +2 -2
  54. package/package/Canvas/index.ts +2 -2
  55. package/package/Cardinal/index.ts +2 -2
  56. package/package/Eoap/index.ts +2 -2
  57. package/package/Hermite/index.ts +2 -2
  58. package/package/MapCoordinate/index.ts +2 -2
  59. package/package/Matrix4/index.ts +2 -2
  60. package/package/Mercator/index.ts +2 -2
  61. package/package/PieLayout/index.ts +2 -2
  62. package/package/RawCanvas/index.ts +2 -2
  63. package/package/SVG/index.ts +2 -2
  64. package/package/Shader/index.ts +2 -2
  65. package/package/Texture/index.ts +2 -2
  66. package/package/TreeLayout/index.ts +2 -2
  67. package/package/animation/index.ts +5 -5
  68. package/package/assemble/index.ts +2 -2
  69. package/package/getLoopColors/index.ts +2 -2
  70. package/package/getWebGLContext/index.ts +40 -40
  71. package/package/index.ts +84 -84
  72. package/package/initOption/index.ts +2 -2
  73. package/package/mergeOption/index.ts +2 -2
  74. package/package/move/index.ts +2 -2
  75. package/package/rotate/index.ts +2 -2
  76. package/package/ruler/index.ts +2 -2
  77. package/package/scale/index.ts +2 -2
  78. package/package/throttle/index.ts +2 -2
  79. package/package.json +79 -79
  80. package/skills/vislite-lib/BarLayout.md +117 -117
  81. package/skills/vislite-lib/Canvas.md +183 -183
  82. package/skills/vislite-lib/Interpolation.md +129 -129
  83. package/skills/vislite-lib/Matrix.md +174 -174
  84. package/skills/vislite-lib/PieLayout.md +131 -131
  85. package/skills/vislite-lib/Projections.md +158 -158
  86. package/skills/vislite-lib/SKILL.md +179 -179
  87. package/skills/vislite-lib/SVG.md +137 -137
  88. package/skills/vislite-lib/TreeLayout.md +176 -176
  89. package/skills/vislite-lib/Utilities.md +261 -261
  90. package/skills/vislite-lib/WebGL.md +106 -106
  91. package/skills/vislite-lib/minialipay/ui-canvas.md +95 -95
  92. package/skills/vislite-lib/miniprogram/ui-canvas.md +98 -98
  93. package/skills/vislite-lib/uniapp/ui-canvas.md +113 -113
  94. package/src/Canvas.ts +89 -89
  95. package/src/Eoap.ts +66 -66
  96. package/src/Matrix4/index.ts +84 -84
  97. package/src/Matrix4/move.ts +12 -12
  98. package/src/Matrix4/rotate.ts +15 -15
  99. package/src/Matrix4/scale.ts +11 -11
  100. package/src/Matrix4/transform.ts +64 -64
  101. package/src/Mercator.ts +27 -27
  102. package/src/SVG.ts +86 -69
  103. package/src/common/assemble.ts +30 -22
  104. package/src/common/canvas/arc.ts +51 -51
  105. package/src/common/canvas/config.ts +176 -176
  106. package/src/common/canvas/default.ts +64 -64
  107. package/src/common/canvas/gradient.ts +31 -31
  108. package/src/common/canvas/index.ts +189 -189
  109. package/src/common/canvas/painter.ts +475 -454
  110. package/src/common/canvas/texts.ts +18 -18
  111. package/src/common/map/getBoundary.ts +15 -15
  112. package/src/common/map/tool.ts +29 -29
  113. package/src/common/option.ts +31 -31
  114. package/src/common/setStyle.ts +5 -5
  115. package/src/common/svg/config.ts +213 -213
  116. package/src/common/svg/default.ts +29 -29
  117. package/src/common/svg/gradient.ts +53 -53
  118. package/src/common/svg/index.ts +420 -420
  119. package/src/common/svg/tool.ts +51 -51
  120. package/src/common/tree/index.ts +25 -25
  121. package/src/common/tree/toInnerTree.ts +61 -61
  122. package/src/common/tree/toPlainTree.ts +135 -135
  123. package/src/common/type.ts +26 -26
  124. package/src/common/webgl/buffer.ts +79 -79
  125. package/src/common/webgl/getWebGLContext.ts +45 -45
  126. package/src/common/webgl/shader.ts +75 -75
  127. package/src/common/webgl/texture.ts +98 -98
  128. package/src/coordinate/MapCoordinate.ts +80 -80
  129. package/src/getLoopColors.ts +42 -42
  130. package/src/interpolation/Cardinal.ts +110 -110
  131. package/src/interpolation/Hermite.ts +65 -65
  132. package/src/layout/BarLayout.ts +249 -249
  133. package/src/layout/PieLayout.ts +146 -146
  134. package/src/layout/TreeLayout.ts +200 -200
  135. package/src/move.ts +7 -7
  136. package/src/rotate.ts +7 -7
  137. package/src/ruler.ts +209 -209
  138. package/src/scale.ts +6 -6
  139. package/types/Bar.d.ts +91 -91
  140. package/types/BarConfig.d.ts +4 -4
  141. package/types/BarLayout.d.ts +48 -48
  142. package/types/BarOption.d.ts +31 -31
  143. package/types/Buffer.d.ts +30 -30
  144. package/types/Canvas.d.ts +379 -379
  145. package/types/CanvasConfig.d.ts +61 -61
  146. package/types/CanvasOption.d.ts +13 -13
  147. package/types/CanvasOpts.d.ts +9 -9
  148. package/types/Cardinal.d.ts +20 -20
  149. package/types/Gradient.d.ts +20 -20
  150. package/types/Hermite.d.ts +25 -25
  151. package/types/Map.d.ts +9 -9
  152. package/types/MapConfig.d.ts +27 -27
  153. package/types/MapCoordinate.d.ts +22 -22
  154. package/types/Matrix4.d.ts +79 -79
  155. package/types/Pie.d.ts +73 -73
  156. package/types/PieConfig.d.ts +26 -26
  157. package/types/PieLayout.d.ts +40 -40
  158. package/types/PieOption.d.ts +21 -21
  159. package/types/SVG.d.ts +282 -282
  160. package/types/SVGConfig.d.ts +54 -54
  161. package/types/Shader.d.ts +22 -22
  162. package/types/Texture.d.ts +22 -22
  163. package/types/Tree.d.ts +74 -74
  164. package/types/TreeConfig.d.ts +52 -52
  165. package/types/TreeLayout.d.ts +71 -71
  166. package/types/TreeOption.d.ts +48 -48
  167. package/types/animation.d.ts +26 -26
  168. package/types/assemble.d.ts +14 -14
  169. package/types/getLoopColors.d.ts +13 -13
  170. package/types/getWebGLContext.d.ts +7 -7
  171. package/types/index.d.ts +220 -221
  172. package/types/module.d.ts +110 -110
  173. package/types/move.d.ts +15 -15
  174. package/types/option.d.ts +12 -12
  175. package/types/painterConfig.d.ts +14 -14
  176. package/types/rotate.d.ts +15 -15
  177. package/types/ruler.d.ts +24 -24
  178. package/types/scale.d.ts +15 -15
  179. package/types/throttle.d.ts +6 -6
  180. package/types/ui-canvas.d.ts +4 -4
  181. package/types/uni-canvas.d.ts +3 -3
  182. package/uni-app/drawImage.js +19 -19
  183. 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