@leafer-ui/display 1.0.0-beta.9 → 1.0.0-rc.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 +12 -9
- package/src/Arrow.ts +27 -0
- package/src/Box.ts +13 -6
- package/src/Canvas.ts +10 -11
- package/src/Ellipse.ts +10 -7
- package/src/Frame.ts +8 -6
- package/src/Group.ts +58 -18
- package/src/Image.ts +7 -27
- package/src/Leafer.ts +417 -0
- package/src/Line.ts +38 -22
- package/src/Path.ts +2 -2
- package/src/Pen.ts +7 -5
- package/src/Polygon.ts +35 -12
- package/src/Rect.ts +7 -11
- package/src/Star.ts +7 -7
- package/src/Text.ts +65 -28
- package/src/UI.ts +166 -57
- package/src/index.ts +1 -0
- package/types/index.d.ts +368 -0
package/src/Leafer.ts
ADDED
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
import { ILeaferCanvas, IRenderer, ILayouter, ISelector, IWatcher, IInteraction, ILeaferConfig, ICanvasManager, IHitCanvasManager, IAutoBounds, IScreenSizeData, IResizeEvent, ILeaf, IEventListenerId, ITimer, IValue, IObject, IControl, IPointData, ILeaferType, ICursorType, IBoundsData } from '@leafer/interface'
|
|
2
|
+
import { AutoBounds, LayoutEvent, ResizeEvent, LeaferEvent, CanvasManager, ImageManager, DataHelper, Creator, Run, Debug, RenderEvent, registerUI, boundsType, canvasSizeAttrs, dataProcessor, WaitHelper, WatchEvent, Bounds } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { ILeaferInputData, ILeaferData, IFunction, IUIInputData, ILeafer, IGroup, 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
|
+
public get __tag() { return 'Leafer' }
|
|
15
|
+
|
|
16
|
+
@dataProcessor(LeaferData)
|
|
17
|
+
declare public __: ILeaferData
|
|
18
|
+
|
|
19
|
+
@boundsType()
|
|
20
|
+
public pixelRatio: number
|
|
21
|
+
|
|
22
|
+
public get isApp(): boolean { return false }
|
|
23
|
+
public get app(): ILeafer { return this.parent || this }
|
|
24
|
+
|
|
25
|
+
declare public parent?: IApp
|
|
26
|
+
|
|
27
|
+
public running: boolean
|
|
28
|
+
public created: boolean
|
|
29
|
+
public ready: boolean
|
|
30
|
+
public viewReady: boolean
|
|
31
|
+
public viewCompleted: boolean
|
|
32
|
+
public get imageReady(): boolean { return this.viewReady && ImageManager.isComplete }
|
|
33
|
+
public get layoutLocked() { return !this.layouter.running }
|
|
34
|
+
|
|
35
|
+
public transforming: boolean
|
|
36
|
+
|
|
37
|
+
public view: unknown
|
|
38
|
+
|
|
39
|
+
// manager
|
|
40
|
+
public canvas: ILeaferCanvas
|
|
41
|
+
public renderer: IRenderer
|
|
42
|
+
|
|
43
|
+
public watcher: IWatcher
|
|
44
|
+
public layouter: ILayouter
|
|
45
|
+
|
|
46
|
+
public selector?: ISelector
|
|
47
|
+
public interaction?: IInteraction
|
|
48
|
+
|
|
49
|
+
public canvasManager: ICanvasManager
|
|
50
|
+
public hitCanvasManager?: IHitCanvasManager
|
|
51
|
+
|
|
52
|
+
// plugin
|
|
53
|
+
public editor: IEditorBase
|
|
54
|
+
|
|
55
|
+
public zoomLayer: IGroup = this
|
|
56
|
+
|
|
57
|
+
public userConfig: ILeaferConfig
|
|
58
|
+
public config: ILeaferConfig = {
|
|
59
|
+
type: 'design',
|
|
60
|
+
start: true,
|
|
61
|
+
hittable: true,
|
|
62
|
+
smooth: true,
|
|
63
|
+
zoom: {
|
|
64
|
+
min: 0.02,
|
|
65
|
+
max: 256
|
|
66
|
+
},
|
|
67
|
+
move: {
|
|
68
|
+
holdSpaceKey: true,
|
|
69
|
+
holdMiddleKey: true,
|
|
70
|
+
dragOut: true,
|
|
71
|
+
autoDistance: 2
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public autoLayout?: IAutoBounds
|
|
76
|
+
|
|
77
|
+
public get cursorPoint(): IPointData { return (this.interaction && this.interaction.hoverData) || { x: this.width / 2, y: this.height / 2 } }
|
|
78
|
+
public leafs = 0
|
|
79
|
+
|
|
80
|
+
public __eventIds: IEventListenerId[] = []
|
|
81
|
+
protected __startTimer: ITimer
|
|
82
|
+
protected __controllers: IControl[] = []
|
|
83
|
+
|
|
84
|
+
protected __readyWait: IFunction[] = []
|
|
85
|
+
protected __viewReadyWait: IFunction[] = []
|
|
86
|
+
protected __viewCompletedWait: IFunction[] = []
|
|
87
|
+
public __nextRenderWait: IFunction[] = []
|
|
88
|
+
|
|
89
|
+
constructor(userConfig?: ILeaferConfig, data?: ILeaferInputData) {
|
|
90
|
+
super(data)
|
|
91
|
+
this.userConfig = userConfig
|
|
92
|
+
if (userConfig && (userConfig.view || userConfig.width)) this.init(userConfig)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public init(userConfig?: ILeaferConfig, parentApp?: IApp): void {
|
|
96
|
+
if (this.canvas) return
|
|
97
|
+
|
|
98
|
+
this.__setLeafer(this)
|
|
99
|
+
if (userConfig) DataHelper.assign(this.config, userConfig)
|
|
100
|
+
|
|
101
|
+
let start: boolean
|
|
102
|
+
const { config } = this
|
|
103
|
+
|
|
104
|
+
this.initType(config.type) // LeaferType
|
|
105
|
+
|
|
106
|
+
// render / layout
|
|
107
|
+
this.canvas = Creator.canvas(config)
|
|
108
|
+
this.__controllers.push(
|
|
109
|
+
this.renderer = Creator.renderer(this, this.canvas, config),
|
|
110
|
+
this.watcher = Creator.watcher(this, config),
|
|
111
|
+
this.layouter = Creator.layouter(this, config)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
if (this.isApp) this.__setApp()
|
|
115
|
+
this.__checkAutoLayout(config)
|
|
116
|
+
this.view = this.canvas.view
|
|
117
|
+
|
|
118
|
+
// interaction / manager
|
|
119
|
+
if (parentApp) {
|
|
120
|
+
this.__bindApp(parentApp)
|
|
121
|
+
start = parentApp.running
|
|
122
|
+
} else {
|
|
123
|
+
this.selector = Creator.selector(this)
|
|
124
|
+
this.interaction = Creator.interaction(this, this.canvas, this.selector, config)
|
|
125
|
+
|
|
126
|
+
if (this.interaction) {
|
|
127
|
+
this.__controllers.unshift(this.interaction)
|
|
128
|
+
this.hitCanvasManager = Creator.hitCanvasManager()
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.canvasManager = new CanvasManager()
|
|
132
|
+
|
|
133
|
+
start = config.start
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.hittable = config.hittable
|
|
137
|
+
this.fill = config.fill
|
|
138
|
+
this.canvasManager.add(this.canvas)
|
|
139
|
+
|
|
140
|
+
this.__listenEvents()
|
|
141
|
+
|
|
142
|
+
if (start) this.__startTimer = setTimeout(this.start.bind(this))
|
|
143
|
+
|
|
144
|
+
this.onInit() // can rewrite init event
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public onInit(): void { }
|
|
148
|
+
|
|
149
|
+
public initType(_type: ILeaferType): void { } // rewrite in @leafer-ui/type
|
|
150
|
+
|
|
151
|
+
public set(data: IUIInputData): void {
|
|
152
|
+
if (!this.children) {
|
|
153
|
+
setTimeout(() => {
|
|
154
|
+
super.set(data)
|
|
155
|
+
})
|
|
156
|
+
} else {
|
|
157
|
+
super.set(data)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public start(): void {
|
|
162
|
+
clearTimeout(this.__startTimer)
|
|
163
|
+
if (!this.running && this.canvas) {
|
|
164
|
+
this.ready ? this.emitLeafer(LeaferEvent.RESTART) : this.emitLeafer(LeaferEvent.START)
|
|
165
|
+
this.__controllers.forEach(item => item.start())
|
|
166
|
+
if (!this.isApp) this.renderer.render()
|
|
167
|
+
this.running = true
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
public stop(): void {
|
|
172
|
+
clearTimeout(this.__startTimer)
|
|
173
|
+
if (this.running && this.canvas) {
|
|
174
|
+
this.__controllers.forEach(item => item.stop())
|
|
175
|
+
this.running = false
|
|
176
|
+
this.emitLeafer(LeaferEvent.STOP)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
public unlockLayout(): void {
|
|
181
|
+
this.layouter.start()
|
|
182
|
+
this.updateLayout()
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
public lockLayout(): void {
|
|
186
|
+
this.updateLayout()
|
|
187
|
+
this.layouter.stop()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public resize(size: IScreenSizeData): void {
|
|
191
|
+
const data = DataHelper.copyAttrs({}, size, canvasSizeAttrs)
|
|
192
|
+
Object.keys(data).forEach(key => (this as any)[key] = data[key])
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
public forceFullRender(): void {
|
|
196
|
+
this.forceRender()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
public forceRender(bounds?: IBoundsData): void {
|
|
200
|
+
this.renderer.addBlock(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
|
+
protected __doResize(size: IScreenSizeData): void {
|
|
210
|
+
if (!this.canvas || this.canvas.isSameSize(size)) return
|
|
211
|
+
const old = DataHelper.copyAttrs({}, this.canvas, canvasSizeAttrs) as IScreenSizeData
|
|
212
|
+
this.canvas.resize(size)
|
|
213
|
+
this.__onResize(new ResizeEvent(size, old))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
protected __onResize(event: IResizeEvent): void {
|
|
217
|
+
this.emitEvent(event)
|
|
218
|
+
DataHelper.copyAttrs(this.__, event, canvasSizeAttrs)
|
|
219
|
+
setTimeout(() => { if (this.canvasManager) this.canvasManager.clearRecycled() }, 0)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
protected __setApp(): void { }
|
|
223
|
+
|
|
224
|
+
protected __bindApp(app: IApp): void {
|
|
225
|
+
this.selector = app.selector
|
|
226
|
+
this.interaction = app.interaction
|
|
227
|
+
|
|
228
|
+
this.canvasManager = app.canvasManager
|
|
229
|
+
this.hitCanvasManager = app.hitCanvasManager
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
public __setLeafer(leafer: ILeafer): void {
|
|
233
|
+
this.leafer = leafer
|
|
234
|
+
this.isLeafer = !!leafer
|
|
235
|
+
this.__level = 1
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public setZoomLayer(zoomLayer: ILeaf): void {
|
|
239
|
+
this.zoomLayer = zoomLayer as IGroup
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
protected __checkAutoLayout(config: ILeaferConfig): void {
|
|
243
|
+
if (!config.width || !config.height) {
|
|
244
|
+
this.autoLayout = new AutoBounds(config)
|
|
245
|
+
this.canvas.startAutoLayout(this.autoLayout, this.__onResize.bind(this))
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
public __setAttr(attrName: string, newValue: IValue): void {
|
|
250
|
+
if (this.canvas) {
|
|
251
|
+
if (canvasSizeAttrs.includes(attrName)) {
|
|
252
|
+
this.__changeCanvasSize(attrName, newValue as number)
|
|
253
|
+
} else if (attrName === 'fill') {
|
|
254
|
+
this.__changeFill(newValue as string)
|
|
255
|
+
} else if (attrName === 'hittable') {
|
|
256
|
+
this.canvas.hittable = newValue as boolean
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
super.__setAttr(attrName, newValue)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
public __getAttr(attrName: string): IValue {
|
|
263
|
+
if (this.canvas && canvasSizeAttrs.includes(attrName)) return this.canvas[attrName]
|
|
264
|
+
return super.__getAttr(attrName)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
protected __changeCanvasSize(attrName: string, newValue: number): void {
|
|
268
|
+
const data = DataHelper.copyAttrs({}, this.canvas, canvasSizeAttrs)
|
|
269
|
+
data[attrName] = (this.config as IObject)[attrName] = newValue
|
|
270
|
+
if (newValue) this.canvas.stopAutoLayout()
|
|
271
|
+
this.__doResize(data as IScreenSizeData)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
protected __changeFill(newValue: string): void {
|
|
275
|
+
this.config.fill = newValue as string
|
|
276
|
+
if (this.canvas.allowBackgroundColor) {
|
|
277
|
+
this.canvas.backgroundColor = newValue as string
|
|
278
|
+
} else {
|
|
279
|
+
this.forceFullRender()
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
protected __onCreated(): void {
|
|
284
|
+
this.created = true
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
protected __onReady(): void {
|
|
288
|
+
if (this.ready) return
|
|
289
|
+
this.ready = true
|
|
290
|
+
this.emitLeafer(LeaferEvent.BEFORE_READY)
|
|
291
|
+
this.emitLeafer(LeaferEvent.READY)
|
|
292
|
+
this.emitLeafer(LeaferEvent.AFTER_READY)
|
|
293
|
+
WaitHelper.run(this.__readyWait)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
protected __onViewReady(): void {
|
|
297
|
+
if (this.viewReady) return
|
|
298
|
+
this.viewReady = true
|
|
299
|
+
this.emitLeafer(LeaferEvent.VIEW_READY)
|
|
300
|
+
WaitHelper.run(this.__viewReadyWait)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
protected __onNextRender(): void {
|
|
304
|
+
if (this.viewReady) {
|
|
305
|
+
WaitHelper.run(this.__nextRenderWait)
|
|
306
|
+
|
|
307
|
+
const { imageReady } = this
|
|
308
|
+
if (imageReady && !this.viewCompleted) this.__checkViewCompleted()
|
|
309
|
+
if (!imageReady) this.viewCompleted = false
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
protected __checkViewCompleted(emit: boolean = true): void {
|
|
314
|
+
this.nextRender(() => {
|
|
315
|
+
if (this.imageReady) {
|
|
316
|
+
if (emit) this.emitLeafer(LeaferEvent.VIEW_COMPLETED)
|
|
317
|
+
WaitHelper.run(this.__viewCompletedWait)
|
|
318
|
+
this.viewCompleted = true
|
|
319
|
+
}
|
|
320
|
+
})
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
protected __onWatchData(): void {
|
|
324
|
+
if (this.watcher.childrenChanged && this.interaction) {
|
|
325
|
+
this.nextRender(() => this.interaction.updateCursor())
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
public waitReady(item: IFunction): void {
|
|
330
|
+
this.ready ? item() : this.__readyWait.push(item)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
public waitViewReady(item: IFunction): void {
|
|
334
|
+
this.viewReady ? item() : this.__viewReadyWait.push(item)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
public waitViewCompleted(item: IFunction): void {
|
|
338
|
+
this.__viewCompletedWait.push(item)
|
|
339
|
+
if (this.viewCompleted) {
|
|
340
|
+
this.__checkViewCompleted(false)
|
|
341
|
+
} else {
|
|
342
|
+
if (!this.running) this.start()
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
public nextRender(item: IFunction, off?: 'off'): void {
|
|
347
|
+
const list = this.__nextRenderWait
|
|
348
|
+
if (off) {
|
|
349
|
+
for (let i = 0; i < list.length; i++) {
|
|
350
|
+
if (list[i] === item) { list.splice(i, 1); break }
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
list.push(item)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
protected __checkUpdateLayout(): void {
|
|
358
|
+
this.__layout.update()
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
protected emitLeafer(type: string): void {
|
|
362
|
+
this.emitEvent(new LeaferEvent(type, this))
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
protected __listenEvents(): void {
|
|
366
|
+
const runId = Run.start('FirstCreate ' + this.innerName)
|
|
367
|
+
this.once(LeaferEvent.START, () => Run.end(runId))
|
|
368
|
+
this.once(LayoutEvent.END, () => this.__onReady())
|
|
369
|
+
this.once(RenderEvent.START, () => this.__onCreated())
|
|
370
|
+
this.once(RenderEvent.END, () => this.__onViewReady())
|
|
371
|
+
this.__eventIds.push(
|
|
372
|
+
this.on_(WatchEvent.DATA, this.__onWatchData, this),
|
|
373
|
+
this.on_(RenderEvent.NEXT, this.__onNextRender, this),
|
|
374
|
+
this.on_(LayoutEvent.CHECK_UPDATE, this.__checkUpdateLayout, this)
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
protected __removeListenEvents(): void {
|
|
379
|
+
this.off_(this.__eventIds)
|
|
380
|
+
this.__eventIds.length = 0
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
public destroy(): void {
|
|
384
|
+
setTimeout(() => {
|
|
385
|
+
if (!this.destroyed) {
|
|
386
|
+
try {
|
|
387
|
+
this.stop()
|
|
388
|
+
this.emitEvent(new LeaferEvent(LeaferEvent.END, this))
|
|
389
|
+
this.__removeListenEvents()
|
|
390
|
+
|
|
391
|
+
this.__controllers.forEach(item => {
|
|
392
|
+
if (!(this.parent && item === this.interaction)) item.destroy()
|
|
393
|
+
})
|
|
394
|
+
this.__controllers.length = 0
|
|
395
|
+
|
|
396
|
+
if (!this.parent) {
|
|
397
|
+
if (this.selector) this.selector.destroy()
|
|
398
|
+
if (this.hitCanvasManager) this.hitCanvasManager.destroy()
|
|
399
|
+
this.canvasManager.destroy()
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
this.canvas.destroy()
|
|
403
|
+
|
|
404
|
+
this.config.view = this.view = null
|
|
405
|
+
if (this.userConfig) this.userConfig.view = null
|
|
406
|
+
|
|
407
|
+
super.destroy()
|
|
408
|
+
|
|
409
|
+
setTimeout(() => { ImageManager.clearRecycled() }, 100)
|
|
410
|
+
} catch (e) {
|
|
411
|
+
debug.error(e)
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
}
|
|
417
|
+
}
|
package/src/Line.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IPointData,
|
|
2
|
-
import { PathCommandDataHelper, PointHelper,
|
|
1
|
+
import { IPointData, INumber } from '@leafer/interface'
|
|
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'
|
|
@@ -7,11 +7,9 @@ import { LineData } from '@leafer-ui/data'
|
|
|
7
7
|
import { UI } from './UI'
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
const { moveTo, lineTo } = PathCommandDataHelper
|
|
10
|
+
const { moveTo, lineTo, drawPoints } = PathCommandDataHelper
|
|
11
11
|
const { rotate, getAngle, getDistance, defaultPoint } = PointHelper
|
|
12
|
-
const {
|
|
13
|
-
|
|
14
|
-
const pointBounds = {} as ITwoPointBoundsData
|
|
12
|
+
const { toBounds } = PathBounds
|
|
15
13
|
|
|
16
14
|
|
|
17
15
|
@registerUI()
|
|
@@ -20,25 +18,26 @@ export class Line extends UI implements ILine {
|
|
|
20
18
|
public get __tag() { return 'Line' }
|
|
21
19
|
|
|
22
20
|
@dataProcessor(LineData)
|
|
23
|
-
public __: ILineData
|
|
24
|
-
|
|
25
|
-
@boundsType()
|
|
26
|
-
public rotation: __Number
|
|
21
|
+
declare public __: ILineData
|
|
27
22
|
|
|
28
23
|
@affectStrokeBoundsType('center')
|
|
29
|
-
public strokeAlign: IStrokeAlign
|
|
24
|
+
declare public strokeAlign: IStrokeAlign
|
|
30
25
|
|
|
31
|
-
|
|
26
|
+
@boundsType(0)
|
|
27
|
+
declare public height: INumber
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
@pathType()
|
|
30
|
+
public points: number[]
|
|
35
31
|
|
|
32
|
+
@pathType(0)
|
|
33
|
+
public curve: boolean | number
|
|
34
|
+
|
|
35
|
+
public get toPoint(): IPointData {
|
|
36
36
|
const { width, rotation } = this.__
|
|
37
|
-
const to: IPointData =
|
|
37
|
+
const to: IPointData = getPointData()
|
|
38
38
|
|
|
39
39
|
if (width) to.x = width
|
|
40
40
|
if (rotation) rotate(to, rotation)
|
|
41
|
-
this.__toPoint = to
|
|
42
41
|
|
|
43
42
|
return to
|
|
44
43
|
}
|
|
@@ -57,16 +56,33 @@ export class Line extends UI implements ILine {
|
|
|
57
56
|
public __updatePath(): void {
|
|
58
57
|
|
|
59
58
|
const path: number[] = this.__.path = []
|
|
60
|
-
moveTo(path, 0, 0)
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
if (this.__.points) {
|
|
61
|
+
|
|
62
|
+
drawPoints(path, this.__.points, false)
|
|
63
|
+
|
|
64
|
+
} else {
|
|
65
|
+
|
|
66
|
+
moveTo(path, 0, 0)
|
|
67
|
+
lineTo(path, this.width, 0)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public __updateRenderPath(): void {
|
|
73
|
+
if (this.__.points && this.__.curve) {
|
|
74
|
+
drawPoints(this.__.__pathForRender = [], this.__.points, this.__.curve, this.__tag !== 'Line')
|
|
75
|
+
} else {
|
|
76
|
+
super.__updateRenderPath()
|
|
77
|
+
}
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
public __updateBoxBounds(): void {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
if (this.points) {
|
|
82
|
+
toBounds(this.__.__pathForRender, this.__layout.boxBounds)
|
|
83
|
+
} else {
|
|
84
|
+
super.__updateBoxBounds()
|
|
85
|
+
}
|
|
70
86
|
}
|
|
71
87
|
|
|
72
88
|
}
|
package/src/Path.ts
CHANGED
|
@@ -15,7 +15,7 @@ export class Path extends UI implements IPath {
|
|
|
15
15
|
public get __tag() { return 'Path' }
|
|
16
16
|
|
|
17
17
|
@dataProcessor(PathData)
|
|
18
|
-
public __: IPathData
|
|
18
|
+
declare public __: IPathData
|
|
19
19
|
|
|
20
20
|
@pathType()
|
|
21
21
|
public path: IPathCommandData | IPathString
|
|
@@ -24,7 +24,7 @@ export class Path extends UI implements IPath {
|
|
|
24
24
|
public windingRule: IWindingRule
|
|
25
25
|
|
|
26
26
|
@affectStrokeBoundsType('center')
|
|
27
|
-
public strokeAlign: IStrokeAlign
|
|
27
|
+
declare public strokeAlign: IStrokeAlign
|
|
28
28
|
|
|
29
29
|
constructor(data?: IPathInputData) {
|
|
30
30
|
super(data)
|
package/src/Pen.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PathCreator, dataProcessor, registerUI, useModule } from '@leafer/core'
|
|
2
2
|
|
|
3
|
-
import { IPenData, IPenInputData, IPathInputData, IPathCommandData, IPath } from '@leafer-ui/interface'
|
|
3
|
+
import { IPenData, IPenInputData, IPathInputData, IPathCommandData, IPath, IPen } from '@leafer-ui/interface'
|
|
4
4
|
import { PenData } from '@leafer-ui/data'
|
|
5
5
|
|
|
6
6
|
import { Group } from './Group'
|
|
@@ -9,12 +9,12 @@ import { Path } from './Path'
|
|
|
9
9
|
|
|
10
10
|
@useModule(PathCreator, ['beginPath'])
|
|
11
11
|
@registerUI()
|
|
12
|
-
export class Pen extends Group {
|
|
12
|
+
export class Pen extends Group implements IPen {
|
|
13
13
|
|
|
14
14
|
public get __tag() { return 'Pen' }
|
|
15
15
|
|
|
16
16
|
@dataProcessor(PenData)
|
|
17
|
-
public __: IPenData
|
|
17
|
+
declare public __: IPenData
|
|
18
18
|
|
|
19
19
|
public pathElement: IPath
|
|
20
20
|
public pathStyle: IPathInputData
|
|
@@ -66,9 +66,11 @@ export class Pen extends Group {
|
|
|
66
66
|
|
|
67
67
|
// moveTo, then draw
|
|
68
68
|
|
|
69
|
-
public
|
|
69
|
+
public drawEllipse(_x: number, _y: number, _radiusX: number, _radiusY: number, _rotation?: number, _startAngle?: number, _endAngle?: number, _anticlockwise?: boolean): Pen { return this }
|
|
70
70
|
|
|
71
|
-
public
|
|
71
|
+
public drawArc(_x: number, _y: number, _radius: number, _startAngle?: number, _endAngle?: number, _anticlockwise?: boolean): Pen { return this }
|
|
72
|
+
|
|
73
|
+
public drawPoints(_points: number[], _curve?: boolean | number, _close?: boolean): Pen { return this }
|
|
72
74
|
|
|
73
75
|
|
|
74
76
|
public paint(): void {
|
package/src/Polygon.ts
CHANGED
|
@@ -1,26 +1,34 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PathCommandDataHelper, dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
1
|
+
import { INumber } from '@leafer/interface'
|
|
2
|
+
import { PathCommandDataHelper, dataProcessor, pathType, registerUI, rewrite, rewriteAble } from '@leafer/core'
|
|
3
3
|
|
|
4
4
|
import { IPolygon, IPolygonData, IPolygonInputData } from '@leafer-ui/interface'
|
|
5
5
|
import { PolygonData } from '@leafer-ui/data'
|
|
6
6
|
|
|
7
7
|
import { UI } from './UI'
|
|
8
|
+
import { Line } from './Line'
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
const { sin, cos, PI } = Math
|
|
11
|
-
const { moveTo, lineTo, closePath } = PathCommandDataHelper
|
|
12
|
-
|
|
12
|
+
const { moveTo, lineTo, closePath, drawPoints } = PathCommandDataHelper
|
|
13
|
+
const line = Line.prototype
|
|
13
14
|
|
|
15
|
+
@rewriteAble()
|
|
14
16
|
@registerUI()
|
|
15
17
|
export class Polygon extends UI implements IPolygon {
|
|
16
18
|
|
|
17
19
|
public get __tag() { return 'Polygon' }
|
|
18
20
|
|
|
19
21
|
@dataProcessor(PolygonData)
|
|
20
|
-
public __: IPolygonData
|
|
22
|
+
declare public __: IPolygonData
|
|
21
23
|
|
|
22
24
|
@pathType(3)
|
|
23
|
-
sides:
|
|
25
|
+
sides: INumber
|
|
26
|
+
|
|
27
|
+
@pathType()
|
|
28
|
+
points: number[]
|
|
29
|
+
|
|
30
|
+
@pathType(0)
|
|
31
|
+
curve: boolean | number
|
|
24
32
|
|
|
25
33
|
constructor(data?: IPolygonInputData) {
|
|
26
34
|
super(data)
|
|
@@ -28,17 +36,32 @@ export class Polygon extends UI implements IPolygon {
|
|
|
28
36
|
|
|
29
37
|
public __updatePath(): void {
|
|
30
38
|
|
|
31
|
-
const { width, height, sides } = this.__
|
|
32
|
-
const rx = width / 2, ry = height / 2
|
|
33
|
-
|
|
34
39
|
const path: number[] = this.__.path = []
|
|
35
|
-
moveTo(path, rx, 0)
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
if (this.__.points) {
|
|
42
|
+
|
|
43
|
+
drawPoints(path, this.__.points, false, true)
|
|
44
|
+
|
|
45
|
+
} else {
|
|
46
|
+
|
|
47
|
+
const { width, height, sides } = this.__
|
|
48
|
+
const rx = width / 2, ry = height / 2
|
|
49
|
+
|
|
50
|
+
moveTo(path, rx, 0)
|
|
51
|
+
|
|
52
|
+
for (let i = 1; i < sides; i++) {
|
|
53
|
+
lineTo(path, rx + rx * sin((i * 2 * PI) / sides), ry - ry * cos((i * 2 * PI) / sides))
|
|
54
|
+
}
|
|
55
|
+
|
|
39
56
|
}
|
|
40
57
|
|
|
41
58
|
closePath(path)
|
|
42
59
|
}
|
|
43
60
|
|
|
61
|
+
@rewrite(line.__updateRenderPath)
|
|
62
|
+
public __updateRenderPath(): void { }
|
|
63
|
+
|
|
64
|
+
@rewrite(line.__updateBoxBounds)
|
|
65
|
+
public __updateBoxBounds(): void { }
|
|
66
|
+
|
|
44
67
|
}
|
package/src/Rect.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IPathDrawer, IPathCommandData
|
|
2
|
-
import { dataProcessor, registerUI, useModule } from '@leafer/core'
|
|
1
|
+
import { IPathDrawer, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { dataProcessor, registerUI, rewrite, rewriteAble, useModule } from '@leafer/core'
|
|
3
3
|
|
|
4
4
|
import { IRect, IRectInputData, IRectData } from '@leafer-ui/interface'
|
|
5
5
|
import { RectData } from '@leafer-ui/data'
|
|
@@ -9,24 +9,20 @@ import { UI } from './UI'
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
@useModule(RectRender)
|
|
12
|
+
@rewriteAble()
|
|
12
13
|
@registerUI()
|
|
13
14
|
export class Rect extends UI implements IRect {
|
|
14
15
|
|
|
15
16
|
public get __tag() { return 'Rect' }
|
|
16
17
|
|
|
17
18
|
@dataProcessor(RectData)
|
|
18
|
-
public __: IRectData
|
|
19
|
+
declare public __: IRectData
|
|
19
20
|
|
|
20
21
|
constructor(data?: IRectInputData) {
|
|
21
22
|
super(data)
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
drawer.roundRect(0, 0, width, height, cornerRadius)
|
|
28
|
-
} else {
|
|
29
|
-
drawer.rect(0, 0, width, height)
|
|
30
|
-
}
|
|
31
|
-
}
|
|
25
|
+
@rewrite(UI.prototype.__drawPathByBox)
|
|
26
|
+
public __drawPathByData(_drawer: IPathDrawer, _data: IPathCommandData): void { }
|
|
27
|
+
|
|
32
28
|
}
|