@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.
Files changed (2) hide show
  1. package/package.json +10 -8
  2. 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.1",
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": ["src"],
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.1",
21
- "@leafer/math": "1.0.0-alpha.1",
22
- "@leafer/data": "1.0.0-alpha.1",
23
- "@leafer/platform": "1.0.0-alpha.1",
24
- "@leafer/debug": "1.0.0-alpha.1"
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
- "@leafer/interface": "1.0.0-alpha.1"
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, ILayoutBlockData } from '@leafer/interface'
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 layoutedBlocks: ILayoutBlockData[]
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 FPS = 60
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
- public running: boolean
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.listenEvents()
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
- private listenEvents(): void {
58
- const { target } = this
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
- target.emit(START)
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
- if (this.layoutedBlocks) this.partRender()
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
- if (this.layoutedBlocks) {
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
- protected __checkAgain(): void {
145
- if (this.changed && this.times < 3) this.target.emit(RenderEvent.AGAIN)
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 (layoutedBlocks.some(block => block.updatedBounds.includes(this.target.__world))) {
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
- let bounds: IBounds
156
- layoutedBlocks.forEach(block => {
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('part render')
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('full render')
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
- private requestRender(): void {
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.removeListenEvents()
208
- this.target = undefined
209
- this.canvas = undefined
210
- this.config = undefined
214
+ this.__removeListenEvents()
215
+ this.target = null
216
+ this.canvas = null
217
+ this.config = null
211
218
  }
212
219
  }
213
220
  }