@leafer/canvas-web 1.0.0-alpha.1 → 1.0.0-alpha.21
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 +9 -7
- package/src/CanvasBase.ts +31 -31
- package/src/LeaferCanvas.ts +129 -94
- package/src/patch/roundRect.ts +3 -3
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer/canvas-web",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.21",
|
|
4
4
|
"description": "@leafer/canvas-web",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "src/index.ts",
|
|
8
|
-
"files": [
|
|
8
|
+
"files": [
|
|
9
|
+
"src"
|
|
10
|
+
],
|
|
9
11
|
"repository": {
|
|
10
12
|
"type": "git",
|
|
11
13
|
"url": "https://github.com/leaferjs/leafer.git"
|
|
@@ -17,11 +19,11 @@
|
|
|
17
19
|
"leaferjs"
|
|
18
20
|
],
|
|
19
21
|
"dependencies": {
|
|
20
|
-
"@leafer/math": "1.0.0-alpha.
|
|
21
|
-
"@leafer/event": "1.0.0-alpha.
|
|
22
|
-
"@leafer/debug": "1.0.0-alpha.
|
|
22
|
+
"@leafer/math": "1.0.0-alpha.21",
|
|
23
|
+
"@leafer/event": "1.0.0-alpha.21",
|
|
24
|
+
"@leafer/debug": "1.0.0-alpha.21"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
25
|
-
|
|
27
|
+
"@leafer/interface": "1.0.0-alpha.21"
|
|
26
28
|
}
|
|
27
|
-
}
|
|
29
|
+
}
|
package/src/CanvasBase.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ICanvasAttr,
|
|
1
|
+
import { ICanvasAttr, ITextMetrics, ICanvasContext2D, IPath2D, IObject, InnerId, IMatrixData, IFunction, IWindingRule } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
function contextAttr(realName?: string) {
|
|
@@ -14,7 +14,7 @@ function contextAttr(realName?: string) {
|
|
|
14
14
|
|
|
15
15
|
const contextMethodNameList: string[] = []
|
|
16
16
|
function contextMethod() {
|
|
17
|
-
return (
|
|
17
|
+
return (_target: CanvasBase, key: string) => {
|
|
18
18
|
contextMethodNameList.push(key)
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -29,7 +29,7 @@ export class CanvasBase {
|
|
|
29
29
|
|
|
30
30
|
public __: ICanvasAttr
|
|
31
31
|
|
|
32
|
-
public context:
|
|
32
|
+
public context: ICanvasContext2D
|
|
33
33
|
|
|
34
34
|
// canvas attr
|
|
35
35
|
|
|
@@ -122,7 +122,7 @@ export class CanvasBase {
|
|
|
122
122
|
|
|
123
123
|
// end
|
|
124
124
|
|
|
125
|
-
public
|
|
125
|
+
public __bindContext(): void {
|
|
126
126
|
let method: IFunction
|
|
127
127
|
contextMethodNameList.forEach(name => {
|
|
128
128
|
method = (this.context as IObject)[name]
|
|
@@ -133,7 +133,7 @@ export class CanvasBase {
|
|
|
133
133
|
// canvas method
|
|
134
134
|
|
|
135
135
|
@contextMethod()
|
|
136
|
-
public setTransform(
|
|
136
|
+
public setTransform(_a: number | IMatrixData, _b?: number, _c?: number, _d?: number, _e?: number, _f?: number): void { }
|
|
137
137
|
|
|
138
138
|
@contextMethod()
|
|
139
139
|
public resetTransform(): void { }
|
|
@@ -148,31 +148,31 @@ export class CanvasBase {
|
|
|
148
148
|
public restore(): void { }
|
|
149
149
|
|
|
150
150
|
@contextMethod()
|
|
151
|
-
public translate(
|
|
151
|
+
public translate(_x: number, _y: number): void { }
|
|
152
152
|
|
|
153
153
|
@contextMethod()
|
|
154
|
-
public scale(
|
|
154
|
+
public scale(_x: number, _y: number): void { }
|
|
155
155
|
|
|
156
156
|
@contextMethod()
|
|
157
|
-
public rotate(
|
|
157
|
+
public rotate(_angle: number): void { }
|
|
158
158
|
|
|
159
159
|
@contextMethod()
|
|
160
|
-
public fill(
|
|
160
|
+
public fill(_path2d?: IPath2D | IWindingRule, _rule?: IWindingRule): void { }
|
|
161
161
|
|
|
162
162
|
@contextMethod()
|
|
163
|
-
public stroke(
|
|
163
|
+
public stroke(_path2d?: IPath2D): void { }
|
|
164
164
|
|
|
165
165
|
@contextMethod()
|
|
166
|
-
public clip(
|
|
166
|
+
public clip(_path2d?: IPath2D | IWindingRule, _rule?: IWindingRule): void { }
|
|
167
167
|
|
|
168
168
|
@contextMethod()
|
|
169
|
-
public fillRect(
|
|
169
|
+
public fillRect(_x: number, _y: number, _width: number, _height: number): void { }
|
|
170
170
|
|
|
171
171
|
@contextMethod()
|
|
172
|
-
public strokeRect(
|
|
172
|
+
public strokeRect(_x: number, _y: number, _width: number, _height: number): void { }
|
|
173
173
|
|
|
174
174
|
@contextMethod()
|
|
175
|
-
public clearRect(
|
|
175
|
+
public clearRect(_x: number, _y: number, _width: number, _height: number): void { }
|
|
176
176
|
|
|
177
177
|
public drawImage(image: CanvasImageSource, sx: number, sy: number, sw?: number, sh?: number, dx?: number, dy?: number, dw?: number, dh?: number): void {
|
|
178
178
|
switch (arguments.length) {
|
|
@@ -211,62 +211,62 @@ export class CanvasBase {
|
|
|
211
211
|
public beginPath(): void { }
|
|
212
212
|
|
|
213
213
|
@contextMethod()
|
|
214
|
-
public moveTo(
|
|
214
|
+
public moveTo(_x: number, _y: number): void { }
|
|
215
215
|
|
|
216
216
|
@contextMethod()
|
|
217
|
-
public lineTo(
|
|
217
|
+
public lineTo(_x: number, _y: number): void { }
|
|
218
218
|
|
|
219
219
|
@contextMethod()
|
|
220
|
-
public bezierCurveTo(
|
|
220
|
+
public bezierCurveTo(_cp1x: number, _cp1y: number, _cp2x: number, _cp2y: number, _x: number, _y: number): void { }
|
|
221
221
|
|
|
222
222
|
@contextMethod()
|
|
223
|
-
public quadraticCurveTo(
|
|
223
|
+
public quadraticCurveTo(_cpx: number, _cpy: number, _x: number, _y: number): void { }
|
|
224
224
|
|
|
225
225
|
@contextMethod()
|
|
226
226
|
public closePath(): void { }
|
|
227
227
|
|
|
228
228
|
@contextMethod()
|
|
229
|
-
public arc(
|
|
229
|
+
public arc(_x: number, _y: number, _radius: number, _startAngle: number, _endAngle: number, _counterclockwise?: boolean): void { }
|
|
230
230
|
|
|
231
231
|
@contextMethod()
|
|
232
|
-
public arcTo(
|
|
232
|
+
public arcTo(_x1: number, _y1: number, _x2: number, _y2: number, _radius: number): void { }
|
|
233
233
|
|
|
234
234
|
@contextMethod()
|
|
235
|
-
public ellipse(
|
|
235
|
+
public ellipse(_x: number, _y: number, _radiusX: number, _radiusY: number, _rotation: number, _startAngle: number, _endAngle: number, _counterclockwise?: boolean): void { }
|
|
236
236
|
|
|
237
237
|
@contextMethod()
|
|
238
|
-
public rect(
|
|
238
|
+
public rect(_x: number, _y: number, _width: number, _height: number): void { }
|
|
239
239
|
|
|
240
240
|
@contextMethod()
|
|
241
|
-
public roundRect(
|
|
241
|
+
public roundRect(_x: number, _y: number, _width: number, _height: number, _radius?: number | number[]): void { }
|
|
242
242
|
|
|
243
243
|
// end canvas draw
|
|
244
244
|
|
|
245
245
|
// paint
|
|
246
246
|
|
|
247
247
|
@contextMethod()
|
|
248
|
-
public createConicGradient(
|
|
248
|
+
public createConicGradient(_startAngle: number, _x: number, _y: number): CanvasGradient { return void 0 }
|
|
249
249
|
|
|
250
250
|
@contextMethod()
|
|
251
|
-
public createLinearGradient(
|
|
251
|
+
public createLinearGradient(_x0: number, _y0: number, _x1: number, _y1: number): CanvasGradient { return void 0 }
|
|
252
252
|
|
|
253
253
|
@contextMethod()
|
|
254
|
-
public createPattern(
|
|
254
|
+
public createPattern(_image: CanvasImageSource, _repetition: string | null): CanvasPattern | null { return void 0 }
|
|
255
255
|
|
|
256
256
|
@contextMethod()
|
|
257
|
-
public createRadialGradient(
|
|
257
|
+
public createRadialGradient(_x0: number, _y0: number, _r0: number, _x1: number, _y1: number, _r1: number): CanvasGradient { return void 0 }
|
|
258
258
|
|
|
259
259
|
// text
|
|
260
260
|
@contextMethod()
|
|
261
|
-
public fillText(
|
|
261
|
+
public fillText(_text: string, _x: number, _y: number, _maxWidth?: number): void { }
|
|
262
262
|
|
|
263
263
|
@contextMethod()
|
|
264
|
-
public measureText(
|
|
264
|
+
public measureText(_text: string): ITextMetrics { return void 0 }
|
|
265
265
|
|
|
266
266
|
@contextMethod()
|
|
267
|
-
public strokeText(
|
|
267
|
+
public strokeText(_text: string, _x: number, _y: number, _maxWidth?: number): void { }
|
|
268
268
|
|
|
269
269
|
public destroy(): void {
|
|
270
|
-
this.context =
|
|
270
|
+
this.context = null
|
|
271
271
|
}
|
|
272
272
|
}
|
package/src/LeaferCanvas.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { IBounds, ILeaferCanvas, ICanvasStrokeOptions,
|
|
1
|
+
import { IBounds, ILeaferCanvas, ICanvasStrokeOptions, ICanvasContext2D, ILeaferCanvasConfig, IMatrixData, IBoundsData, IAutoBounds, ISizeData, IScreenSizeData, IResizeEventListener, IMatrixWithBoundsData, IPointData, InnerId, ICanvasManager, IWindingRule } from '@leafer/interface'
|
|
2
2
|
import { Bounds, BoundsHelper, IncrementId } from '@leafer/math'
|
|
3
3
|
import { ResizeEvent } from '@leafer/event'
|
|
4
|
+
import { Platform } from '@leafer/platform'
|
|
4
5
|
import { Debug } from '@leafer/debug'
|
|
5
6
|
|
|
6
7
|
import { CanvasBase } from './CanvasBase'
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
const debug = Debug.get('LeaferCanvas')
|
|
11
|
+
|
|
12
|
+
const temp = new Bounds()
|
|
10
13
|
const minSize: IScreenSizeData = {
|
|
11
14
|
width: 1,
|
|
12
15
|
height: 1,
|
|
@@ -15,10 +18,9 @@ const minSize: IScreenSizeData = {
|
|
|
15
18
|
|
|
16
19
|
export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
17
20
|
|
|
18
|
-
public readonly innerId: InnerId
|
|
19
|
-
|
|
20
21
|
public manager: ICanvasManager
|
|
21
|
-
|
|
22
|
+
|
|
23
|
+
public readonly innerId: InnerId
|
|
22
24
|
|
|
23
25
|
public pixelRatio: number
|
|
24
26
|
public get pixelWidth(): number { return this.width * this.pixelRatio }
|
|
@@ -26,6 +28,9 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
26
28
|
|
|
27
29
|
public bounds: IBounds
|
|
28
30
|
|
|
31
|
+
public view: HTMLCanvasElement | OffscreenCanvas
|
|
32
|
+
public offscreen: boolean
|
|
33
|
+
|
|
29
34
|
public recycled?: boolean
|
|
30
35
|
|
|
31
36
|
protected resizeObserver: ResizeObserver
|
|
@@ -38,110 +43,139 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
38
43
|
this.manager = manager
|
|
39
44
|
this.innerId = IncrementId.create(IncrementId.CNAVAS)
|
|
40
45
|
|
|
41
|
-
|
|
46
|
+
const { view, width, height, pixelRatio, fill, hittable: hitable } = config
|
|
47
|
+
const autoLayout = !width || !height
|
|
42
48
|
|
|
43
|
-
|
|
49
|
+
this.pixelRatio = pixelRatio
|
|
50
|
+
this.offscreen = Platform.isWorker || config.offscreen
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
52
|
+
if (this.offscreen) {
|
|
53
|
+
view ? this.view = view as OffscreenCanvas : this.__createView()
|
|
54
|
+
} else {
|
|
55
|
+
view ? this.__createViewFrom(view) : this.__createView()
|
|
56
|
+
const { style } = this.view as HTMLCanvasElement
|
|
57
|
+
if (fill) style.backgroundColor = fill
|
|
58
|
+
if (!hitable) style.pointerEvents = 'none'
|
|
59
|
+
if (autoLayout) style.display || (style.display = 'block')
|
|
60
|
+
}
|
|
48
61
|
|
|
49
|
-
|
|
62
|
+
this.__init()
|
|
63
|
+
if (!autoLayout) this.resize(config as IScreenSizeData)
|
|
64
|
+
}
|
|
50
65
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
protected __init(): void {
|
|
67
|
+
this.context = this.view.getContext('2d') as ICanvasContext2D
|
|
68
|
+
this.smooth = true
|
|
69
|
+
this.__bindContext()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
protected __createView(): void {
|
|
73
|
+
this.view = this.offscreen ? new OffscreenCanvas(1, 1) : document.createElement('canvas')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
protected __createViewFrom(inputView: string | object): void {
|
|
77
|
+
let find: unknown = (typeof inputView === 'string') ? document.getElementById(inputView) : inputView as HTMLElement
|
|
78
|
+
if (find) {
|
|
79
|
+
if (find instanceof HTMLCanvasElement) {
|
|
80
|
+
|
|
81
|
+
this.view = find
|
|
61
82
|
|
|
62
|
-
this.view = document.createElement('canvas');
|
|
63
|
-
(realView as HTMLElement).appendChild(this.view)
|
|
64
|
-
}
|
|
65
83
|
} else {
|
|
66
|
-
debug.error(`can't find view by id: ${view}`)
|
|
67
|
-
}
|
|
68
84
|
|
|
69
|
-
|
|
85
|
+
let parent = find as HTMLDivElement
|
|
86
|
+
if (find === window || find === document) {
|
|
87
|
+
const div = document.createElement('div')
|
|
88
|
+
const { style } = div
|
|
89
|
+
style.position = 'absolute'
|
|
90
|
+
style.top = style.bottom = style.left = style.right = '0px'
|
|
91
|
+
style.overflow = 'hidden'
|
|
92
|
+
document.body.appendChild(div)
|
|
93
|
+
parent = div
|
|
94
|
+
}
|
|
70
95
|
|
|
71
|
-
|
|
72
|
-
|
|
96
|
+
this.__createView()
|
|
97
|
+
const view = this.view as HTMLCanvasElement
|
|
73
98
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
if (parent.hasChildNodes()) {
|
|
100
|
+
const { style } = view
|
|
101
|
+
style.position = 'absolute'
|
|
102
|
+
style.top = style.left = '0px'
|
|
103
|
+
parent.style.position || (parent.style.position = 'relative')
|
|
104
|
+
}
|
|
79
105
|
|
|
80
|
-
|
|
106
|
+
parent.appendChild(view)
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
debug.error(`can't find view by id: ${inputView}`)
|
|
110
|
+
this.__createView()
|
|
81
111
|
}
|
|
82
112
|
}
|
|
83
113
|
|
|
84
|
-
public debug(): void { }
|
|
85
|
-
|
|
86
114
|
public pixel(num: number): number { return num * this.pixelRatio }
|
|
87
115
|
|
|
88
|
-
public
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
public startAutoLayout(autoBounds: IAutoBounds, listener: IResizeEventListener): void {
|
|
117
|
+
if (!this.offscreen) {
|
|
118
|
+
const view = this.view as HTMLCanvasElement
|
|
119
|
+
const check = (parentSize: ISizeData) => {
|
|
120
|
+
const { x, y, width, height } = autoBounds.getBoundsFrom(parentSize)
|
|
121
|
+
const { style } = view
|
|
122
|
+
style.marginLeft = x + 'px'
|
|
123
|
+
style.marginTop = y + 'px'
|
|
124
|
+
|
|
125
|
+
if (width !== this.width || height !== this.height) {
|
|
126
|
+
const { pixelRatio } = this
|
|
127
|
+
const size = { width, height, pixelRatio }
|
|
128
|
+
const oldSize = { width: this.width, height: this.height, pixelRatio: this.pixelRatio }
|
|
129
|
+
this.resize(size)
|
|
130
|
+
if (this.width !== undefined) listener(new ResizeEvent(size, oldSize))
|
|
131
|
+
}
|
|
101
132
|
}
|
|
102
|
-
}
|
|
103
133
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
134
|
+
this.resizeObserver = new ResizeObserver((entries) => {
|
|
135
|
+
for (const entry of entries) {
|
|
136
|
+
check(entry.contentRect)
|
|
137
|
+
}
|
|
138
|
+
})
|
|
109
139
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
140
|
+
const parent = view.parentElement
|
|
141
|
+
if (parent) {
|
|
142
|
+
this.resizeObserver.observe(parent)
|
|
143
|
+
check(parent.getBoundingClientRect())
|
|
144
|
+
}
|
|
114
145
|
}
|
|
115
146
|
}
|
|
116
147
|
|
|
117
148
|
public stopAutoLayout(): void {
|
|
118
149
|
if (this.resizeObserver) {
|
|
119
150
|
this.resizeObserver.disconnect()
|
|
120
|
-
this.resizeObserver =
|
|
151
|
+
this.resizeObserver = null
|
|
121
152
|
}
|
|
122
153
|
}
|
|
123
154
|
|
|
124
155
|
public resize(size: IScreenSizeData): void {
|
|
125
|
-
const { style } = this.view
|
|
126
156
|
const { width, height, pixelRatio } = size
|
|
127
157
|
if (this.isSameSize(size)) return
|
|
128
158
|
|
|
129
159
|
let takeCanvas: ILeaferCanvas
|
|
130
160
|
if (this.context && this.width) {
|
|
131
161
|
takeCanvas = this.getSameCanvas()
|
|
132
|
-
takeCanvas.
|
|
162
|
+
takeCanvas.copyWorld(this)
|
|
133
163
|
}
|
|
134
164
|
|
|
135
165
|
Object.assign(this, { width, height, pixelRatio })
|
|
136
166
|
this.bounds = new Bounds(0, 0, width, height)
|
|
137
167
|
|
|
138
|
-
|
|
139
|
-
|
|
168
|
+
if (!this.offscreen) {
|
|
169
|
+
const { style } = this.view as HTMLCanvasElement
|
|
170
|
+
style.width = width + 'px'
|
|
171
|
+
style.height = height + 'px'
|
|
172
|
+
}
|
|
173
|
+
|
|
140
174
|
this.view.width = width * pixelRatio
|
|
141
175
|
this.view.height = height * pixelRatio
|
|
142
176
|
|
|
143
177
|
if (this.context && takeCanvas) {
|
|
144
|
-
this.
|
|
178
|
+
this.copyWorld(takeCanvas)
|
|
145
179
|
takeCanvas.recycle()
|
|
146
180
|
}
|
|
147
181
|
}
|
|
@@ -201,7 +235,16 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
201
235
|
}
|
|
202
236
|
}
|
|
203
237
|
|
|
204
|
-
public
|
|
238
|
+
public hitPath(point: IPointData, fillRule?: IWindingRule): boolean {
|
|
239
|
+
return this.context.isPointInPath(point.x, point.y, fillRule)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
public hitStroke(point: IPointData): boolean {
|
|
243
|
+
return this.context.isPointInStroke(point.x, point.y)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
public setWorldShadow(x: number, y: number, blur: number, color?: string): void {
|
|
205
248
|
const { pixelRatio } = this
|
|
206
249
|
this.shadowOffsetX = x * pixelRatio
|
|
207
250
|
this.shadowOffsetY = y * pixelRatio
|
|
@@ -209,28 +252,13 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
209
252
|
this.shadowColor = color || 'black'
|
|
210
253
|
}
|
|
211
254
|
|
|
212
|
-
public
|
|
255
|
+
public setWorldBlur(blur: number): void {
|
|
213
256
|
const { pixelRatio } = this
|
|
214
257
|
this.filter = `blur(${blur * pixelRatio}px)`
|
|
215
258
|
}
|
|
216
259
|
|
|
217
260
|
|
|
218
|
-
public
|
|
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()
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
public copy(canvas: ILeaferCanvas, from?: IBoundsData, to?: IBoundsData, blendMode?: string): void {
|
|
261
|
+
public copyWorld(canvas: ILeaferCanvas, from?: IBoundsData, to?: IBoundsData, blendMode?: string): void {
|
|
234
262
|
if (from) {
|
|
235
263
|
if (!to) to = from
|
|
236
264
|
const { pixelRatio } = this
|
|
@@ -249,7 +277,7 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
249
277
|
if (fromWorld.b || fromWorld.c) {
|
|
250
278
|
this.save()
|
|
251
279
|
this.resetTransform()
|
|
252
|
-
this.
|
|
280
|
+
this.copyWorld(canvas, fromWorld, BoundsHelper.tempToWorld(toLocalBounds, fromWorld))
|
|
253
281
|
this.restore()
|
|
254
282
|
} else {
|
|
255
283
|
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)
|
|
@@ -257,7 +285,7 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
257
285
|
if (blendMode) this.blendMode = 'normal'
|
|
258
286
|
}
|
|
259
287
|
|
|
260
|
-
public
|
|
288
|
+
public fillWorld(bounds: IBoundsData, color: string | object, blendMode?: string): void {
|
|
261
289
|
const { pixelRatio } = this
|
|
262
290
|
if (blendMode) this.blendMode = blendMode
|
|
263
291
|
this.fillStyle = color
|
|
@@ -265,7 +293,7 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
265
293
|
if (blendMode) this.blendMode = 'normal'
|
|
266
294
|
}
|
|
267
295
|
|
|
268
|
-
public
|
|
296
|
+
public strokeWorld(bounds: IBoundsData, color: string | object, blendMode?: string): void {
|
|
269
297
|
const { pixelRatio } = this
|
|
270
298
|
if (blendMode) this.blendMode = blendMode
|
|
271
299
|
this.strokeStyle = color
|
|
@@ -273,15 +301,19 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
273
301
|
if (blendMode) this.blendMode = 'normal'
|
|
274
302
|
}
|
|
275
303
|
|
|
276
|
-
public
|
|
304
|
+
public clearWorld(bounds: IBoundsData, ceilPixel?: boolean): void {
|
|
277
305
|
const { pixelRatio } = this
|
|
278
|
-
|
|
306
|
+
temp.copy(bounds).scale(pixelRatio)
|
|
307
|
+
if (ceilPixel) temp.ceil()
|
|
308
|
+
this.clearRect(temp.x, temp.y, temp.width, temp.height)
|
|
279
309
|
}
|
|
280
310
|
|
|
281
|
-
public
|
|
311
|
+
public clipWorld(bounds: IBoundsData, ceilPixel?: boolean): void {
|
|
282
312
|
const { pixelRatio } = this
|
|
283
313
|
this.beginPath()
|
|
284
|
-
|
|
314
|
+
temp.copy(bounds).scale(pixelRatio)
|
|
315
|
+
if (ceilPixel) temp.ceil()
|
|
316
|
+
this.rect(temp.x, temp.y, temp.width, temp.height)
|
|
285
317
|
this.clip()
|
|
286
318
|
|
|
287
319
|
}
|
|
@@ -328,10 +360,13 @@ export class LeaferCanvas extends CanvasBase implements ILeaferCanvas {
|
|
|
328
360
|
if (this.view) {
|
|
329
361
|
super.destroy()
|
|
330
362
|
this.stopAutoLayout()
|
|
331
|
-
this.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
363
|
+
if (!this.offscreen) {
|
|
364
|
+
const view = this.view as HTMLCanvasElement
|
|
365
|
+
if (view.parentElement) view.remove()
|
|
366
|
+
}
|
|
367
|
+
this.manager = null
|
|
368
|
+
this.view = null
|
|
369
|
+
this.context = null
|
|
335
370
|
}
|
|
336
371
|
}
|
|
337
372
|
|
package/src/patch/roundRect.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IObject } from '@leafer/interface'
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export function roundRect(): void {
|
|
5
5
|
|
|
6
|
-
if (!(CanvasRenderingContext2D.prototype as
|
|
6
|
+
if (!(CanvasRenderingContext2D.prototype as IObject).roundRect) {
|
|
7
7
|
|
|
8
|
-
(CanvasRenderingContext2D.prototype as
|
|
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
9
|
|
|
10
10
|
let topLeft: number, topRight: number, bottomRight: number, bottomLeft: number
|
|
11
11
|
|