@leafer/canvas-web 1.0.0-alpha.23 → 1.0.0-alpha.31

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer/canvas-web",
3
- "version": "1.0.0-alpha.23",
3
+ "version": "1.0.0-alpha.31",
4
4
  "description": "@leafer/canvas-web",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -19,11 +19,11 @@
19
19
  "leaferjs"
20
20
  ],
21
21
  "dependencies": {
22
- "@leafer/math": "1.0.0-alpha.23",
23
- "@leafer/event": "1.0.0-alpha.23",
24
- "@leafer/debug": "1.0.0-alpha.23"
22
+ "@leafer/math": "1.0.0-alpha.31",
23
+ "@leafer/event": "1.0.0-alpha.31",
24
+ "@leafer/debug": "1.0.0-alpha.31"
25
25
  },
26
26
  "devDependencies": {
27
- "@leafer/interface": "1.0.0-alpha.23"
27
+ "@leafer/interface": "1.0.0-alpha.31"
28
28
  }
29
29
  }
@@ -1,81 +1,63 @@
1
- import { IBounds, ILeaferCanvas, ICanvasStrokeOptions, ICanvasContext2D, ILeaferCanvasConfig, IMatrixData, IBoundsData, IAutoBounds, ISizeData, IScreenSizeData, IResizeEventListener, IMatrixWithBoundsData, IPointData, InnerId, ICanvasManager, IWindingRule } from '@leafer/interface'
2
- import { Bounds, BoundsHelper, IncrementId } from '@leafer/math'
1
+ import { ICanvasContext2D, IAutoBounds, ISizeData, IScreenSizeData, IResizeEventListener } from '@leafer/interface'
3
2
  import { ResizeEvent } from '@leafer/event'
4
- import { Platform } from '@leafer/platform'
3
+ import { LeaferCanvasBase, canvasSizeAttrs } from '@leafer/canvas'
4
+ import { DataHelper } from '@leafer/data'
5
5
  import { Debug } from '@leafer/debug'
6
6
 
7
- import { CanvasBase } from './CanvasBase'
8
-
9
7
 
10
8
  const debug = Debug.get('LeaferCanvas')
11
9
 
12
- const temp = new Bounds()
13
- const minSize: IScreenSizeData = {
14
- width: 1,
15
- height: 1,
16
- pixelRatio: 1
17
- }
18
-
19
- export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
20
-
21
- public manager: ICanvasManager
22
-
23
- public readonly innerId: InnerId
24
-
25
- public pixelRatio: number
26
- public get pixelWidth(): number { return this.width * this.pixelRatio }
27
- public get pixelHeight(): number { return this.height * this.pixelRatio }
28
-
29
- public bounds: IBounds
10
+ export class LeaferCanvas extends LeaferCanvasBase {
30
11
 
31
12
  public view: HTMLCanvasElement | OffscreenCanvas
32
13
  public parentView: HTMLElement
33
14
 
34
- public offscreen: boolean
35
-
36
- public recycled?: boolean
37
-
38
15
  protected resizeObserver: ResizeObserver
16
+ protected autoBounds: IAutoBounds
17
+ protected resizeListener: IResizeEventListener
39
18
 
40
- protected savedblendMode: string
41
-
42
- constructor(config?: ILeaferCanvasConfig, manager?: ICanvasManager) {
43
- super()
44
-
45
- if (!config) config = minSize
46
- if (!config.pixelRatio) config.pixelRatio = devicePixelRatio
47
-
48
- this.manager = manager
49
- this.innerId = IncrementId.create(IncrementId.CNAVAS)
50
-
51
- const { view, width, height, pixelRatio, fill, hittable } = config
52
- const autoLayout = !width || !height
53
-
54
- this.pixelRatio = pixelRatio
55
- this.offscreen = Platform.isWorker || config.offscreen
19
+ public init(): void {
20
+ const { view } = this.config
56
21
 
57
22
  if (this.offscreen) {
58
23
  view ? this.view = view as OffscreenCanvas : this.__createView()
59
24
  } else {
60
25
  view ? this.__createViewFrom(view) : this.__createView()
61
26
  const { style } = this.view as HTMLCanvasElement
62
- if (fill) style.backgroundColor = fill
63
- if (!hittable) style.pointerEvents = 'none'
64
- if (autoLayout) style.display || (style.display = 'block')
27
+ if (this.autoLayout) style.display || (style.display = 'block')
65
28
  this.parentView = (this.view as HTMLCanvasElement).parentElement
66
29
  }
67
30
 
68
- this.__init()
69
- if (!autoLayout) this.resize(config as IScreenSizeData)
31
+ this.__createContext()
32
+
33
+ if (!this.autoLayout) this.resize(this.config as IScreenSizeData)
34
+ }
35
+
36
+ public setBackgroundColor(color: string): void {
37
+ const view = this.view as HTMLElement
38
+ view.style.backgroundColor = color
70
39
  }
71
40
 
72
- protected __init(): void {
41
+ public setHittable(hittable: boolean): void {
42
+ const view = this.view as HTMLElement
43
+ view.style.pointerEvents = hittable ? 'auto' : 'none'
44
+ }
45
+
46
+ protected __createContext(): void {
73
47
  this.context = this.view.getContext('2d') as ICanvasContext2D
74
48
  this.__bindContext()
75
49
  }
76
50
 
77
51
  protected __createView(): void {
78
- this.view = this.offscreen ? new OffscreenCanvas(1, 1) : document.createElement('canvas')
52
+ if (this.offscreen) {
53
+ try {
54
+ this.view = new OffscreenCanvas(1, 1)
55
+ return
56
+ } catch (e) {
57
+ debug.error(e)
58
+ }
59
+ }
60
+ this.view = document.createElement('canvas')
79
61
  }
80
62
 
81
63
  protected __createViewFrom(inputView: string | object): void {
@@ -110,77 +92,13 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
110
92
  parent.appendChild(view)
111
93
  }
112
94
  } else {
113
- debug.error(`can't find view by id: ${inputView}`)
95
+ debug.error(`no id: ${inputView}`)
114
96
  this.__createView()
115
97
  }
116
98
  }
117
99
 
118
- public debug(): void {
119
- const panel = document.createElement('div')
120
- panel.style.position = 'absolute'
121
- panel.style.top = '10px'
122
- panel.style.left = '10px'
123
- panel.style.transform = 'scale(0.5)'
124
- panel.style.transformOrigin = '0px 0px'
125
- panel.style.pointerEvents = 'none'
126
- panel.style.zIndex = '100'
127
- document.body.appendChild(panel)
128
- panel.appendChild(this.view as HTMLCanvasElement)
129
- }
130
-
131
- public pixel(num: number): number { return num * this.pixelRatio }
132
-
133
- public startAutoLayout(autoBounds: IAutoBounds, listener: IResizeEventListener): void {
134
- if (!this.offscreen) {
135
- const view = this.view as HTMLCanvasElement
136
- const check = (parentSize: ISizeData) => {
137
- const { x, y, width, height } = autoBounds.getBoundsFrom(parentSize)
138
- const { style } = view
139
- style.marginLeft = x + 'px'
140
- style.marginTop = y + 'px'
141
-
142
- if (width !== this.width || height !== this.height) {
143
- const { pixelRatio } = this
144
- const size = { width, height, pixelRatio }
145
- const oldSize = { width: this.width, height: this.height, pixelRatio: this.pixelRatio }
146
- this.resize(size)
147
- if (this.width !== undefined) listener(new ResizeEvent(size, oldSize))
148
- }
149
- }
150
-
151
- this.resizeObserver = new ResizeObserver((entries) => {
152
- for (const entry of entries) {
153
- check(entry.contentRect)
154
- }
155
- })
156
-
157
- const parent = this.parentView
158
- if (parent) {
159
- this.resizeObserver.observe(parent)
160
- check(parent.getBoundingClientRect())
161
- }
162
- }
163
- }
164
-
165
- public stopAutoLayout(): void {
166
- if (this.resizeObserver) {
167
- this.resizeObserver.disconnect()
168
- this.resizeObserver = null
169
- }
170
- }
171
-
172
- public resize(size: IScreenSizeData): void {
100
+ public setViewSize(size: IScreenSizeData): void {
173
101
  const { width, height, pixelRatio } = size
174
- if (this.isSameSize(size)) return
175
-
176
- let takeCanvas: ILeaferCanvas
177
- if (this.context && this.width) {
178
- takeCanvas = this.getSameCanvas()
179
- takeCanvas.copyWorld(this)
180
- }
181
-
182
- Object.assign(this, { width, height, pixelRatio })
183
- this.bounds = new Bounds(0, 0, width, height)
184
102
 
185
103
  if (!this.offscreen) {
186
104
  const { style } = this.view as HTMLCanvasElement
@@ -190,217 +108,82 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
190
108
 
191
109
  this.view.width = width * pixelRatio
192
110
  this.view.height = height * pixelRatio
193
- this.smooth = false
194
-
195
- if (this.context && takeCanvas) {
196
- this.copyWorld(takeCanvas)
197
- takeCanvas.recycle()
198
- }
199
- }
200
-
201
- public saveBlendMode(blendMode: string): void {
202
- this.savedblendMode = this.blendMode
203
- this.blendMode = blendMode
204
111
  }
205
112
 
206
- public restoreBlendMode(): void {
207
- this.blendMode = this.savedblendMode
208
- }
113
+ public startAutoLayout(autoBounds: IAutoBounds, listener: IResizeEventListener): void {
114
+ if (!this.offscreen) {
115
+ this.autoBounds = autoBounds
116
+ this.resizeListener = listener
117
+ try {
118
+
119
+ this.resizeObserver = new ResizeObserver((entries) => {
120
+ for (const entry of entries) this.checkAutoBounds(entry.contentRect)
121
+ })
122
+
123
+ const parent = this.parentView
124
+ if (parent) {
125
+ this.resizeObserver.observe(parent)
126
+ this.checkAutoBounds(parent.getBoundingClientRect())
127
+ }
209
128
 
210
- public setWorld(matrix: IMatrixData, parentMatrix?: IMatrixData, onlyTranslate?: boolean): void {
211
- const { pixelRatio } = this
212
- if (parentMatrix) {
213
-
214
- if (onlyTranslate) {
215
- this.setTransform(
216
- matrix.a * pixelRatio,
217
- matrix.b * pixelRatio,
218
- matrix.c * pixelRatio,
219
- matrix.d * pixelRatio,
220
- (matrix.e + parentMatrix.e) * pixelRatio,
221
- (matrix.f + parentMatrix.f) * pixelRatio
222
- )
223
- } else {
224
- const { a, b, c, d, e, f } = parentMatrix
225
- this.setTransform(
226
- ((matrix.a * a) + (matrix.b * c)) * pixelRatio,
227
- ((matrix.a * b) + (matrix.b * d)) * pixelRatio,
228
- ((matrix.c * a) + (matrix.d * c)) * pixelRatio,
229
- ((matrix.c * b) + (matrix.d * d)) * pixelRatio,
230
- (((matrix.e * a) + (matrix.f * c) + e)) * pixelRatio,
231
- (((matrix.e * b) + (matrix.f * d) + f)) * pixelRatio
232
- )
233
- }
129
+ } catch (e) {
234
130
 
235
- } else {
131
+ this.imitateResizeObserver()
236
132
 
237
- this.setTransform(
238
- matrix.a * pixelRatio,
239
- matrix.b * pixelRatio,
240
- matrix.c * pixelRatio,
241
- matrix.d * pixelRatio,
242
- matrix.e * pixelRatio,
243
- matrix.f * pixelRatio
244
- )
133
+ }
245
134
  }
246
135
  }
247
136
 
248
- public useSameTransform(canvas: ILeaferCanvas): void {
249
- this.setTransform(canvas.getTransform())
250
- }
251
-
252
-
253
- public setStroke(strokeStyle: string | object, strokeWidth: number, options?: ICanvasStrokeOptions): void {
254
-
255
- if (strokeWidth) this.strokeWidth = strokeWidth
256
- if (strokeStyle) this.strokeStyle = strokeStyle
257
- if (options) {
258
- this.strokeCap = options.strokeCap
259
- this.strokeJoin = options.strokeJoin
260
- this.dashPattern = options.dashPattern
261
- this.dashOffset = options.dashOffset
262
- this.miterLimit = options.miterLimit
137
+ protected imitateResizeObserver(): void {
138
+ if (this.autoLayout) {
139
+ if (this.parentView) this.checkAutoBounds(this.parentView.getBoundingClientRect())
140
+ window.requestAnimationFrame(this.imitateResizeObserver.bind(this))
263
141
  }
264
142
  }
265
143
 
266
- public hitFill(point: IPointData, fillRule?: IWindingRule): boolean {
267
- return this.context.isPointInPath(point.x, point.y, fillRule)
268
- }
269
-
270
- public hitStroke(point: IPointData): boolean {
271
- return this.context.isPointInStroke(point.x, point.y)
272
- }
273
-
274
-
275
- public setWorldShadow(x: number, y: number, blur: number, color?: string): void {
276
- const { pixelRatio } = this
277
- this.shadowOffsetX = x * pixelRatio
278
- this.shadowOffsetY = y * pixelRatio
279
- this.shadowBlur = blur * pixelRatio
280
- this.shadowColor = color || 'black'
281
- }
282
-
283
- public setWorldBlur(blur: number): void {
284
- const { pixelRatio } = this
285
- this.filter = `blur(${blur * pixelRatio}px)`
286
- }
287
-
288
-
289
- public copyWorld(canvas: ILeaferCanvas, from?: IBoundsData, to?: IBoundsData, blendMode?: string): void {
290
- if (blendMode) this.blendMode = blendMode
291
- if (from) {
144
+ protected checkAutoBounds(parentSize: ISizeData): void {
145
+ const view = this.view as HTMLCanvasElement
146
+ const { x, y, width, height } = this.autoBounds.getBoundsFrom(parentSize)
147
+ if (width !== this.width || height !== this.height) {
148
+ const { style } = view
292
149
  const { pixelRatio } = this
293
- if (!to) to = from
294
- this.drawImage(canvas.view as HTMLCanvasElement, from.x * pixelRatio, from.y * pixelRatio, from.width * pixelRatio, from.height * pixelRatio, to.x * pixelRatio, to.y * pixelRatio, to.width * pixelRatio, to.height * pixelRatio)
295
- } else {
296
- this.drawImage(canvas.view as HTMLCanvasElement, 0, 0)
150
+ style.marginLeft = x + 'px'
151
+ style.marginTop = y + 'px'
152
+ const size = { width, height, pixelRatio }
153
+ const oldSize = {} as IScreenSizeData
154
+ DataHelper.copyAttrs(oldSize, this, canvasSizeAttrs)
155
+ this.resize(size)
156
+ if (this.width !== undefined) this.resizeListener(new ResizeEvent(size, oldSize))
297
157
  }
298
- if (blendMode) this.blendMode = 'normal'
299
158
  }
300
159
 
301
- public copyWorldToInner(canvas: ILeaferCanvas, fromWorld: IMatrixWithBoundsData, toInnerBounds: IBoundsData, blendMode?: string): void {
302
- if (blendMode) this.blendMode = blendMode
303
- if (fromWorld.b || fromWorld.c) {
304
- this.save()
305
- this.resetTransform()
306
- this.copyWorld(canvas, fromWorld, BoundsHelper.tempToOuterOf(toInnerBounds, fromWorld))
307
- this.restore()
308
- } else {
309
- const { pixelRatio } = this
310
- this.drawImage(canvas.view as HTMLCanvasElement, fromWorld.x * pixelRatio, fromWorld.y * pixelRatio, fromWorld.width * pixelRatio, fromWorld.height * pixelRatio, toInnerBounds.x, toInnerBounds.y, toInnerBounds.width, toInnerBounds.height)
160
+ public stopAutoLayout(): void {
161
+ this.autoLayout = false
162
+ this.resizeListener = null
163
+ if (this.resizeObserver) {
164
+ this.resizeObserver.disconnect()
165
+ this.resizeObserver = null
311
166
  }
312
- if (blendMode) this.blendMode = 'normal'
313
- }
314
-
315
- public fillWorld(bounds: IBoundsData, color: string | object, blendMode?: string): void {
316
- if (blendMode) this.blendMode = blendMode
317
- this.fillStyle = color
318
- temp.copy(bounds).scale(this.pixelRatio)
319
- this.fillRect(temp.x, temp.y, temp.width, temp.height)
320
- if (blendMode) this.blendMode = 'normal'
321
- }
322
-
323
- public strokeWorld(bounds: IBoundsData, color: string | object, blendMode?: string): void {
324
- if (blendMode) this.blendMode = blendMode
325
- this.strokeStyle = color
326
- temp.copy(bounds).scale(this.pixelRatio)
327
- this.strokeRect(temp.x, temp.y, temp.width, temp.height)
328
- if (blendMode) this.blendMode = 'normal'
329
- }
330
-
331
- public clearWorld(bounds: IBoundsData, ceilPixel?: boolean): void {
332
- temp.copy(bounds).scale(this.pixelRatio)
333
- if (ceilPixel) temp.ceil()
334
- this.clearRect(temp.x, temp.y, temp.width, temp.height)
335
167
  }
336
168
 
337
- public clipWorld(bounds: IBoundsData, ceilPixel?: boolean): void {
338
- this.beginPath()
339
- temp.copy(bounds).scale(this.pixelRatio)
340
- if (ceilPixel) temp.ceil()
341
- this.rect(temp.x, temp.y, temp.width, temp.height)
342
- this.clip()
343
-
344
- }
345
-
346
- public clear(): void {
347
- const { pixelRatio } = this
348
- this.clearRect(0, 0, this.width * pixelRatio, this.height * pixelRatio)
349
- }
350
-
351
-
352
- // other
353
-
354
- public isSameSize(size: IScreenSizeData): boolean {
355
- return this.width === size.width && this.height === size.height && this.pixelRatio === size.pixelRatio
356
- }
357
-
358
- // 需要有 manager变量
359
- public getSameCanvas(useSameTransform?: boolean): ILeaferCanvas {
360
- const { width, height, pixelRatio } = this
361
- const canvas = this.manager.get({ width, height, pixelRatio })
362
- canvas.manager || (canvas.manager = this.manager)
363
- canvas.save()
364
- if (useSameTransform) canvas.useSameTransform(this)
365
- return canvas
366
- }
367
-
368
- public getBiggerCanvas(addWidth: number, addHeight: number): ILeaferCanvas {
369
- let { width, height, pixelRatio } = this
370
- if (addWidth) width += addWidth
371
- if (addHeight) height += addHeight
372
- const canvas = this.manager.get({ width, height, pixelRatio })
373
- canvas.manager || (canvas.manager = this.manager)
374
- canvas.save()
375
- return canvas
376
- }
377
-
378
- public recycle(): void {
379
- this.restore()
380
- this.manager.recycle(this)
381
- }
382
-
383
- public unloadView(): void {
384
- if (this.parentView) {
169
+ public unrealCanvas(): void { // App needs to use
170
+ if (!this.unreal && this.parentView) {
385
171
  const view = this.view as HTMLCanvasElement
386
- const fill = view.style.backgroundColor
387
- if (fill) this.parentView.style.backgroundColor = fill
388
- view.remove() // App needs to use
172
+ if (view) view.remove()
173
+
174
+ this.view = this.parentView as HTMLCanvasElement
175
+ this.unreal = true
389
176
  }
390
177
  }
391
178
 
392
179
  public destroy(): void {
393
180
  if (this.view) {
394
- super.destroy()
395
181
  this.stopAutoLayout()
396
- if (!this.offscreen) {
182
+ if (!this.unreal && !this.offscreen) {
397
183
  const view = this.view as HTMLCanvasElement
398
184
  if (view.parentElement) view.remove()
399
185
  }
400
- this.manager = null
401
- this.view = null
402
- this.parentView = null
403
- this.context = null
186
+ super.destroy()
404
187
  }
405
188
  }
406
189
 
@@ -1,61 +1,16 @@
1
- import { IObject } from '@leafer/interface'
1
+ import { IObject, IPathDrawer } from '@leafer/interface'
2
+ import { RectHelper } from '@leafer/path'
2
3
 
3
4
 
5
+ const { drawRoundRect } = RectHelper
6
+
4
7
  export function roundRect(): void {
5
8
 
6
9
  if (!(CanvasRenderingContext2D.prototype as IObject).roundRect) {
7
10
 
8
- (CanvasRenderingContext2D.prototype as IObject).roundRect = (Path2D.prototype as IObject).roundRect = function (x: number, y: number, w: number, h: number, r: number | number[]): void {
9
-
10
- let topLeft: number, topRight: number, bottomRight: number, bottomLeft: number
11
-
12
- if (r instanceof Array) {
13
- switch (r.length) {
14
- case 4:
15
- topLeft = r[0]
16
- topRight = r[1]
17
- bottomRight = r[2]
18
- bottomLeft = r[3]
19
- break
20
- case 2:
21
- topLeft = bottomRight = r[0]
22
- topRight = bottomLeft = r[1]
23
- break
24
- case 3:
25
- topLeft = r[0]
26
- topRight = bottomLeft = r[1]
27
- bottomRight = r[2]
28
- break
29
- case 1:
30
- r = r[0]
31
- break
32
- default:
33
- r = 0
34
- }
35
- }
36
-
37
- if (topLeft === undefined) {
38
- if (r) {
39
- topLeft = topRight = bottomRight = bottomLeft = r as number
40
- } else {
41
- this.rect(x, y, w, h)
42
- return
43
- }
44
- }
45
-
46
- const max = Math.min(w / 2, h / 2)
47
- if (topLeft > max) topLeft = max
48
- if (topRight > max) topRight = max
49
- if (bottomRight > max) bottomRight = max
50
- if (bottomLeft > max) bottomLeft = max
51
-
52
- const R = this
53
- topLeft ? R.moveTo(x + topLeft, y) : R.moveTo(x, y)
54
- topRight ? R.arcTo(x + w, y, x + w, y + h, topRight) : R.lineTo(x + w, y)
55
- bottomRight ? R.arcTo(x + w, y + h, x, y + h, bottomRight) : R.lineTo(x + w, y + h)
56
- bottomLeft ? R.arcTo(x, y + h, x, y, bottomLeft) : R.lineTo(x, y + h)
57
- topLeft ? R.arcTo(x, y, x + w, y, topLeft) : R.lineTo(x, y)
58
- R.closePath()
11
+ (CanvasRenderingContext2D.prototype as IObject).roundRect = (Path2D.prototype as IObject).roundRect = function (x: number, y: number, width: number, height: number, cornerRadius: number | number[]): void {
12
+
13
+ drawRoundRect(this as IPathDrawer, x, y, width, height, cornerRadius)
59
14
  }
60
15
  }
61
16
 
package/src/CanvasBase.ts DELETED
@@ -1,280 +0,0 @@
1
- import { ICanvasAttr, ITextMetrics, ICanvasContext2D, IPath2D, IObject, InnerId, IMatrixData, IFunction, IWindingRule } from '@leafer/interface'
2
-
3
-
4
- function contextAttr(realName?: string) {
5
- return (target: CanvasBase, key: string) => {
6
- if (!realName) realName = key
7
- const property: IObject & ThisType<CanvasBase> = {
8
- get() { return (this.context as IObject)[realName] },
9
- set(value: unknown) { (this.context as IObject)[realName] = value }
10
- }
11
- Object.defineProperty(target, key, property)
12
- }
13
- }
14
-
15
- const contextMethodNameList: string[] = []
16
- function contextMethod() {
17
- return (_target: CanvasBase, key: string) => {
18
- contextMethodNameList.push(key)
19
- }
20
- }
21
-
22
- const emptyArray: number[] = []
23
-
24
- export class CanvasBase {
25
-
26
- public readonly innerId: InnerId
27
-
28
- public width: number
29
- public height: number
30
-
31
- public __: ICanvasAttr
32
-
33
- public context: ICanvasContext2D
34
-
35
- // canvas attr
36
-
37
- @contextAttr('imageSmoothingEnabled')
38
- public smooth: boolean
39
-
40
- @contextAttr('imageSmoothingQuality')
41
- public smoothLevel: ImageSmoothingQuality
42
-
43
- @contextAttr('globalAlpha')
44
- public opacity: number
45
-
46
- @contextAttr('globalCompositeOperation')
47
- public blendMode: string
48
-
49
-
50
- @contextAttr()
51
- public fillStyle: string | object
52
-
53
- @contextAttr()
54
- public strokeStyle: string | object
55
-
56
-
57
- @contextAttr('lineWidth')
58
- public strokeWidth: number
59
-
60
- @contextAttr('lineCap')
61
- public strokeCap: string
62
-
63
- @contextAttr('lineJoin')
64
- public strokeJoin: string
65
-
66
- public set dashPattern(value: number[]) {
67
- this.context.setLineDash(value || emptyArray)
68
- }
69
- public get dashPattern(): number[] {
70
- return this.context.getLineDash()
71
- }
72
-
73
- @contextAttr('lineDashOffset')
74
- public dashOffset: number
75
-
76
- @contextAttr()
77
- public miterLimit: number
78
-
79
-
80
- @contextAttr()
81
- public shadowBlur: number
82
-
83
- @contextAttr()
84
- public shadowColor: string
85
-
86
- @contextAttr()
87
- public shadowOffsetX: number
88
-
89
- @contextAttr()
90
- public shadowOffsetY: number
91
-
92
- @contextAttr()
93
- public filter: string
94
-
95
-
96
- @contextAttr()
97
- public font: string
98
-
99
- @contextAttr()
100
- public fontKerning: string
101
-
102
- @contextAttr()
103
- public fontStretch: string
104
-
105
- @contextAttr()
106
- public fontVariantCaps: string
107
-
108
-
109
- @contextAttr()
110
- public textAlign: string
111
-
112
- @contextAttr()
113
- public textBaseline: string
114
-
115
- @contextAttr()
116
- public textRendering: string
117
-
118
- @contextAttr()
119
- public wordSpacing: string
120
-
121
- @contextAttr()
122
- public letterSpacing: string
123
-
124
-
125
- @contextAttr()
126
- public direction: string
127
-
128
- // end
129
-
130
- public __bindContext(): void {
131
- let method: IFunction
132
- contextMethodNameList.forEach(name => {
133
- method = (this.context as IObject)[name]
134
- if (method) (this as IObject)[name] = method.bind(this.context)
135
- })
136
- }
137
-
138
- // canvas method
139
-
140
- @contextMethod()
141
- public setTransform(_a: number | IMatrixData, _b?: number, _c?: number, _d?: number, _e?: number, _f?: number): void { }
142
-
143
- @contextMethod()
144
- public resetTransform(): void { }
145
-
146
- @contextMethod()
147
- public getTransform(): IMatrixData { return void 0 }
148
-
149
- @contextMethod()
150
- public save(): void { }
151
-
152
- @contextMethod()
153
- public restore(): void { }
154
-
155
- @contextMethod()
156
- public transform(_a: number, _b: number, _c: number, _d: number, _e: number, _f: number): void { }
157
-
158
- @contextMethod()
159
- public translate(_x: number, _y: number): void { }
160
-
161
- @contextMethod()
162
- public scale(_x: number, _y: number): void { }
163
-
164
- @contextMethod()
165
- public rotate(_angle: number): void { }
166
-
167
- @contextMethod()
168
- public fill(_path2d?: IPath2D | IWindingRule, _rule?: IWindingRule): void { }
169
-
170
- @contextMethod()
171
- public stroke(_path2d?: IPath2D): void { }
172
-
173
- @contextMethod()
174
- public clip(_path2d?: IPath2D | IWindingRule, _rule?: IWindingRule): void { }
175
-
176
- @contextMethod()
177
- public fillRect(_x: number, _y: number, _width: number, _height: number): void { }
178
-
179
- @contextMethod()
180
- public strokeRect(_x: number, _y: number, _width: number, _height: number): void { }
181
-
182
- @contextMethod()
183
- public clearRect(_x: number, _y: number, _width: number, _height: number): void { }
184
-
185
- public drawImage(image: CanvasImageSource, sx: number, sy: number, sw?: number, sh?: number, dx?: number, dy?: number, dw?: number, dh?: number): void {
186
- switch (arguments.length) {
187
- case 9:
188
-
189
- // safari: drawimage裁剪画布外的坐标会有问题, 必须是不小于0的坐标点
190
- if (sx < 0) {
191
- const d = (-sx / sw) * dw
192
- sw += sx
193
- sx = 0
194
- dx += d
195
- dw -= d
196
- }
197
-
198
- if (sy < 0) {
199
- const d = (-sy / sh) * dh
200
- sh += sy
201
- sy = 0
202
- dy += d
203
- dh -= d
204
- }
205
-
206
- this.context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
207
- break
208
- case 5:
209
- this.context.drawImage(image, sx, sy, sw, sh) // = dx, dy, dw, dh
210
- break
211
- case 3:
212
- this.context.drawImage(image, sx, sy)
213
- }
214
- }
215
-
216
-
217
- // canvas draw
218
- @contextMethod()
219
- public beginPath(): void { }
220
-
221
- @contextMethod()
222
- public moveTo(_x: number, _y: number): void { }
223
-
224
- @contextMethod()
225
- public lineTo(_x: number, _y: number): void { }
226
-
227
- @contextMethod()
228
- public bezierCurveTo(_cp1x: number, _cp1y: number, _cp2x: number, _cp2y: number, _x: number, _y: number): void { }
229
-
230
- @contextMethod()
231
- public quadraticCurveTo(_cpx: number, _cpy: number, _x: number, _y: number): void { }
232
-
233
- @contextMethod()
234
- public closePath(): void { }
235
-
236
- @contextMethod()
237
- public arc(_x: number, _y: number, _radius: number, _startAngle: number, _endAngle: number, _counterclockwise?: boolean): void { }
238
-
239
- @contextMethod()
240
- public arcTo(_x1: number, _y1: number, _x2: number, _y2: number, _radius: number): void { }
241
-
242
- @contextMethod()
243
- public ellipse(_x: number, _y: number, _radiusX: number, _radiusY: number, _rotation: number, _startAngle: number, _endAngle: number, _counterclockwise?: boolean): void { }
244
-
245
- @contextMethod()
246
- public rect(_x: number, _y: number, _width: number, _height: number): void { }
247
-
248
- @contextMethod()
249
- public roundRect(_x: number, _y: number, _width: number, _height: number, _radius?: number | number[]): void { }
250
-
251
- // end canvas draw
252
-
253
- // paint
254
-
255
- @contextMethod()
256
- public createConicGradient(_startAngle: number, _x: number, _y: number): CanvasGradient { return void 0 }
257
-
258
- @contextMethod()
259
- public createLinearGradient(_x0: number, _y0: number, _x1: number, _y1: number): CanvasGradient { return void 0 }
260
-
261
- @contextMethod()
262
- public createPattern(_image: CanvasImageSource, _repetition: string | null): CanvasPattern | null { return void 0 }
263
-
264
- @contextMethod()
265
- public createRadialGradient(_x0: number, _y0: number, _r0: number, _x1: number, _y1: number, _r1: number): CanvasGradient { return void 0 }
266
-
267
- // text
268
- @contextMethod()
269
- public fillText(_text: string, _x: number, _y: number, _maxWidth?: number): void { }
270
-
271
- @contextMethod()
272
- public measureText(_text: string): ITextMetrics { return void 0 }
273
-
274
- @contextMethod()
275
- public strokeText(_text: string, _x: number, _y: number, _maxWidth?: number): void { }
276
-
277
- public destroy(): void {
278
- this.context = null
279
- }
280
- }