@leafer/renderer 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +10 -8
- package/src/Renderer.ts +95 -88
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer/renderer",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.10",
|
|
4
4
|
"description": "@leafer/renderer",
|
|
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,13 +19,13 @@
|
|
|
17
19
|
"leaferjs"
|
|
18
20
|
],
|
|
19
21
|
"dependencies": {
|
|
20
|
-
"@leafer/event": "1.0.0-alpha.
|
|
21
|
-
"@leafer/math": "1.0.0-alpha.
|
|
22
|
-
"@leafer/data": "1.0.0-alpha.
|
|
23
|
-
"@leafer/platform": "1.0.0-alpha.
|
|
24
|
-
"@leafer/debug": "1.0.0-alpha.
|
|
22
|
+
"@leafer/event": "1.0.0-alpha.10",
|
|
23
|
+
"@leafer/math": "1.0.0-alpha.10",
|
|
24
|
+
"@leafer/data": "1.0.0-alpha.10",
|
|
25
|
+
"@leafer/platform": "1.0.0-alpha.10",
|
|
26
|
+
"@leafer/debug": "1.0.0-alpha.10"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
|
-
|
|
29
|
+
"@leafer/interface": "1.0.0-alpha.10"
|
|
28
30
|
}
|
|
29
31
|
}
|
package/src/Renderer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ILeaf, ILeaferCanvas, IRenderer, IRendererConfig, IEventListenerId, IBounds, IFunction
|
|
1
|
+
import { ILeaf, ILeaferCanvas, IRenderer, IRendererConfig, IEventListenerId, IBounds, IFunction } from '@leafer/interface'
|
|
2
2
|
import { LayoutEvent, RenderEvent, ResizeEvent } from '@leafer/event'
|
|
3
3
|
import { Bounds } from '@leafer/math'
|
|
4
4
|
import { DataHelper } from '@leafer/data'
|
|
@@ -6,80 +6,45 @@ import { Platform } from '@leafer/platform'
|
|
|
6
6
|
import { Debug, Run } from '@leafer/debug'
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
const debug = Debug.get('Renderer')
|
|
10
|
+
|
|
9
11
|
export class Renderer implements IRenderer {
|
|
10
12
|
|
|
11
13
|
public target: ILeaf
|
|
12
14
|
public canvas: ILeaferCanvas
|
|
13
|
-
public
|
|
15
|
+
public updateBlocks: IBounds[]
|
|
14
16
|
|
|
17
|
+
public FPS = 60
|
|
15
18
|
public totalTimes = 0
|
|
16
19
|
public times: number = 0
|
|
17
20
|
|
|
18
|
-
public
|
|
21
|
+
public running: boolean
|
|
22
|
+
public changed: boolean
|
|
19
23
|
|
|
20
24
|
public config: IRendererConfig = {
|
|
25
|
+
usePartRender: true,
|
|
21
26
|
maxFPS: 60
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
private _changed = false
|
|
27
|
-
set changed(value: boolean) {
|
|
28
|
-
if (value) {
|
|
29
|
-
if (!this._changed) {
|
|
30
|
-
this._changed = true
|
|
31
|
-
this.requestRender()
|
|
32
|
-
}
|
|
33
|
-
} else {
|
|
34
|
-
this._changed = false
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
get changed(): boolean { return this._changed }
|
|
38
|
-
|
|
39
|
-
protected eventIds: IEventListenerId[]
|
|
29
|
+
protected __eventIds: IEventListenerId[]
|
|
40
30
|
|
|
41
31
|
constructor(target: ILeaf, canvas: ILeaferCanvas, userConfig: IRendererConfig) {
|
|
42
32
|
this.target = target
|
|
43
33
|
this.canvas = canvas
|
|
44
34
|
if (userConfig) this.config = DataHelper.default(userConfig, this.config)
|
|
45
|
-
this.
|
|
35
|
+
this.__listenEvents()
|
|
46
36
|
}
|
|
47
37
|
|
|
48
38
|
public start(): void {
|
|
49
39
|
this.running = true
|
|
50
|
-
this.changed = true
|
|
51
40
|
}
|
|
52
41
|
|
|
53
42
|
public stop(): void {
|
|
54
43
|
this.running = false
|
|
55
44
|
}
|
|
56
45
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.eventIds = [
|
|
60
|
-
target.on__(RenderEvent.REQUEST, this.onRequest, this),
|
|
61
|
-
target.on__(LayoutEvent.END, this.onLayoutEnd, this),
|
|
62
|
-
target.on__(RenderEvent.AGAIN, this.renderOnce, this),
|
|
63
|
-
target.on__(ResizeEvent.RESIZE, this.onResize, this)
|
|
64
|
-
]
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private removeListenEvents(): void {
|
|
68
|
-
this.target.off__(this.eventIds)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
protected onResize(e: ResizeEvent): void {
|
|
72
|
-
if (e.bigger || !e.samePixelRatio) {
|
|
73
|
-
const { width, height } = e.old
|
|
74
|
-
const bounds = new Bounds(0, 0, width, height)
|
|
75
|
-
if (!bounds.includes(this.target.__world)) {
|
|
76
|
-
this.target.__updateAttr('fill')
|
|
77
|
-
this.changed = true
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
protected onRequest(): void {
|
|
46
|
+
public update(): void {
|
|
47
|
+
if (!this.changed) this.__requestRender()
|
|
83
48
|
this.changed = true
|
|
84
49
|
}
|
|
85
50
|
|
|
@@ -87,23 +52,22 @@ export class Renderer implements IRenderer {
|
|
|
87
52
|
this.target.emit(LayoutEvent.REQUEST)
|
|
88
53
|
}
|
|
89
54
|
|
|
90
|
-
public onLayoutEnd(event: LayoutEvent): void {
|
|
91
|
-
this.layoutedBlocks = event.data
|
|
92
|
-
}
|
|
93
|
-
|
|
94
55
|
public render(callback?: IFunction): void {
|
|
95
56
|
const { target } = this
|
|
96
|
-
const { START, RENDER, END } = RenderEvent
|
|
97
57
|
this.times = 0
|
|
98
|
-
|
|
58
|
+
|
|
59
|
+
debug.log(target.innerId, '--->')
|
|
60
|
+
|
|
61
|
+
target.emit(RenderEvent.START)
|
|
99
62
|
this.renderOnce(callback)
|
|
100
|
-
target.emit(RENDER)
|
|
101
|
-
target.emit(END)
|
|
63
|
+
target.emit(RenderEvent.RENDER)
|
|
64
|
+
target.emit(RenderEvent.END)
|
|
65
|
+
|
|
66
|
+
debug.log(target.innerId, '---|')
|
|
102
67
|
}
|
|
103
68
|
|
|
104
69
|
public renderOnce(callback?: IFunction): void {
|
|
105
70
|
const { target } = this
|
|
106
|
-
const { BEFORE_ONCE, ONCE, AFTER_ONCE } = RenderEvent
|
|
107
71
|
|
|
108
72
|
this.times++
|
|
109
73
|
this.totalTimes++
|
|
@@ -111,7 +75,7 @@ export class Renderer implements IRenderer {
|
|
|
111
75
|
|
|
112
76
|
if (callback) {
|
|
113
77
|
|
|
114
|
-
target.emit(BEFORE_ONCE)
|
|
78
|
+
target.emit(RenderEvent.BEFORE_ONCE)
|
|
115
79
|
|
|
116
80
|
callback()
|
|
117
81
|
|
|
@@ -119,56 +83,53 @@ export class Renderer implements IRenderer {
|
|
|
119
83
|
|
|
120
84
|
this.requestLayout()
|
|
121
85
|
|
|
122
|
-
target.emit(BEFORE_ONCE)
|
|
86
|
+
target.emit(RenderEvent.BEFORE_ONCE)
|
|
123
87
|
|
|
124
|
-
if (this.totalTimes > 1) {
|
|
125
|
-
|
|
88
|
+
if (this.config.usePartRender && this.totalTimes > 1) {
|
|
89
|
+
this.partRender()
|
|
126
90
|
} else {
|
|
127
91
|
this.fullRender()
|
|
128
92
|
}
|
|
129
93
|
|
|
130
94
|
}
|
|
131
95
|
|
|
132
|
-
target.emit(ONCE)
|
|
133
|
-
target.emit(AFTER_ONCE)
|
|
96
|
+
target.emit(RenderEvent.ONCE)
|
|
97
|
+
target.emit(RenderEvent.AFTER_ONCE)
|
|
134
98
|
|
|
135
99
|
|
|
136
|
-
|
|
137
|
-
this.layoutedBlocks.forEach(item => { item.destroy() })
|
|
138
|
-
this.layoutedBlocks = undefined
|
|
139
|
-
}
|
|
100
|
+
this.updateBlocks = null
|
|
140
101
|
|
|
141
102
|
this.__checkAgain()
|
|
142
103
|
}
|
|
143
104
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
protected partRender(): void {
|
|
150
|
-
const { canvas, layoutedBlocks } = this
|
|
105
|
+
public partRender(): void {
|
|
106
|
+
const { canvas, updateBlocks: list } = this
|
|
151
107
|
|
|
152
|
-
if (
|
|
108
|
+
if (!list) {
|
|
109
|
+
debug.warn('PartRender: layoutedBlocks is empty')
|
|
153
110
|
this.fullRender(canvas.bounds)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (list.some(block => block.includes(this.target.__world))) {
|
|
115
|
+
this.mergeBlocks()
|
|
116
|
+
this.clipRender(this.updateBlocks[0], true)
|
|
154
117
|
} else {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
bounds = block.updatedBounds
|
|
158
|
-
if (canvas.bounds.hit(bounds) && !bounds.isEmpty()) this.clipRender(bounds.getIntersect(canvas.bounds))
|
|
118
|
+
list.forEach(block => {
|
|
119
|
+
if (canvas.bounds.hit(block) && !block.isEmpty()) this.clipRender(block.getIntersect(canvas.bounds))
|
|
159
120
|
})
|
|
160
121
|
}
|
|
161
122
|
}
|
|
162
123
|
|
|
163
|
-
public clipRender(bounds: IBounds): void {
|
|
164
|
-
const t = Run.start('
|
|
124
|
+
public clipRender(bounds: IBounds, fullMode?: boolean): void {
|
|
125
|
+
const t = Run.start('PartRender')
|
|
165
126
|
const { canvas, target } = this
|
|
166
127
|
|
|
167
128
|
canvas.save()
|
|
168
129
|
canvas.clearBounds(bounds)
|
|
169
130
|
if (Debug.showRepaint) canvas.strokeBounds(bounds, 'red')
|
|
170
131
|
canvas.clipBounds(bounds)
|
|
171
|
-
target.__render(canvas, { bounds })
|
|
132
|
+
target.__render(canvas, fullMode ? {} : { bounds })
|
|
172
133
|
canvas.restore()
|
|
173
134
|
|
|
174
135
|
Run.end(t)
|
|
@@ -177,11 +138,10 @@ export class Renderer implements IRenderer {
|
|
|
177
138
|
public fullRender(bounds?: IBounds): void {
|
|
178
139
|
const { canvas, target } = this
|
|
179
140
|
Renderer.fullRender(target, canvas, bounds)
|
|
180
|
-
if (Debug.showRepaint) canvas.strokeBounds(bounds || canvas.bounds, 'red')
|
|
181
141
|
}
|
|
182
142
|
|
|
183
143
|
static fullRender(target: ILeaf, canvas: ILeaferCanvas, bounds?: IBounds): void {
|
|
184
|
-
const t = Run.start('
|
|
144
|
+
const t = Run.start('FullRender')
|
|
185
145
|
if (!bounds) bounds = canvas.bounds
|
|
186
146
|
|
|
187
147
|
canvas.save()
|
|
@@ -192,7 +152,25 @@ export class Renderer implements IRenderer {
|
|
|
192
152
|
Run.end(t)
|
|
193
153
|
}
|
|
194
154
|
|
|
195
|
-
|
|
155
|
+
public addBlock(block: IBounds): void {
|
|
156
|
+
if (!this.updateBlocks) this.updateBlocks = []
|
|
157
|
+
this.updateBlocks.push(block)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public mergeBlocks(): void {
|
|
161
|
+
const { updateBlocks } = this
|
|
162
|
+
if (updateBlocks) {
|
|
163
|
+
const bounds = new Bounds()
|
|
164
|
+
bounds.setByList(updateBlocks)
|
|
165
|
+
this.updateBlocks = [bounds]
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
protected __checkAgain(): void {
|
|
170
|
+
if (this.changed && this.times < 3) this.target.emit(RenderEvent.AGAIN)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
protected __requestRender(): void {
|
|
196
174
|
const startTime = Date.now()
|
|
197
175
|
Platform.requestRender(() => {
|
|
198
176
|
if (this.changed) {
|
|
@@ -202,12 +180,41 @@ export class Renderer implements IRenderer {
|
|
|
202
180
|
})
|
|
203
181
|
}
|
|
204
182
|
|
|
183
|
+
protected __onResize(e: ResizeEvent): void {
|
|
184
|
+
if (e.bigger || !e.samePixelRatio) {
|
|
185
|
+
const { width, height } = e.old
|
|
186
|
+
const bounds = new Bounds(0, 0, width, height)
|
|
187
|
+
if (!bounds.includes(this.target.__world)) {
|
|
188
|
+
this.target.__updateAttr('fill')
|
|
189
|
+
this.update()
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
protected __onLayoutEnd(event: LayoutEvent): void {
|
|
195
|
+
event.data.map(item => this.addBlock(item.updatedBounds))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
protected __listenEvents(): void {
|
|
199
|
+
const { target } = this
|
|
200
|
+
this.__eventIds = [
|
|
201
|
+
target.on__(RenderEvent.REQUEST, this.update, this),
|
|
202
|
+
target.on__(LayoutEvent.END, this.__onLayoutEnd, this),
|
|
203
|
+
target.on__(RenderEvent.AGAIN, this.renderOnce, this),
|
|
204
|
+
target.on__(ResizeEvent.RESIZE, this.__onResize, this)
|
|
205
|
+
]
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
protected __removeListenEvents(): void {
|
|
209
|
+
this.target.off__(this.__eventIds)
|
|
210
|
+
}
|
|
211
|
+
|
|
205
212
|
public destroy(): void {
|
|
206
213
|
if (this.target) {
|
|
207
|
-
this.
|
|
208
|
-
this.target =
|
|
209
|
-
this.canvas =
|
|
210
|
-
this.config =
|
|
214
|
+
this.__removeListenEvents()
|
|
215
|
+
this.target = null
|
|
216
|
+
this.canvas = null
|
|
217
|
+
this.config = null
|
|
211
218
|
}
|
|
212
219
|
}
|
|
213
220
|
}
|