@leafer-ui/display 1.0.0-rc.9 → 1.0.1

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/src/Leafer.ts ADDED
@@ -0,0 +1,449 @@
1
+ import { ILeaferCanvas, IRenderer, ILayouter, ISelector, IWatcher, IInteraction, ILeaferConfig, ICanvasManager, IHitCanvasManager, IAutoBounds, IScreenSizeData, IResizeEvent, IEventListenerId, ITimer, IValue, IObject, IControl, IPointData, ILeaferType, ICursorType, IBoundsData, INumber, IZoomType, IFourNumber, IBounds, IClientPointData } from '@leafer/interface'
2
+ import { AutoBounds, LayoutEvent, ResizeEvent, LeaferEvent, CanvasManager, ImageManager, DataHelper, Creator, Run, Debug, RenderEvent, registerUI, boundsType, canvasSizeAttrs, dataProcessor, WaitHelper, WatchEvent, Bounds, LeafList } from '@leafer/core'
3
+
4
+ import { ILeaferInputData, ILeaferData, IFunction, IUIInputData, ILeafer, IApp, IEditorBase } from '@leafer-ui/interface'
5
+ import { LeaferData } from '@leafer-ui/data'
6
+ import { Group } from './Group'
7
+
8
+
9
+ const debug = Debug.get('Leafer')
10
+
11
+ @registerUI()
12
+ export class Leafer extends Group implements ILeafer {
13
+
14
+ static list = new LeafList() // 所有leafer实例
15
+
16
+
17
+ public get __tag() { return 'Leafer' }
18
+
19
+ @dataProcessor(LeaferData)
20
+ declare public __: ILeaferData
21
+
22
+ @boundsType()
23
+ declare public pixelRatio?: INumber
24
+
25
+ public get isApp(): boolean { return false }
26
+ public get app(): ILeafer { return this.parent || this }
27
+
28
+ public get isLeafer(): boolean { return true }
29
+
30
+ declare public parent?: IApp
31
+
32
+ public running: boolean
33
+ public created: boolean
34
+ public ready: boolean
35
+ public viewReady: boolean
36
+ public viewCompleted: boolean
37
+ public get imageReady(): boolean { return this.viewReady && ImageManager.isComplete }
38
+ public get layoutLocked() { return !this.layouter.running }
39
+
40
+ public transforming: boolean
41
+
42
+ public view: unknown
43
+
44
+ // manager
45
+ public canvas: ILeaferCanvas
46
+ public renderer: IRenderer
47
+
48
+ public watcher: IWatcher
49
+ public layouter: ILayouter
50
+
51
+ public selector?: ISelector
52
+ public interaction?: IInteraction
53
+
54
+ public canvasManager: ICanvasManager
55
+ public hitCanvasManager?: IHitCanvasManager
56
+
57
+ // plugin
58
+ public editor: IEditorBase
59
+
60
+ public userConfig: ILeaferConfig
61
+ public config: ILeaferConfig = {
62
+ type: 'design',
63
+ start: true,
64
+ hittable: true,
65
+ smooth: true,
66
+ lazySpeard: 100,
67
+ zoom: {
68
+ min: 0.01,
69
+ max: 256
70
+ },
71
+ move: {
72
+ holdSpaceKey: true,
73
+ holdMiddleKey: true,
74
+ autoDistance: 2
75
+ }
76
+ }
77
+
78
+ public autoLayout?: IAutoBounds
79
+ public lazyBounds: IBounds
80
+
81
+ public get FPS(): number { return this.renderer ? this.renderer.FPS : 60 }
82
+ public get cursorPoint(): IPointData { return (this.interaction && this.interaction.hoverData) || { x: this.width / 2, y: this.height / 2 } }
83
+ public get clientBounds(): IBoundsData { return this.canvas && this.canvas.getClientBounds() }
84
+ public leafs = 0
85
+
86
+ public __eventIds: IEventListenerId[] = []
87
+ protected __startTimer: ITimer
88
+ protected __controllers: IControl[] = []
89
+
90
+ protected __initWait: IFunction[] // assign in waitInit()
91
+ protected __readyWait: IFunction[] = []
92
+ protected __viewReadyWait: IFunction[] = []
93
+ protected __viewCompletedWait: IFunction[] = []
94
+ public __nextRenderWait: IFunction[] = []
95
+
96
+ constructor(userConfig?: ILeaferConfig, data?: ILeaferInputData) {
97
+ super(data)
98
+ this.userConfig = userConfig
99
+ if (userConfig && (userConfig.view || userConfig.width)) this.init(userConfig)
100
+ Leafer.list.add(this)
101
+ }
102
+
103
+ public init(userConfig?: ILeaferConfig, parentApp?: IApp): void {
104
+ if (this.canvas) return
105
+
106
+ this.__setLeafer(this)
107
+ if (userConfig) DataHelper.assign(this.config, userConfig)
108
+
109
+ let start: boolean
110
+ const { config } = this
111
+
112
+ this.initType(config.type) // LeaferType
113
+
114
+ // render / layout
115
+ const canvas = this.canvas = Creator.canvas(config)
116
+ this.__controllers.push(
117
+ this.renderer = Creator.renderer(this, canvas, config),
118
+ this.watcher = Creator.watcher(this, config),
119
+ this.layouter = Creator.layouter(this, config)
120
+ )
121
+
122
+ if (this.isApp) this.__setApp()
123
+ this.__checkAutoLayout(config, parentApp)
124
+ this.view = canvas.view
125
+
126
+ // interaction / manager
127
+ if (parentApp) {
128
+ this.__bindApp(parentApp)
129
+ start = parentApp.running
130
+ } else {
131
+ this.selector = Creator.selector(this)
132
+ this.interaction = Creator.interaction(this, canvas, this.selector, config)
133
+
134
+ if (this.interaction) {
135
+ this.__controllers.unshift(this.interaction)
136
+ this.hitCanvasManager = Creator.hitCanvasManager()
137
+ }
138
+
139
+ this.canvasManager = new CanvasManager()
140
+
141
+ start = config.start
142
+ }
143
+
144
+ this.hittable = config.hittable
145
+ this.fill = config.fill
146
+ this.canvasManager.add(canvas)
147
+
148
+
149
+ this.__listenEvents()
150
+
151
+ if (start) this.__startTimer = setTimeout(this.start.bind(this))
152
+
153
+ WaitHelper.run(this.__initWait)
154
+ this.onInit() // can rewrite init event
155
+ }
156
+
157
+ public onInit(): void { }
158
+
159
+ public initType(_type: ILeaferType): void { } // rewrite in @leafer-ui/type
160
+
161
+ public set(data: IUIInputData): void {
162
+ this.waitInit(() => { super.set(data) })
163
+ }
164
+
165
+ public start(): void {
166
+ clearTimeout(this.__startTimer)
167
+ if (!this.running && this.canvas) {
168
+ this.ready ? this.emitLeafer(LeaferEvent.RESTART) : this.emitLeafer(LeaferEvent.START)
169
+ this.__controllers.forEach(item => item.start())
170
+ if (!this.isApp) this.renderer.render()
171
+ this.running = true
172
+ }
173
+ }
174
+
175
+ public stop(): void {
176
+ clearTimeout(this.__startTimer)
177
+ if (this.running && this.canvas) {
178
+ this.__controllers.forEach(item => item.stop())
179
+ this.running = false
180
+ this.emitLeafer(LeaferEvent.STOP)
181
+ }
182
+ }
183
+
184
+ public unlockLayout(): void {
185
+ this.layouter.start()
186
+ this.updateLayout()
187
+ }
188
+
189
+ public lockLayout(): void {
190
+ this.updateLayout()
191
+ this.layouter.stop()
192
+ }
193
+
194
+ public resize(size: IScreenSizeData): void {
195
+ const data = DataHelper.copyAttrs({}, size, canvasSizeAttrs)
196
+ Object.keys(data).forEach(key => (this as any)[key] = data[key])
197
+ }
198
+
199
+ override forceRender(bounds?: IBoundsData): void {
200
+ this.renderer.addBlock(bounds ? new Bounds(bounds) : this.canvas.bounds)
201
+ if (this.viewReady) this.renderer.update()
202
+ }
203
+
204
+ public updateCursor(cursor?: ICursorType): void {
205
+ const i = this.interaction
206
+ if (i) cursor ? i.setCursor(cursor) : i.updateCursor()
207
+ }
208
+
209
+ public updateLazyBounds(): void {
210
+ this.lazyBounds = this.canvas.bounds.clone().spread(this.config.lazySpeard)
211
+ }
212
+
213
+ protected __doResize(size: IScreenSizeData): void {
214
+ const { canvas } = this
215
+ if (!canvas || canvas.isSameSize(size)) return
216
+ const old = DataHelper.copyAttrs({}, this.canvas, canvasSizeAttrs) as IScreenSizeData
217
+ canvas.resize(size)
218
+ this.updateLazyBounds()
219
+ this.__onResize(new ResizeEvent(size, old))
220
+ }
221
+
222
+ protected __onResize(event: IResizeEvent): void {
223
+ this.emitEvent(event)
224
+ DataHelper.copyAttrs(this.__, event, canvasSizeAttrs)
225
+ if (!event.width || !event.height) debug.warn('w = 0 or h = 0')
226
+ setTimeout(() => { if (this.canvasManager) this.canvasManager.clearRecycled() }, 0)
227
+ }
228
+
229
+ protected __setApp(): void { }
230
+
231
+ protected __bindApp(app: IApp): void {
232
+ this.selector = app.selector
233
+ this.interaction = app.interaction
234
+
235
+ this.canvasManager = app.canvasManager
236
+ this.hitCanvasManager = app.hitCanvasManager
237
+ }
238
+
239
+ public __setLeafer(leafer: ILeafer): void {
240
+ this.leafer = leafer
241
+ this.__level = 1
242
+ }
243
+
244
+ protected __checkAutoLayout(config: ILeaferConfig, parentApp?: IApp): void {
245
+ if (!parentApp) {
246
+ if (!config.width || !config.height) this.autoLayout = new AutoBounds(config)
247
+ this.canvas.startAutoLayout(this.autoLayout, this.__onResize.bind(this))
248
+ }
249
+ }
250
+
251
+ override __setAttr(attrName: string, newValue: IValue): boolean {
252
+ if (this.canvas) {
253
+ if (canvasSizeAttrs.includes(attrName)) {
254
+ if (!newValue) debug.warn(attrName + ' is 0')
255
+ this.__changeCanvasSize(attrName, newValue as number)
256
+ } else if (attrName === 'fill') {
257
+ this.__changeFill(newValue as string)
258
+ } else if (attrName === 'hittable') {
259
+ if (!this.parent) this.canvas.hittable = newValue as boolean
260
+ } else if (attrName === 'zIndex') {
261
+ this.canvas.zIndex = newValue as any
262
+ setTimeout(() => this.parent && this.parent.__updateSortChildren())
263
+ }
264
+ }
265
+ return super.__setAttr(attrName, newValue)
266
+ }
267
+
268
+ override __getAttr(attrName: string): IValue {
269
+ if (this.canvas && canvasSizeAttrs.includes(attrName)) return this.canvas[attrName]
270
+ return super.__getAttr(attrName)
271
+ }
272
+
273
+ protected __changeCanvasSize(attrName: string, newValue: number): void {
274
+ const data = DataHelper.copyAttrs({}, this.canvas, canvasSizeAttrs)
275
+ data[attrName] = (this.config as IObject)[attrName] = newValue
276
+ if (newValue) this.canvas.stopAutoLayout()
277
+ this.__doResize(data as IScreenSizeData)
278
+ }
279
+
280
+ protected __changeFill(newValue: string): void {
281
+ this.config.fill = newValue as string
282
+ if (this.canvas.allowBackgroundColor) {
283
+ this.canvas.backgroundColor = newValue as string
284
+ } else {
285
+ this.forceRender()
286
+ }
287
+ }
288
+
289
+ protected __onCreated(): void {
290
+ this.created = true
291
+ }
292
+
293
+ protected __onReady(): void {
294
+ if (this.ready) return
295
+ this.ready = true
296
+ this.emitLeafer(LeaferEvent.BEFORE_READY)
297
+ this.emitLeafer(LeaferEvent.READY)
298
+ this.emitLeafer(LeaferEvent.AFTER_READY)
299
+ WaitHelper.run(this.__readyWait)
300
+ }
301
+
302
+ protected __onViewReady(): void {
303
+ if (this.viewReady) return
304
+ this.viewReady = true
305
+ this.emitLeafer(LeaferEvent.VIEW_READY)
306
+ WaitHelper.run(this.__viewReadyWait)
307
+ }
308
+
309
+ protected __onNextRender(): void {
310
+ if (this.viewReady) {
311
+ WaitHelper.run(this.__nextRenderWait)
312
+
313
+ const { imageReady } = this
314
+ if (imageReady && !this.viewCompleted) this.__checkViewCompleted()
315
+ if (!imageReady) this.viewCompleted = false
316
+ }
317
+ }
318
+
319
+ protected __checkViewCompleted(emit: boolean = true): void {
320
+ this.nextRender(() => {
321
+ if (this.imageReady) {
322
+ if (emit) this.emitLeafer(LeaferEvent.VIEW_COMPLETED)
323
+ WaitHelper.run(this.__viewCompletedWait)
324
+ this.viewCompleted = true
325
+ }
326
+ })
327
+ }
328
+
329
+ protected __onWatchData(): void {
330
+ if (this.watcher.childrenChanged && this.interaction) {
331
+ this.nextRender(() => this.interaction.updateCursor())
332
+ }
333
+ }
334
+
335
+ public waitInit(item: IFunction, bind?: IObject): void {
336
+ if (bind) item = item.bind(bind)
337
+ if (!this.__initWait) this.__initWait = [] // set() use
338
+ this.canvas ? item() : this.__initWait.push(item)
339
+ }
340
+
341
+ public waitReady(item: IFunction, bind?: IObject): void {
342
+ if (bind) item = item.bind(bind)
343
+ this.ready ? item() : this.__readyWait.push(item)
344
+ }
345
+
346
+ public waitViewReady(item: IFunction, bind?: IObject): void {
347
+ if (bind) item = item.bind(bind)
348
+ this.viewReady ? item() : this.__viewReadyWait.push(item)
349
+ }
350
+
351
+ public waitViewCompleted(item: IFunction, bind?: IObject): void {
352
+ if (bind) item = item.bind(bind)
353
+ this.__viewCompletedWait.push(item)
354
+ if (this.viewCompleted) {
355
+ this.__checkViewCompleted(false)
356
+ } else {
357
+ if (!this.running) this.start()
358
+ }
359
+ }
360
+
361
+ public nextRender(item: IFunction, bind?: IObject, off?: 'off'): void {
362
+ if (bind) item = item.bind(bind)
363
+ const list = this.__nextRenderWait
364
+ if (off) {
365
+ for (let i = 0; i < list.length; i++) {
366
+ if (list[i] === item) { list.splice(i, 1); break }
367
+ }
368
+ } else {
369
+ list.push(item)
370
+ }
371
+ }
372
+
373
+ // need view plugin
374
+ public zoom(_zoomType: IZoomType, _padding?: IFourNumber, _fixedScale?: boolean): IBoundsData {
375
+ return debug.error('need @leafer-in/view') as undefined
376
+ }
377
+
378
+ // interaction window rewrite
379
+ public getValidMove(moveX: number, moveY: number): IPointData { return { x: moveX, y: moveY } }
380
+ public getValidScale(changeScale: number): number { return changeScale }
381
+
382
+
383
+ public getWorldPointByClient(clientPoint: IClientPointData, updateClient?: boolean): IPointData {
384
+ return this.interaction && this.interaction.getLocal(clientPoint, updateClient)
385
+ }
386
+
387
+ protected __checkUpdateLayout(): void {
388
+ this.__layout.update()
389
+ }
390
+
391
+ protected emitLeafer(type: string): void {
392
+ this.emitEvent(new LeaferEvent(type, this))
393
+ }
394
+
395
+ protected __listenEvents(): void {
396
+ const runId = Run.start('FirstCreate ' + this.innerName)
397
+ this.once(LeaferEvent.START, () => Run.end(runId))
398
+ this.once(LayoutEvent.START, () => this.updateLazyBounds())
399
+ this.once(LayoutEvent.END, () => this.__onReady())
400
+ this.once(RenderEvent.START, () => this.__onCreated())
401
+ this.once(RenderEvent.END, () => this.__onViewReady())
402
+ this.__eventIds.push(
403
+ this.on_(WatchEvent.DATA, this.__onWatchData, this),
404
+ this.on_(RenderEvent.NEXT, this.__onNextRender, this),
405
+ this.on_(LayoutEvent.CHECK_UPDATE, this.__checkUpdateLayout, this)
406
+ )
407
+ }
408
+
409
+ protected __removeListenEvents(): void {
410
+ this.off_(this.__eventIds)
411
+ this.__eventIds.length = 0
412
+ }
413
+
414
+ override destroy(sync?: boolean): void {
415
+ const doDestory = () => {
416
+ if (!this.destroyed) {
417
+ Leafer.list.remove(this)
418
+ try {
419
+ this.stop()
420
+ this.emitEvent(new LeaferEvent(LeaferEvent.END, this))
421
+ this.__removeListenEvents()
422
+
423
+ this.__controllers.forEach(item => {
424
+ if (!(this.parent && item === this.interaction)) item.destroy()
425
+ })
426
+ this.__controllers.length = 0
427
+
428
+ if (!this.parent) {
429
+ if (this.selector) this.selector.destroy()
430
+ if (this.hitCanvasManager) this.hitCanvasManager.destroy()
431
+ this.canvasManager.destroy()
432
+ }
433
+
434
+ this.canvas.destroy()
435
+
436
+ this.config.view = this.view = null
437
+ if (this.userConfig) this.userConfig.view = null
438
+
439
+ super.destroy()
440
+
441
+ setTimeout(() => { ImageManager.clearRecycled() }, 100)
442
+ } catch (e) {
443
+ debug.error(e)
444
+ }
445
+ }
446
+ }
447
+ sync ? doDestory() : setTimeout(doDestory)
448
+ }
449
+ }
package/src/Line.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { IPointData, INumber } from '@leafer/interface'
2
- import { PathBounds, PathCommandDataHelper, PointHelper, boundsType, pathType, affectStrokeBoundsType, dataProcessor, registerUI, PathScaler } from '@leafer/core'
2
+ import { PathBounds, PathCommandDataHelper, PointHelper, boundsType, pathType, affectStrokeBoundsType, dataProcessor, registerUI, getPointData } from '@leafer/core'
3
3
 
4
4
  import { ILine, ILineData, ILineInputData, IStrokeAlign } from '@leafer-ui/interface'
5
5
  import { LineData } from '@leafer-ui/data'
6
6
 
7
7
  import { UI } from './UI'
8
+ import { PathArrow } from '@leafer-ui/external'
8
9
 
9
10
 
10
11
  const { moveTo, lineTo, drawPoints } = PathCommandDataHelper
@@ -13,7 +14,7 @@ const { toBounds } = PathBounds
13
14
 
14
15
 
15
16
  @registerUI()
16
- export class Line extends UI implements ILine {
17
+ export class Line extends UI implements ILine { // tip: rewrited Polygon
17
18
 
18
19
  public get __tag() { return 'Line' }
19
20
 
@@ -21,20 +22,23 @@ export class Line extends UI implements ILine {
21
22
  declare public __: ILineData
22
23
 
23
24
  @affectStrokeBoundsType('center')
24
- declare public strokeAlign: IStrokeAlign
25
+ declare public strokeAlign?: IStrokeAlign
25
26
 
26
27
  @boundsType(0)
27
- declare public height: INumber
28
+ declare public height?: INumber
28
29
 
29
30
  @pathType()
30
- public points: number[]
31
+ public points?: number[]
31
32
 
32
33
  @pathType(0)
33
- public curve: boolean | number
34
+ public curve?: boolean | number
35
+
36
+ @pathType(false)
37
+ declare public closed?: boolean
34
38
 
35
39
  public get toPoint(): IPointData {
36
40
  const { width, rotation } = this.__
37
- const to: IPointData = { x: 0, y: 0 }
41
+ const to: IPointData = getPointData()
38
42
 
39
43
  if (width) to.x = width
40
44
  if (rotation) rotate(to, rotation)
@@ -55,11 +59,12 @@ export class Line extends UI implements ILine {
55
59
 
56
60
  public __updatePath(): void {
57
61
 
58
- const path: number[] = this.__.path = []
62
+ const data = this.__
63
+ const path: number[] = data.path = []
59
64
 
60
- if (this.__.points) {
65
+ if (data.points) {
61
66
 
62
- drawPoints(path, this.__.points, false)
67
+ drawPoints(path, data.points, false, data.closed)
63
68
 
64
69
  } else {
65
70
 
@@ -70,8 +75,10 @@ export class Line extends UI implements ILine {
70
75
  }
71
76
 
72
77
  public __updateRenderPath(): void {
73
- if (this.__.points && this.__.curve) {
74
- drawPoints(this.__.__pathForRender = [], this.__.points, this.__.curve, this.__tag !== 'Line')
78
+ const data = this.__
79
+ if (!this.pathInputed && data.points && data.curve) {
80
+ drawPoints(data.__pathForRender = [], data.points, data.curve, data.closed)
81
+ if (data.__useArrow) PathArrow.addArrows(this, false)
75
82
  } else {
76
83
  super.__updateRenderPath()
77
84
  }
@@ -85,22 +92,4 @@ export class Line extends UI implements ILine {
85
92
  }
86
93
  }
87
94
 
88
- public __scaleResize(scaleX: number, scaleY: number): void {
89
- if (this.points) {
90
- PathScaler.scalePoints(this.__.points, scaleX, scaleY)
91
- this.points = this.__.points
92
- } else {
93
-
94
- if (this.__tag === 'Line') {
95
- const point = this.toPoint
96
- point.x *= scaleX
97
- point.y *= scaleY
98
- this.toPoint = point
99
- } else {
100
- // Polygon ...
101
- super.__scaleResize(scaleX, scaleY)
102
- }
103
- }
104
- }
105
-
106
95
  }
package/src/Path.ts CHANGED
@@ -1,14 +1,11 @@
1
- import { IPathCommandData, IWindingRule } from '@leafer/interface'
2
- import { PathBounds, dataProcessor, pathType, affectStrokeBoundsType, registerUI, PathScaler } from '@leafer/core'
1
+ import { dataProcessor, affectStrokeBoundsType, registerUI } from '@leafer/core'
3
2
 
4
- import { IPath, IPathData, IPathInputData, IPathString, IStrokeAlign } from '@leafer-ui/interface'
3
+ import { IPath, IPathData, IPathInputData, IStrokeAlign } from '@leafer-ui/interface'
5
4
  import { PathData } from '@leafer-ui/data'
6
5
 
7
6
  import { UI } from './UI'
8
7
 
9
8
 
10
- const { toBounds } = PathBounds
11
-
12
9
  @registerUI()
13
10
  export class Path extends UI implements IPath {
14
11
 
@@ -17,26 +14,12 @@ export class Path extends UI implements IPath {
17
14
  @dataProcessor(PathData)
18
15
  declare public __: IPathData
19
16
 
20
- @pathType()
21
- public path: IPathCommandData | IPathString
22
-
23
- @pathType()
24
- public windingRule: IWindingRule
25
-
26
17
  @affectStrokeBoundsType('center')
27
- declare public strokeAlign: IStrokeAlign
18
+ declare public strokeAlign?: IStrokeAlign
28
19
 
29
20
  constructor(data?: IPathInputData) {
30
21
  super(data)
31
- }
32
-
33
- public __scaleResize(scaleX: number, scaleY: number): void {
34
- PathScaler.scale(this.__.path, scaleX, scaleY)
35
- this.path = this.__.path
36
- }
37
-
38
- public __updateBoxBounds(): void {
39
- toBounds(this.__.path, this.__layout.boxBounds)
22
+ this.__.__pathInputed = 2
40
23
  }
41
24
 
42
25
  }
package/src/Pen.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PathCreator, dataProcessor, registerUI, useModule } from '@leafer/core'
1
+ import { PathCreator, dataProcessor, defineKey, registerUI, useModule } from '@leafer/core'
2
2
 
3
3
  import { IPenData, IPenInputData, IPathInputData, IPathCommandData, IPath, IPen } from '@leafer-ui/interface'
4
4
  import { PenData } from '@leafer-ui/data'
@@ -7,7 +7,7 @@ import { Group } from './Group'
7
7
  import { Path } from './Path'
8
8
 
9
9
 
10
- @useModule(PathCreator, ['beginPath'])
10
+ @useModule(PathCreator, ['set', 'beginPath', 'path'])
11
11
  @registerUI()
12
12
  export class Pen extends Group implements IPen {
13
13
 
@@ -18,7 +18,11 @@ export class Pen extends Group implements IPen {
18
18
 
19
19
  public pathElement: IPath
20
20
  public pathStyle: IPathInputData
21
- public path: IPathCommandData
21
+
22
+ @penPathType()
23
+ declare public path: IPathCommandData // use __path, readonly
24
+
25
+ public __path: IPathCommandData
22
26
 
23
27
  constructor(data?: IPenInputData) {
24
28
  super(data)
@@ -27,13 +31,13 @@ export class Pen extends Group implements IPen {
27
31
  public setStyle(data: IPathInputData): Pen {
28
32
  const path = this.pathElement = new Path(data)
29
33
  this.pathStyle = data
30
- this.path = path.path as IPathCommandData || (path.path = [])
34
+ this.__path = path.path as IPathCommandData || (path.path = [])
31
35
  this.add(path)
32
36
  return this
33
37
  }
34
38
 
35
39
  public beginPath(): Pen {
36
- this.path.length = 0
40
+ this.__path.length = 0
37
41
  this.paint()
38
42
  return this
39
43
  }
@@ -72,13 +76,19 @@ export class Pen extends Group implements IPen {
72
76
 
73
77
  public drawPoints(_points: number[], _curve?: boolean | number, _close?: boolean): Pen { return this }
74
78
 
79
+ public clearPath(): Pen { return this }
75
80
 
76
81
  public paint(): void {
77
82
  this.pathElement.forceUpdate('path')
78
83
  }
79
84
 
80
- public clear(): void {
81
- this.removeAll(true)
82
- }
83
85
 
86
+ }
87
+
88
+ function penPathType() {
89
+ return (target: IPen, key: string) => {
90
+ defineKey(target, key, {
91
+ get() { return this.__path }
92
+ })
93
+ }
84
94
  }
package/src/Polygon.ts CHANGED
@@ -22,13 +22,13 @@ export class Polygon extends UI implements IPolygon {
22
22
  declare public __: IPolygonData
23
23
 
24
24
  @pathType(3)
25
- sides: INumber
25
+ public sides?: INumber
26
26
 
27
27
  @pathType()
28
- points: number[]
28
+ public points?: number[]
29
29
 
30
30
  @pathType(0)
31
- curve: boolean | number
31
+ public curve?: boolean | number
32
32
 
33
33
  constructor(data?: IPolygonInputData) {
34
34
  super(data)
@@ -64,7 +64,4 @@ export class Polygon extends UI implements IPolygon {
64
64
  @rewrite(line.__updateBoxBounds)
65
65
  public __updateBoxBounds(): void { }
66
66
 
67
- @rewrite(line.__scaleResize)
68
- public __scaleResize(_scaleX: number, _scaleY: number): void { }
69
-
70
67
  }