@leafer/canvas-web 1.0.0-alpha.7 → 1.0.0-bate

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