@leafer-ui/display 1.0.0-alpha.21 → 1.0.0-alpha.23

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer-ui/display",
3
- "version": "1.0.0-alpha.21",
3
+ "version": "1.0.0-alpha.23",
4
4
  "description": "@leafer-ui/display",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -19,13 +19,13 @@
19
19
  "leaferjs"
20
20
  ],
21
21
  "dependencies": {
22
- "@leafer/core": "1.0.0-alpha.21",
23
- "@leafer-ui/data": "1.0.0-alpha.21",
24
- "@leafer-ui/display-module": "1.0.0-alpha.21",
25
- "@leafer-ui/decorator": "1.0.0-alpha.21"
22
+ "@leafer/core": "1.0.0-alpha.23",
23
+ "@leafer-ui/data": "1.0.0-alpha.23",
24
+ "@leafer-ui/display-module": "1.0.0-alpha.23",
25
+ "@leafer-ui/decorator": "1.0.0-alpha.23"
26
26
  },
27
27
  "devDependencies": {
28
- "@leafer/interface": "1.0.0-alpha.21",
29
- "@leafer-ui/interface": "1.0.0-alpha.21"
28
+ "@leafer/interface": "1.0.0-alpha.23",
29
+ "@leafer-ui/interface": "1.0.0-alpha.23"
30
30
  }
31
31
  }
package/src/Ellipse.ts CHANGED
@@ -7,7 +7,6 @@ import { EllipseData } from '@leafer-ui/data'
7
7
  import { UI } from './UI'
8
8
 
9
9
 
10
-
11
10
  const { PI } = Math
12
11
  const { begin, moveTo, close, ellipse } = PathCreator
13
12
 
@@ -15,6 +14,8 @@ const { begin, moveTo, close, ellipse } = PathCreator
15
14
  @registerUI()
16
15
  export class Ellipse extends UI implements IEllipse {
17
16
 
17
+ public get __tag() { return 'Ellipse' }
18
+
18
19
  @dataProcessor(EllipseData)
19
20
  public __: IEllipseData
20
21
 
@@ -41,12 +42,14 @@ export class Ellipse extends UI implements IEllipse {
41
42
  if (innerRadius) {
42
43
 
43
44
  if (startAngle || endAngle) {
44
- ellipse(rx, ry, rx * (1 - innerRadius), ry * (1 - innerRadius), 0, startAngle * OneRadian, endAngle * OneRadian, false)
45
+ if (innerRadius < 1) ellipse(rx, ry, rx * innerRadius, ry * innerRadius, 0, startAngle * OneRadian, endAngle * OneRadian, false)
45
46
  ellipse(rx, ry, rx, ry, 0, endAngle * OneRadian, startAngle * OneRadian, true)
46
- close()
47
+ if (innerRadius < 1) close()
47
48
  } else {
48
- ellipse(rx, ry, rx * (1 - innerRadius), ry * (1 - innerRadius), 0, 0, 2 * PI, false)
49
- moveTo(width, ry)
49
+ if (innerRadius < 1) {
50
+ ellipse(rx, ry, rx * innerRadius, ry * innerRadius, 0, 0, 2 * PI, false)
51
+ moveTo(width, ry)
52
+ }
50
53
  ellipse(rx, ry, rx, ry, 0, 0, 2 * PI, true)
51
54
  }
52
55
 
package/src/Frame.ts CHANGED
@@ -20,6 +20,8 @@ const { copy, add } = BoundsHelper
20
20
  @registerUI()
21
21
  export class Frame extends Group implements IFrame {
22
22
 
23
+ public get __tag() { return 'Frame' }
24
+
23
25
  @dataProcessor(FrameData)
24
26
  public __: IFrameData
25
27
 
@@ -45,12 +47,12 @@ export class Frame extends Group implements IFrame {
45
47
  }
46
48
  }
47
49
 
48
- public __updateEventBounds(): void {
49
- this.__updateRectEventBounds()
50
+ public __updateStrokeBounds(): void {
51
+ this.__updateRectStrokeBounds()
50
52
  if (!this.__.clip) {
51
- const { eventBounds } = this.__layout
53
+ const { strokeBounds: eventBounds } = this.__layout
52
54
  copy(bounds, eventBounds)
53
- super.__updateEventBounds()
55
+ super.__updateStrokeBounds()
54
56
  add(eventBounds, bounds)
55
57
  }
56
58
  }
@@ -68,8 +70,8 @@ export class Frame extends Group implements IFrame {
68
70
  @rewrite(rect.__updateBoxBounds)
69
71
  public __updateRectBoxBounds(): void { }
70
72
 
71
- @rewrite(rect.__updateEventBounds)
72
- public __updateRectEventBounds(): void { }
73
+ @rewrite(rect.__updateStrokeBounds)
74
+ public __updateRectStrokeBounds(): void { }
73
75
 
74
76
  @rewrite(rect.__updateRenderBounds)
75
77
  public __updateRectRenderBounds(): void { }
package/src/Group.ts CHANGED
@@ -10,11 +10,24 @@ import { UI } from './UI'
10
10
  @registerUI()
11
11
  export class Group extends UI implements IGroup {
12
12
 
13
+ public get __tag() { return 'Group' }
14
+
13
15
  @dataProcessor(GroupData)
14
16
  public __: IGroupData
15
17
 
16
18
  public children: IUI[]
17
19
 
20
+ public set mask(child: IUI) {
21
+ if (this.__hasMask) this.__removeMask()
22
+ if (child) {
23
+ child.isMask = true
24
+ this.addAt(child, 0)
25
+ }
26
+ }
27
+ public get mask(): IUI {
28
+ return this.children.find(item => item.isMask)
29
+ }
30
+
18
31
  constructor(data?: IGroupInputData) {
19
32
  super(data)
20
33
  this.__isBranch = true
@@ -39,4 +52,20 @@ export class Group extends UI implements IGroup {
39
52
 
40
53
  public remove(_child?: IUI): void { }
41
54
 
55
+ protected __removeMask(child?: IUI): void {
56
+ if (child) {
57
+ child.isMask = false
58
+ this.remove(child)
59
+ } else {
60
+ const { children } = this
61
+ for (let i = 0, len = children.length; i < len; i++) {
62
+ child = children[i]
63
+ if (child.isMask) {
64
+ child.isMask = false
65
+ this.remove(child)
66
+ len--, i--
67
+ }
68
+ }
69
+ }
70
+ }
42
71
  }
package/src/Image.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ILeaferImage, __String } from '@leafer/interface'
2
- import { boundsType, dataProcessor, registerUI, Creator } from '@leafer/core'
2
+ import { ImageEvent, boundsType, dataProcessor, registerUI } from '@leafer/core'
3
3
 
4
- import { IImage, IImageInputData, IImageData } from '@leafer-ui/interface'
4
+ import { IImage, IImageInputData, IImageData, IImagePaint } from '@leafer-ui/interface'
5
5
  import { ImageData } from '@leafer-ui/data'
6
6
 
7
7
  import { Rect } from './Rect'
@@ -10,27 +10,41 @@ import { Rect } from './Rect'
10
10
  @registerUI()
11
11
  export class Image extends Rect implements IImage {
12
12
 
13
+ public get __tag() { return 'Image' }
14
+
13
15
  @dataProcessor(ImageData)
14
16
  public __: IImageData
15
17
 
16
18
  @boundsType('')
17
19
  public url: __String
18
20
 
19
- @boundsType('')
20
- public thumb: __String
21
+ public get ready(): boolean { return this.image?.ready }
21
22
 
22
- public __image: ILeaferImage
23
+ public image: ILeaferImage
23
24
 
24
25
  constructor(data?: IImageInputData) {
25
26
  super(data)
26
27
  }
27
28
 
28
29
  public __updateBoxBounds(): void {
29
- this.__image = Creator.image(this)
30
- }
31
30
 
31
+ let update: boolean
32
+
33
+ const { url } = this
34
+ const fills = this.fill as IImagePaint[]
35
+ if (fills) {
36
+ if (fills[0].url !== url) update = true
37
+ } else {
38
+ if (url) update = true
39
+ }
40
+
41
+ if (update) {
42
+ if (this.image) this.image = null
43
+ this.fill = { type: 'image', mode: 'strench', url }
44
+ this.once(ImageEvent.LOADED, (e) => this.image = e.image)
45
+ }
32
46
 
33
- public drawFill(): void {
47
+ super.__updateBoxBounds()
34
48
 
35
49
  }
36
50
 
package/src/Line.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { IPointData, ITwoPointBoundsData, __Number } from '@leafer/interface'
2
- import { PathCreator, PointHelper, TwoPointBoundsHelper, boundsType, dataProcessor, registerUI } from '@leafer/core'
2
+ import { PathCreator, PointHelper, TwoPointBoundsHelper, boundsType, affectEventBoundsType, dataProcessor, registerUI } from '@leafer/core'
3
3
 
4
- import { ILine, ILineData, ILineInputData } from '@leafer-ui/interface'
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'
@@ -17,12 +17,17 @@ const pointBounds = {} as ITwoPointBoundsData
17
17
  @registerUI()
18
18
  export class Line extends UI implements ILine {
19
19
 
20
+ public get __tag() { return 'Line' }
21
+
20
22
  @dataProcessor(LineData)
21
23
  public __: ILineData
22
24
 
23
25
  @boundsType()
24
26
  public rotation: __Number
25
27
 
28
+ @affectEventBoundsType('center')
29
+ public strokeAlign: IStrokeAlign
30
+
26
31
  protected __toPoint: IPointData
27
32
 
28
33
  public get toPoint(): IPointData {
package/src/Path.ts CHANGED
@@ -1,21 +1,19 @@
1
- import { ITwoPointBoundsData, ILeaferCanvas, IPathCommandData, IWindingRule } from '@leafer/interface'
2
- import { PathHelper, TwoPointBoundsHelper, dataProcessor, pathType, registerUI } from '@leafer/core'
1
+ import { ILeaferCanvas, IPathCommandData, IWindingRule } from '@leafer/interface'
2
+ import { PathHelper, dataProcessor, pathType, affectEventBoundsType, registerUI } from '@leafer/core'
3
3
 
4
- import { IPath, IPathData, IPathInputData, IPathString } from '@leafer-ui/interface'
4
+ import { IPath, IPathData, IPathInputData, IPathString, IStrokeAlign } from '@leafer-ui/interface'
5
5
  import { PathData } from '@leafer-ui/data'
6
6
 
7
7
  import { UI } from './UI'
8
8
 
9
9
 
10
- const { toTwoPointBounds } = PathHelper
11
- const { toBounds } = TwoPointBoundsHelper
12
-
13
- const pointBounds = {} as ITwoPointBoundsData
14
-
10
+ const { toBounds } = PathHelper
15
11
 
16
12
  @registerUI()
17
13
  export class Path extends UI implements IPath {
18
14
 
15
+ public get __tag() { return 'Path' }
16
+
19
17
  @dataProcessor(PathData)
20
18
  public __: IPathData
21
19
 
@@ -25,6 +23,9 @@ export class Path extends UI implements IPath {
25
23
  @pathType()
26
24
  public windingRule: IWindingRule
27
25
 
26
+ @affectEventBoundsType('center')
27
+ public strokeAlign: IStrokeAlign
28
+
28
29
  constructor(data?: IPathInputData) {
29
30
  super(data)
30
31
  }
@@ -35,8 +36,7 @@ export class Path extends UI implements IPath {
35
36
  }
36
37
 
37
38
  public __updateBoxBounds(): void {
38
- toTwoPointBounds(this.__.path, pointBounds)
39
- toBounds(pointBounds, this.__layout.boxBounds)
39
+ toBounds(this.__.path, this.__layout.boxBounds)
40
40
  }
41
41
 
42
42
  }
package/src/Polygon.ts CHANGED
@@ -14,6 +14,8 @@ const { begin, moveTo, lineTo, close } = PathCreator
14
14
  @registerUI()
15
15
  export class Polygon extends UI implements IPolygon {
16
16
 
17
+ public get __tag() { return 'Polygon' }
18
+
17
19
  @dataProcessor(PolygonData)
18
20
  public __: IPolygonData
19
21
 
package/src/Rect.ts CHANGED
@@ -12,6 +12,8 @@ import { UI } from './UI'
12
12
  @registerUI()
13
13
  export class Rect extends UI implements IRect {
14
14
 
15
+ public get __tag() { return 'Rect' }
16
+
15
17
  @dataProcessor(RectData)
16
18
  public __: IRectData
17
19
 
package/src/Star.ts CHANGED
@@ -14,13 +14,15 @@ const { begin, moveTo, lineTo, close } = PathCreator
14
14
  @registerUI()
15
15
  export class Star extends UI implements IStar {
16
16
 
17
+ public get __tag() { return 'Star' }
18
+
17
19
  @dataProcessor(StarData)
18
20
  public __: IStarData
19
21
 
20
22
  @pathType(5)
21
23
  public points: __Number
22
24
 
23
- @pathType(0.38)
25
+ @pathType(0.382)
24
26
  public innerRadius: __Number
25
27
 
26
28
  constructor(data?: IStarInputData) {
package/src/Text.ts CHANGED
@@ -1,20 +1,29 @@
1
1
  import { IPathDrawer, IPathCommandData, __Boolean, __Number, __String } from '@leafer/interface'
2
- import { Platform, boundsType, dataProcessor, registerUI, useModule } from '@leafer/core'
2
+ import { boundsType, dataProcessor, registerUI, surfaceType, useModule } from '@leafer/core'
3
3
 
4
- import { IText, IFontWeight, ITextCase, ITextDecoration, IPercent, ITextData, ITextInputData } from '@leafer-ui/interface'
4
+ import { IText, IFontWeight, ITextCase, ITextDecoration, IPercent, ITextData, ITextInputData, ITextAlign, IVerticalAlign, ITextDrawData } from '@leafer-ui/interface'
5
5
  import { TextData } from '@leafer-ui/data'
6
6
  import { TextRender } from '@leafer-ui/display-module'
7
+ import { TextConvert } from '@leafer-ui/text'
7
8
 
8
9
  import { UI } from './UI'
9
10
 
10
-
11
11
  @useModule(TextRender)
12
12
  @registerUI()
13
13
  export class Text extends UI implements IText {
14
14
 
15
+ public get __tag() { return 'Text' }
16
+
15
17
  @dataProcessor(TextData)
16
18
  public __: ITextData
17
19
 
20
+ // size
21
+ @boundsType(undefined)
22
+ public width: __Number
23
+
24
+ @boundsType(undefined)
25
+ public height: __Number
26
+
18
27
  @boundsType('')
19
28
  public content: __String
20
29
 
@@ -33,13 +42,13 @@ export class Text extends UI implements IText {
33
42
  @boundsType('normal')
34
43
  public textCase: ITextCase
35
44
 
36
- @boundsType('normal')
45
+ @boundsType('none')
37
46
  public textDecoration: ITextDecoration
38
47
 
39
48
  @boundsType()
40
49
  public letterSpacing: __Number | IPercent
41
50
 
42
- @boundsType()
51
+ @boundsType(1)
43
52
  public lineHeight: __Number | IPercent
44
53
 
45
54
  @boundsType()
@@ -48,6 +57,21 @@ export class Text extends UI implements IText {
48
57
  @boundsType()
49
58
  public paragraphSpacing: __Number
50
59
 
60
+ @surfaceType('left')
61
+ public textAlign: ITextAlign
62
+
63
+ @surfaceType('top')
64
+ public verticalAlign: IVerticalAlign
65
+
66
+ public get realWidth(): number { return this.textDrawData.width }
67
+
68
+ public get realHeight(): number { return this.textDrawData.height }
69
+
70
+ public get textDrawData(): ITextDrawData {
71
+ this.__updateTextDrawData()
72
+ return this.__.__textDrawData
73
+ }
74
+
51
75
  constructor(data?: ITextInputData) {
52
76
  super(data)
53
77
  }
@@ -57,18 +81,21 @@ export class Text extends UI implements IText {
57
81
  drawer.rect(0, 0, width, height)
58
82
  }
59
83
 
84
+ public __updateTextDrawData(): void {
85
+ this.__.__textDrawData || (this.__.__textDrawData = TextConvert.getDrawData(this.__.content, this.__))
86
+ }
87
+
60
88
  public __updateBoxBounds(): void {
61
- const { fontFamily, fontSize, fontWeight, italic, textCase, lineHeight } = this.__
62
- const b = this.__layout.boxBounds
63
89
 
64
- this.__.__font = Platform.canvas.font = `${italic ? 'italic' : ''} ${textCase === 'small-caps' ? 'small-caps' : 'normal'} ${fontWeight ? fontWeight : 'normal'} ${fontSize}px/${lineHeight ? lineHeight : fontSize}px ${fontFamily}`
65
- const width = Platform.canvas.measureText(this.content).width
66
- const height = fontSize
90
+ this.__updateTextDrawData()
91
+
92
+ const { width, height, __textDrawData: data } = this.__
93
+ const b = this.__layout.boxBounds
67
94
 
68
- b.x = 0
69
- b.y = -fontSize * 0.75
70
- b.width = width
71
- b.height = height
95
+ b.x = width ? 0 : data.x || 0
96
+ b.y = height ? 0 : data.y || 0
97
+ b.width = width ? Math.max(width, data.width) : data.width
98
+ b.height = height ? Math.max(height, data.height) : data.height
72
99
  }
73
100
 
74
101
  }
package/src/UI.ts CHANGED
@@ -1,12 +1,14 @@
1
- import { ILeaferCanvas, IPathDrawer, IPathCommandData, IMatrixData, IBoundsData, IHitType, __Number, __Boolean, __String } from '@leafer/interface'
2
- import { Leaf, PathHelper, affectEventBoundsType, surfaceType, dataType, positionType, boundsType, pathType, scaleType, rotationType, opacityType, sortType, dataProcessor, useModule, rewrite, rewriteAble } from '@leafer/core'
1
+ import { ILeaferCanvas, IPathDrawer, IPathCommandData, IHitType, __Number, __Boolean, __String } from '@leafer/interface'
2
+ import { Leaf, PathHelper, affectEventBoundsType, surfaceType, dataType, positionType, boundsType, pathType, scaleType, rotationType, opacityType, sortType, maskType, dataProcessor, useModule, rewrite, rewriteAble, UICreator } from '@leafer/core'
3
3
 
4
- import { IUI, IShadowEffect, IBlurEffect, IPaint, IStrokeAlign, IStrokeJoin, IStrokeCap, IBlendMode, IPaintString, IDashPatternString, IShadowString, IGrayscaleEffect, IUIData, IGroup, IStrokeWidthString, ICornerRadiusString } from '@leafer-ui/interface'
4
+ import { IUI, IShadowEffect, IBlurEffect, IPaint, IStrokeAlign, IStrokeJoin, IStrokeCap, IBlendMode, IPaintString, IDashPatternString, IShadowString, IGrayscaleEffect, IUIData, IGroup, IStrokeWidthString, ICornerRadiusString, IUITagInputData, IUIInputData } from '@leafer-ui/interface'
5
5
  import { effectType } from '@leafer-ui/decorator'
6
6
 
7
7
  import { UIData } from '@leafer-ui/data'
8
8
  import { UIBounds, UIHit, UIRender } from '@leafer-ui/display-module'
9
9
 
10
+ import { Paint } from '@leafer-ui/external'
11
+
10
12
 
11
13
  @useModule(UIBounds)
12
14
  @useModule(UIHit)
@@ -18,7 +20,6 @@ export class UI extends Leaf implements IUI {
18
20
  @dataProcessor(UIData)
19
21
  public __: IUIData
20
22
 
21
- public root?: IGroup
22
23
  public parent?: IGroup
23
24
 
24
25
  // ---
@@ -35,15 +36,24 @@ export class UI extends Leaf implements IUI {
35
36
 
36
37
 
37
38
  // layer
39
+ @surfaceType() // "pass-through"
40
+ public blendMode: IBlendMode
41
+
38
42
  @opacityType(1)
39
43
  public opacity: __Number
40
44
 
41
45
  @opacityType(true)
42
46
  public visible: __Boolean
43
47
 
48
+ @maskType(false)
49
+ public isMask: __Boolean
50
+
44
51
  @sortType(0)
45
52
  public zIndex: __Number
46
53
 
54
+ @dataType()
55
+ public locked: __Boolean
56
+
47
57
 
48
58
  // position
49
59
  @positionType(0)
@@ -96,17 +106,6 @@ export class UI extends Leaf implements IUI {
96
106
  // ---
97
107
 
98
108
 
99
- // layer
100
-
101
- @surfaceType() // "pass-through"
102
- public blendMode: IBlendMode
103
-
104
- @boundsType()
105
- public mask: __Boolean
106
-
107
- @dataType()
108
- public locked: __Boolean
109
-
110
109
  // fill
111
110
 
112
111
  @surfaceType()
@@ -117,7 +116,7 @@ export class UI extends Leaf implements IUI {
117
116
  @affectEventBoundsType()
118
117
  public stroke: IPaint | IPaint[] | IPaintString
119
118
 
120
- @affectEventBoundsType('center')
119
+ @affectEventBoundsType('inside')
121
120
  public strokeAlign: IStrokeAlign
122
121
 
123
122
  @affectEventBoundsType(1)
@@ -165,18 +164,26 @@ export class UI extends Leaf implements IUI {
165
164
  public grayscale: __Number | IGrayscaleEffect
166
165
 
167
166
 
168
- // now transform
169
-
170
- public get worldTransform(): IMatrixData { return this.__layout.getTransform('world') }
171
-
172
- public get relativeTransform(): IMatrixData { return this.__layout.getTransform('relative') }
167
+ constructor(data?: IUIInputData) {
168
+ super(data)
169
+ }
173
170
 
174
- // now bounds
175
171
 
176
- public get worldBoxBounds(): IBoundsData { return this.__layout.getBounds('world', 'box') }
172
+ public set(data: IUITagInputData): void {
173
+ Object.assign(this, data)
174
+ }
177
175
 
178
- public get worldRenderBounds(): IBoundsData { return this.__layout.getBounds('world', 'render') }
176
+ public get(): IUITagInputData {
177
+ return this.__.__getInputData()
178
+ }
179
179
 
180
+ public __onUpdateSize(): void {
181
+ if (this.__.__input) {
182
+ const { fill, stroke } = this.__.__input
183
+ if (fill) Paint.computeFill(this)
184
+ if (stroke) Paint.computeStroke(this)
185
+ }
186
+ }
180
187
 
181
188
  public __updateRenderPath(): void {
182
189
  if (this.__.path) {
@@ -198,4 +205,8 @@ export class UI extends Leaf implements IUI {
198
205
  @rewrite(PathHelper.drawData)
199
206
  public __drawPathByData(_drawer: IPathDrawer, _data: IPathCommandData): void { }
200
207
 
208
+ static one(data: IUITagInputData, x?: number, y?: number, width?: number, height?: number): IUI {
209
+ return UICreator.get(data.tag || this.prototype.__tag, data, x, y, width, height) as IUI
210
+ }
211
+
201
212
  }
package/src/Vector.ts CHANGED
@@ -9,6 +9,8 @@ import { Group } from './Group'
9
9
  @registerUI()
10
10
  export class Vector extends Group implements IVector {
11
11
 
12
+ public get __tag() { return 'Vector' }
13
+
12
14
  @dataProcessor(VectorData)
13
15
  public __: IVectorData
14
16