@leafer-ui/display 1.0.0-alpha.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/LICENSE +21 -0
- package/README.md +1 -0
- package/package.json +30 -0
- package/src/Ellipse.ts +65 -0
- package/src/Frame.ts +84 -0
- package/src/Group.ts +44 -0
- package/src/Image.ts +25 -0
- package/src/Line.ts +71 -0
- package/src/Path.ts +42 -0
- package/src/Polygon.ts +41 -0
- package/src/Rect.ts +32 -0
- package/src/Star.ts +45 -0
- package/src/Text.ts +78 -0
- package/src/UI.ts +197 -0
- package/src/Vector.ts +26 -0
- package/src/index.ts +13 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-present, Chao (Leafer) Wan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @leafer-ui/display
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@leafer-ui/display",
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "@leafer-ui/display",
|
|
5
|
+
"author": "Chao (Leafer) Wan",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "src/index.ts",
|
|
8
|
+
"files": ["src"],
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/leaferjs/ui.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/leaferjs/ui/tree/main/packages/display",
|
|
14
|
+
"bugs": "https://github.com/leaferjs/ui/issues",
|
|
15
|
+
"keywords": [
|
|
16
|
+
"leaferui",
|
|
17
|
+
"leafer-ui",
|
|
18
|
+
"leaferjs"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@leafer/core": "1.0.0-alpha.1",
|
|
22
|
+
"@leafer-ui/data": "1.0.0-alpha.1",
|
|
23
|
+
"@leafer-ui/module": "1.0.0-alpha.1",
|
|
24
|
+
"@leafer-ui/decorator": "1.0.0-alpha.1"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@leafer/interface": "1.0.0-alpha.1",
|
|
28
|
+
"@leafer-ui/interface": "1.0.0-alpha.1"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/src/Ellipse.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { PathCreator, OneRadian, dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IEllipse, IEllipseInputData, IEllipseData } from '@leafer-ui/interface'
|
|
4
|
+
import { EllipseData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { UI } from './UI'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const { PI } = Math
|
|
10
|
+
const { begin, moveTo, close, ellipse } = PathCreator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@registerUI()
|
|
14
|
+
export class Ellipse extends UI implements IEllipse {
|
|
15
|
+
|
|
16
|
+
@dataProcessor(EllipseData)
|
|
17
|
+
public __: IEllipseData
|
|
18
|
+
|
|
19
|
+
@pathType(0)
|
|
20
|
+
public innerRadius: number
|
|
21
|
+
|
|
22
|
+
@pathType(0)
|
|
23
|
+
public startAngle: number
|
|
24
|
+
|
|
25
|
+
@pathType(0)
|
|
26
|
+
public endAngle: number
|
|
27
|
+
|
|
28
|
+
constructor(data?: IEllipseInputData) {
|
|
29
|
+
super(data)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public __updatePath(): void {
|
|
33
|
+
|
|
34
|
+
const { width, height, innerRadius, startAngle, endAngle } = this.__
|
|
35
|
+
const rx = width / 2, ry = height / 2
|
|
36
|
+
|
|
37
|
+
begin(this.__.path = [])
|
|
38
|
+
|
|
39
|
+
if (innerRadius) {
|
|
40
|
+
|
|
41
|
+
if (startAngle || endAngle) {
|
|
42
|
+
ellipse(rx, ry, rx * (1 - innerRadius), ry * (1 - innerRadius), 0, startAngle * OneRadian, endAngle * OneRadian, false)
|
|
43
|
+
ellipse(rx, ry, rx, ry, 0, endAngle * OneRadian, startAngle * OneRadian, true)
|
|
44
|
+
close()
|
|
45
|
+
} else {
|
|
46
|
+
ellipse(rx, ry, rx * (1 - innerRadius), ry * (1 - innerRadius), 0, 0, 2 * PI, false)
|
|
47
|
+
moveTo(width, ry)
|
|
48
|
+
ellipse(rx, ry, rx, ry, 0, 0, 2 * PI, true)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
} else {
|
|
52
|
+
|
|
53
|
+
if (startAngle || endAngle) {
|
|
54
|
+
moveTo(rx, ry)
|
|
55
|
+
ellipse(rx, ry, rx, ry, 0, startAngle * OneRadian, endAngle * OneRadian, false)
|
|
56
|
+
close()
|
|
57
|
+
} else {
|
|
58
|
+
ellipse(rx, ry, rx, ry, 0, 0, 2 * PI, false)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
}
|
package/src/Frame.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { ILeaferCanvas, IRenderOptions, ICanvasDrawPath, IBoundsData, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { BoundsHelper, dataProcessor, boundsType, rewrite, useModule, rewriteAble, registerUI } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IFrame, IFrameData, IFrameInputData } from '@leafer-ui/interface'
|
|
5
|
+
import { FrameData } from '@leafer-ui/data'
|
|
6
|
+
import { FrameRender } from '@leafer-ui/display-module'
|
|
7
|
+
|
|
8
|
+
import { Group } from './Group'
|
|
9
|
+
import { Rect } from './Rect'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
const rect = Rect.prototype
|
|
13
|
+
const group = Group.prototype
|
|
14
|
+
const bounds = {} as IBoundsData
|
|
15
|
+
const { copy, add } = BoundsHelper
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@useModule(FrameRender)
|
|
19
|
+
@rewriteAble()
|
|
20
|
+
@registerUI()
|
|
21
|
+
export class Frame extends Group implements IFrame {
|
|
22
|
+
|
|
23
|
+
@dataProcessor(FrameData)
|
|
24
|
+
public __: IFrameData
|
|
25
|
+
|
|
26
|
+
@boundsType(true)
|
|
27
|
+
public clip: boolean
|
|
28
|
+
|
|
29
|
+
constructor(data?: IFrameInputData) {
|
|
30
|
+
super(data)
|
|
31
|
+
if (!this.fill) this.fill = '#FFFFFF'
|
|
32
|
+
this.__isBranchLeaf = true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@rewrite(rect.__drawPathByData)
|
|
36
|
+
public __drawPathByData(drawer: ICanvasDrawPath, data: IPathCommandData): void { }
|
|
37
|
+
|
|
38
|
+
public __updateBoxBounds(): void {
|
|
39
|
+
this.__updateRectBoxBounds()
|
|
40
|
+
if (!this.__.clip) {
|
|
41
|
+
const { boxBounds } = this.__layout
|
|
42
|
+
copy(bounds, boxBounds)
|
|
43
|
+
super.__updateBoxBounds()
|
|
44
|
+
add(boxBounds, bounds)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public __updateEventBounds(): void {
|
|
49
|
+
this.__updateRectEventBounds()
|
|
50
|
+
if (!this.__.clip) {
|
|
51
|
+
const { eventBounds } = this.__layout
|
|
52
|
+
copy(bounds, eventBounds)
|
|
53
|
+
super.__updateEventBounds()
|
|
54
|
+
add(eventBounds, bounds)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public __updateRenderBounds(): void {
|
|
59
|
+
this.__updateRectRenderBounds()
|
|
60
|
+
if (!this.__.clip) {
|
|
61
|
+
const { renderBounds } = this.__layout
|
|
62
|
+
copy(bounds, renderBounds)
|
|
63
|
+
super.__updateRenderBounds()
|
|
64
|
+
add(renderBounds, bounds)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@rewrite(rect.__updateBoxBounds)
|
|
69
|
+
public __updateRectBoxBounds(): void { }
|
|
70
|
+
|
|
71
|
+
@rewrite(rect.__updateEventBounds)
|
|
72
|
+
public __updateRectEventBounds(): void { }
|
|
73
|
+
|
|
74
|
+
@rewrite(rect.__updateRenderBounds)
|
|
75
|
+
public __updateRectRenderBounds(): void { }
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@rewrite(rect.__render)
|
|
79
|
+
public __renderRect(canvas: ILeaferCanvas, options: IRenderOptions): void { }
|
|
80
|
+
|
|
81
|
+
@rewrite(group.__render)
|
|
82
|
+
public __renderGroup(canvas: ILeaferCanvas, options: IRenderOptions): void { }
|
|
83
|
+
|
|
84
|
+
}
|
package/src/Group.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Branch, useModule, dataProcessor, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IGroup, IGroupData, IGroupInputData, IUI } from '@leafer-ui/interface'
|
|
4
|
+
import { GroupData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { UI } from './UI'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@useModule(Branch)
|
|
10
|
+
@registerUI()
|
|
11
|
+
export class Group extends UI implements IGroup {
|
|
12
|
+
|
|
13
|
+
@dataProcessor(GroupData)
|
|
14
|
+
public __: IGroupData
|
|
15
|
+
|
|
16
|
+
public children: IUI[]
|
|
17
|
+
|
|
18
|
+
constructor(data?: IGroupInputData) {
|
|
19
|
+
super(data)
|
|
20
|
+
this.__isBranch = true
|
|
21
|
+
this.children = []
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public __updatePath(): void {
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public add(child: IUI, index?: number): void { } // Branch rewrite
|
|
29
|
+
|
|
30
|
+
public addAt(child: IUI, index: number): void {
|
|
31
|
+
this.add(child, index)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public addAfter(child: IUI, after: IUI): void {
|
|
35
|
+
this.add(child, this.children.indexOf(after) + 1)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public addBefore(child: UI, before: IUI): void {
|
|
39
|
+
this.add(child, this.children.indexOf(before))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public remove(child?: IUI): void { } // Branch rewrite
|
|
43
|
+
|
|
44
|
+
}
|
package/src/Image.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { boundsType, dataProcessor, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IImage, IImageInputData, IImageData } from '@leafer-ui/interface'
|
|
4
|
+
import { ImageData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { Rect } from './Rect'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@registerUI()
|
|
10
|
+
export class Image extends Rect implements IImage {
|
|
11
|
+
|
|
12
|
+
@dataProcessor(ImageData)
|
|
13
|
+
public __: IImageData
|
|
14
|
+
|
|
15
|
+
@boundsType('')
|
|
16
|
+
public url: string
|
|
17
|
+
|
|
18
|
+
@boundsType('')
|
|
19
|
+
public thumb: string
|
|
20
|
+
|
|
21
|
+
constructor(data?: IImageInputData) {
|
|
22
|
+
super(data)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
package/src/Line.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { __Number, IPointData, ITwoPointBoundsData } from '@leafer/interface'
|
|
2
|
+
import { PathCreator, PointHelper, TwoPointBoundsHelper, boundsType, dataProcessor, registerUI } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { ILine, ILineData, ILineInputData } from '@leafer-ui/interface'
|
|
5
|
+
import { LineData } from '@leafer-ui/data'
|
|
6
|
+
|
|
7
|
+
import { UI } from './UI'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const { begin, moveTo, lineTo, end } = PathCreator
|
|
11
|
+
const { rotate, getAngle, getDistance, defaultPoint } = PointHelper
|
|
12
|
+
const { setPoint, addPoint, toBounds } = TwoPointBoundsHelper
|
|
13
|
+
|
|
14
|
+
const pointBounds = {} as ITwoPointBoundsData
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@registerUI()
|
|
18
|
+
export class Line extends UI implements ILine {
|
|
19
|
+
|
|
20
|
+
@dataProcessor(LineData)
|
|
21
|
+
public __: ILineData
|
|
22
|
+
|
|
23
|
+
@boundsType()
|
|
24
|
+
public rotation: __Number
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
protected __to: IPointData
|
|
28
|
+
|
|
29
|
+
public get toPoint(): IPointData {
|
|
30
|
+
if (this.__to && !this.__layout.boxBoundsChanged) return this.__to
|
|
31
|
+
|
|
32
|
+
const { width, height, rotation } = this.__
|
|
33
|
+
const to: IPointData = { x: 0, y: 0 }
|
|
34
|
+
|
|
35
|
+
if (width) to.x = width
|
|
36
|
+
if (height) to.y = height
|
|
37
|
+
|
|
38
|
+
if (rotation) rotate(to, rotation)
|
|
39
|
+
this.__to = to
|
|
40
|
+
|
|
41
|
+
return to
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public set toPoint(value: IPointData) {
|
|
45
|
+
this.width = getDistance(defaultPoint, value)
|
|
46
|
+
this.rotation = getAngle(defaultPoint, value)
|
|
47
|
+
if (this.height) this.height = 0
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
constructor(data?: ILineInputData) {
|
|
52
|
+
super(data)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public __updatePath(): void {
|
|
56
|
+
|
|
57
|
+
begin(this.__.path = [])
|
|
58
|
+
moveTo(0, 0)
|
|
59
|
+
|
|
60
|
+
const to = this.toPoint
|
|
61
|
+
lineTo(to.x, to.y)
|
|
62
|
+
end()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public __updateBoxBounds(): void {
|
|
66
|
+
setPoint(pointBounds, 0, 0)
|
|
67
|
+
addPoint(pointBounds, this.__to.x, this.__to.y)
|
|
68
|
+
toBounds(pointBounds, this.__layout.boxBounds)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
}
|
package/src/Path.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ITwoPointBoundsData, ILeaferCanvas, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { PathHelper, TwoPointBoundsHelper, dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IPath, IPathData, IPathInputData, IWindingRule, IPathString } from '@leafer-ui/interface'
|
|
5
|
+
import { PathData } from '@leafer-ui/data'
|
|
6
|
+
|
|
7
|
+
import { UI } from './UI'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const { toTwoPointBounds } = PathHelper
|
|
11
|
+
const { toBounds } = TwoPointBoundsHelper
|
|
12
|
+
|
|
13
|
+
const pointBounds = {} as ITwoPointBoundsData
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@registerUI()
|
|
17
|
+
export class Path extends UI implements IPath {
|
|
18
|
+
|
|
19
|
+
@dataProcessor(PathData)
|
|
20
|
+
public __: IPathData
|
|
21
|
+
|
|
22
|
+
@pathType()
|
|
23
|
+
public path: IPathCommandData | IPathString
|
|
24
|
+
|
|
25
|
+
@pathType()
|
|
26
|
+
public windingRule: IWindingRule
|
|
27
|
+
|
|
28
|
+
constructor(data?: IPathInputData) {
|
|
29
|
+
super(data)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public __drawRenderPath(canvas: ILeaferCanvas): void {
|
|
33
|
+
canvas.beginPath()
|
|
34
|
+
this.__drawPathByData(canvas, this.__.path)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public __updateBoxBounds(): void {
|
|
38
|
+
toTwoPointBounds(this.__.path, pointBounds)
|
|
39
|
+
toBounds(pointBounds, this.__layout.boxBounds)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
package/src/Polygon.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { PathCreator, dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IPolygon, IPolygonData, IPolygonInputData } from '@leafer-ui/interface'
|
|
4
|
+
import { PolygonData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { UI } from './UI'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const { sin, cos, PI } = Math
|
|
10
|
+
const { begin, moveTo, lineTo, close } = PathCreator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@registerUI()
|
|
14
|
+
export class Polygon extends UI implements IPolygon {
|
|
15
|
+
|
|
16
|
+
@dataProcessor(PolygonData)
|
|
17
|
+
public __: IPolygonData
|
|
18
|
+
|
|
19
|
+
@pathType(3)
|
|
20
|
+
sides: number
|
|
21
|
+
|
|
22
|
+
constructor(data?: IPolygonInputData) {
|
|
23
|
+
super(data)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public __updatePath(): void {
|
|
27
|
+
|
|
28
|
+
const { width, height, sides } = this.__
|
|
29
|
+
const rx = width / 2, ry = height / 2
|
|
30
|
+
|
|
31
|
+
begin(this.__.path = [])
|
|
32
|
+
moveTo(rx, 0)
|
|
33
|
+
|
|
34
|
+
for (let i = 1; i < sides; i++) {
|
|
35
|
+
lineTo(rx + rx * sin((i * 2 * PI) / sides), ry - ry * cos((i * 2 * PI) / sides))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
close()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
package/src/Rect.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ICanvasDrawPath, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { dataProcessor, registerUI, useModule } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IRect, IRectInputData, IRectData } from '@leafer-ui/interface'
|
|
5
|
+
import { RectData } from '@leafer-ui/data'
|
|
6
|
+
import { RectRender } from '@leafer-ui/display-module'
|
|
7
|
+
|
|
8
|
+
import { UI } from './UI'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@useModule(RectRender)
|
|
12
|
+
@registerUI()
|
|
13
|
+
export class Rect extends UI implements IRect {
|
|
14
|
+
|
|
15
|
+
@dataProcessor(RectData)
|
|
16
|
+
public __: IRectData
|
|
17
|
+
|
|
18
|
+
constructor(data?: IRectInputData) {
|
|
19
|
+
super(data)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public __updatePath(): void { }
|
|
23
|
+
|
|
24
|
+
public __drawPathByData(drawer: ICanvasDrawPath, data: IPathCommandData): void {
|
|
25
|
+
const { width, height, borderRadius } = this.__
|
|
26
|
+
if (borderRadius) {
|
|
27
|
+
drawer.roundRect(0, 0, width, height, borderRadius)
|
|
28
|
+
} else {
|
|
29
|
+
drawer.rect(0, 0, width, height)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/Star.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PathCreator, dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IStar, IStarData, IStarInputData } from '@leafer-ui/interface'
|
|
4
|
+
import { StarData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { UI } from './UI'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const { sin, cos, PI } = Math
|
|
10
|
+
const { begin, moveTo, lineTo, close } = PathCreator
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@registerUI()
|
|
14
|
+
export class Star extends UI implements IStar {
|
|
15
|
+
|
|
16
|
+
@dataProcessor(StarData)
|
|
17
|
+
public __: IStarData
|
|
18
|
+
|
|
19
|
+
@pathType(5)
|
|
20
|
+
public points: number
|
|
21
|
+
|
|
22
|
+
@pathType(0.38)
|
|
23
|
+
public innerRadius: number
|
|
24
|
+
|
|
25
|
+
constructor(data?: IStarInputData) {
|
|
26
|
+
super(data)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public __updatePath() {
|
|
30
|
+
|
|
31
|
+
const { width, height, points, innerRadius } = this.__
|
|
32
|
+
const rx = width / 2, ry = height / 2
|
|
33
|
+
|
|
34
|
+
begin(this.__.path = [])
|
|
35
|
+
moveTo(rx, 0)
|
|
36
|
+
|
|
37
|
+
for (let i = 1; i < points * 2; i++) {
|
|
38
|
+
lineTo(rx + (i % 2 === 0 ? rx : rx * innerRadius) * sin((i * PI) / points), ry - (i % 2 === 0 ? ry : ry * innerRadius) * cos((i * PI) / points))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
close()
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
package/src/Text.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ICanvasDrawPath, IPathCommandData } from '@leafer/interface'
|
|
2
|
+
import { Platform, boundsType, dataProcessor, registerUI, useModule } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IText, IFontWeight, ITextCase, ITextDecoration, IPercent, ITextData, ITextInputData } from '@leafer-ui/interface'
|
|
5
|
+
import { TextData } from '@leafer-ui/data'
|
|
6
|
+
import { TextRender } from '@leafer-ui/display-module'
|
|
7
|
+
|
|
8
|
+
import { UI } from './UI'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@useModule(TextRender)
|
|
12
|
+
@registerUI()
|
|
13
|
+
export class Text extends UI implements IText {
|
|
14
|
+
|
|
15
|
+
@dataProcessor(TextData)
|
|
16
|
+
public __: ITextData
|
|
17
|
+
|
|
18
|
+
@boundsType('')
|
|
19
|
+
public content: string
|
|
20
|
+
|
|
21
|
+
@boundsType('arial')
|
|
22
|
+
public fontFamily: string
|
|
23
|
+
|
|
24
|
+
@boundsType(12)
|
|
25
|
+
public fontSize: number
|
|
26
|
+
|
|
27
|
+
@boundsType('normal')
|
|
28
|
+
public fontWeight: IFontWeight
|
|
29
|
+
|
|
30
|
+
@boundsType(false)
|
|
31
|
+
public italic: boolean
|
|
32
|
+
|
|
33
|
+
@boundsType('normal')
|
|
34
|
+
public textCase: ITextCase
|
|
35
|
+
|
|
36
|
+
@boundsType('normal')
|
|
37
|
+
public textDecoration: ITextDecoration
|
|
38
|
+
|
|
39
|
+
@boundsType()
|
|
40
|
+
public letterSpacing: number | IPercent
|
|
41
|
+
|
|
42
|
+
@boundsType()
|
|
43
|
+
public lineHeight: number | IPercent
|
|
44
|
+
|
|
45
|
+
@boundsType()
|
|
46
|
+
public paragraphIndent: number
|
|
47
|
+
|
|
48
|
+
@boundsType()
|
|
49
|
+
public paragraphSpacing: number
|
|
50
|
+
|
|
51
|
+
constructor(data?: ITextInputData) {
|
|
52
|
+
super(data)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public __updatePath(): void {
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public __drawPathByData(drawer: ICanvasDrawPath, data: IPathCommandData): void {
|
|
60
|
+
const { width, height } = this.__
|
|
61
|
+
drawer.rect(0, 0, width, height)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public __updateBoxBounds(): void {
|
|
65
|
+
const { fontFamily, fontSize, fontWeight, italic, textCase, lineHeight } = this.__
|
|
66
|
+
const b = this.__layout.boxBounds
|
|
67
|
+
|
|
68
|
+
this.__.__font = Platform.canvas.font = `${italic ? 'italic' : ''} ${textCase === 'small-caps' ? 'small-caps' : 'normal'} ${fontWeight ? fontWeight : 'normal'} ${fontSize}px/${lineHeight ? lineHeight : fontSize}px ${fontFamily}`
|
|
69
|
+
const width = Platform.canvas.measureText(this.content).width
|
|
70
|
+
const height = fontSize
|
|
71
|
+
|
|
72
|
+
b.x = 0
|
|
73
|
+
b.y = -fontSize * 0.75
|
|
74
|
+
b.width = width
|
|
75
|
+
b.height = height
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
}
|
package/src/UI.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { ILeaferCanvas, ICanvasDrawPath, IPathCommandData, __Number, __Boolean, __String, IMatrixData, IBoundsData } from '@leafer/interface'
|
|
2
|
+
import { Leaf, PathHelper, affectEventBoundsType, surfaceType, dataType, positionType, boundsType, pathType, scaleType, rotationType, opacityType, sortType, dataProcessor, useModule, rewrite, rewriteAble } from '@leafer/core'
|
|
3
|
+
|
|
4
|
+
import { IUI, IShadowEffect, IBlurEffect, IPaint, IStrokeAlign, IStrokeJoin, IStrokeCap, IBlendMode, IPaintString, IDashPatternString, IShadowString, IGrayscaleEffect, IUIData, IGroup, IBorderWidthString, IBorderRadiusString } from '@leafer-ui/interface'
|
|
5
|
+
import { effectType } from '@leafer-ui/decorator'
|
|
6
|
+
|
|
7
|
+
import { UIData } from '@leafer-ui/data'
|
|
8
|
+
import { UIBounds, UIHit, UIRender } from '@leafer-ui/display-module'
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@useModule(UIBounds)
|
|
12
|
+
@useModule(UIHit)
|
|
13
|
+
@useModule(UIRender)
|
|
14
|
+
@rewriteAble()
|
|
15
|
+
export class UI extends Leaf implements IUI {
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataProcessor(UIData)
|
|
19
|
+
public __: IUIData
|
|
20
|
+
|
|
21
|
+
public root?: IGroup
|
|
22
|
+
public parent?: IGroup
|
|
23
|
+
|
|
24
|
+
// ---
|
|
25
|
+
|
|
26
|
+
// id
|
|
27
|
+
@dataType('')
|
|
28
|
+
public id: __String
|
|
29
|
+
|
|
30
|
+
@dataType('')
|
|
31
|
+
public name: __String
|
|
32
|
+
|
|
33
|
+
@dataType('')
|
|
34
|
+
public className: __String
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
// layer
|
|
38
|
+
@opacityType(1)
|
|
39
|
+
public opacity: __Number
|
|
40
|
+
|
|
41
|
+
@opacityType(true)
|
|
42
|
+
public visible: __Boolean
|
|
43
|
+
|
|
44
|
+
@sortType(0)
|
|
45
|
+
public zIndex: __Number
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// position
|
|
49
|
+
@positionType(0)
|
|
50
|
+
public x: __Number
|
|
51
|
+
|
|
52
|
+
@positionType(0)
|
|
53
|
+
public y: __Number
|
|
54
|
+
|
|
55
|
+
// size
|
|
56
|
+
@boundsType(100)
|
|
57
|
+
public width: __Number
|
|
58
|
+
|
|
59
|
+
@boundsType(100)
|
|
60
|
+
public height: __Number
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
// scale
|
|
64
|
+
@scaleType(1)
|
|
65
|
+
public scaleX: __Number
|
|
66
|
+
|
|
67
|
+
@scaleType(1)
|
|
68
|
+
public scaleY: __Number
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
// rotate
|
|
72
|
+
@rotationType(0)
|
|
73
|
+
public rotation: __Number
|
|
74
|
+
|
|
75
|
+
// skew
|
|
76
|
+
@rotationType(0)
|
|
77
|
+
public skewX: __Number
|
|
78
|
+
|
|
79
|
+
@rotationType(0)
|
|
80
|
+
public skewY: __Number
|
|
81
|
+
|
|
82
|
+
public draggable: __Boolean
|
|
83
|
+
|
|
84
|
+
// ---
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
// layer
|
|
88
|
+
|
|
89
|
+
@surfaceType() // "pass-through"
|
|
90
|
+
public blendMode: IBlendMode
|
|
91
|
+
|
|
92
|
+
@boundsType()
|
|
93
|
+
public mask: __Boolean
|
|
94
|
+
|
|
95
|
+
@dataType()
|
|
96
|
+
public locked: __Boolean
|
|
97
|
+
|
|
98
|
+
// fill
|
|
99
|
+
|
|
100
|
+
@surfaceType()
|
|
101
|
+
public fill: IPaint | IPaint[] | IPaintString
|
|
102
|
+
|
|
103
|
+
// border
|
|
104
|
+
|
|
105
|
+
@pathType()
|
|
106
|
+
public borderRadius: __Number | __Number[] | IBorderRadiusString
|
|
107
|
+
|
|
108
|
+
@affectEventBoundsType(1)
|
|
109
|
+
public borderWidth: __Number | __Number[] | IBorderWidthString
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
// stroke
|
|
113
|
+
|
|
114
|
+
@affectEventBoundsType()
|
|
115
|
+
public stroke: IPaint | IPaint[] | IPaintString
|
|
116
|
+
|
|
117
|
+
@affectEventBoundsType('center')
|
|
118
|
+
public strokeAlign: IStrokeAlign
|
|
119
|
+
|
|
120
|
+
@affectEventBoundsType(1)
|
|
121
|
+
public strokeWidth: __Number
|
|
122
|
+
|
|
123
|
+
@surfaceType('none')
|
|
124
|
+
public strokeCap: IStrokeCap
|
|
125
|
+
|
|
126
|
+
@surfaceType('miter')
|
|
127
|
+
public strokeJoin: IStrokeJoin
|
|
128
|
+
|
|
129
|
+
@surfaceType()
|
|
130
|
+
public dashPattern: __Number[] | IDashPatternString
|
|
131
|
+
|
|
132
|
+
@surfaceType()
|
|
133
|
+
public dashOffset: __Number
|
|
134
|
+
|
|
135
|
+
@surfaceType(10)
|
|
136
|
+
public miterLimit: __Number
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
// corner
|
|
140
|
+
|
|
141
|
+
@pathType()
|
|
142
|
+
public cornerRadius: __Number
|
|
143
|
+
|
|
144
|
+
@pathType()
|
|
145
|
+
public cornerSmoothing: __Number
|
|
146
|
+
|
|
147
|
+
// effect
|
|
148
|
+
|
|
149
|
+
@effectType()
|
|
150
|
+
public shadow: IShadowEffect | IShadowEffect[] | IShadowString
|
|
151
|
+
|
|
152
|
+
@effectType()
|
|
153
|
+
public innerShadow: IShadowEffect | IShadowEffect[] | IShadowString
|
|
154
|
+
|
|
155
|
+
@effectType()
|
|
156
|
+
public blur: __Number | IBlurEffect
|
|
157
|
+
|
|
158
|
+
@effectType()
|
|
159
|
+
public backgroundBlur: __Number | IBlurEffect
|
|
160
|
+
|
|
161
|
+
@effectType()
|
|
162
|
+
public grayscale: __Number | IGrayscaleEffect
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
// now transform
|
|
166
|
+
|
|
167
|
+
public get worldTransform(): IMatrixData { return this.__layout.getTransform('world') }
|
|
168
|
+
|
|
169
|
+
public get relativeTransform(): IMatrixData { return this.__layout.getTransform('relative') }
|
|
170
|
+
|
|
171
|
+
// now bounds
|
|
172
|
+
|
|
173
|
+
public get worldBoxBounds(): IBoundsData { return this.__layout.getBounds('world', 'box') }
|
|
174
|
+
|
|
175
|
+
public get worldRenderBounds(): IBoundsData { return this.__layout.getBounds('world', 'render') }
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
public __updateRenderPath(): void {
|
|
179
|
+
const { __: data } = this
|
|
180
|
+
const { cornerRadius, path } = data
|
|
181
|
+
data.__renderPath = cornerRadius && path ? PathHelper.applyCorner(path, cornerRadius, data.cornerSmoothing) : path
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public __drawRenderPath(canvas: ILeaferCanvas): void {
|
|
185
|
+
canvas.beginPath()
|
|
186
|
+
this.__drawPathByData(canvas, this.__.__renderPath)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
public __drawPath(canvas: ILeaferCanvas): void {
|
|
190
|
+
canvas.beginPath()
|
|
191
|
+
this.__drawPathByData(canvas, this.__.path)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@rewrite(PathHelper.drawData)
|
|
195
|
+
public __drawPathByData(drawer: ICanvasDrawPath, data: IPathCommandData): void { }
|
|
196
|
+
|
|
197
|
+
}
|
package/src/Vector.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { dataProcessor, pathType, registerUI } from '@leafer/core'
|
|
2
|
+
|
|
3
|
+
import { IVectorPath, IVectorPathString, IVector, IVectorData, IVectorInputData } from '@leafer-ui/interface'
|
|
4
|
+
import { VectorData } from '@leafer-ui/data'
|
|
5
|
+
|
|
6
|
+
import { Group } from './Group'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@registerUI()
|
|
10
|
+
export class Vector extends Group implements IVector {
|
|
11
|
+
|
|
12
|
+
@dataProcessor(VectorData)
|
|
13
|
+
public __: IVectorData
|
|
14
|
+
|
|
15
|
+
@pathType()
|
|
16
|
+
public paths: IVectorPath[] | IVectorPathString
|
|
17
|
+
|
|
18
|
+
constructor(data?: IVectorInputData) {
|
|
19
|
+
super(data)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public __updatePath(): void {
|
|
23
|
+
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { UI } from './UI'
|
|
2
|
+
export { Group } from './Group'
|
|
3
|
+
export { Frame } from './Frame'
|
|
4
|
+
export { Rect } from './Rect'
|
|
5
|
+
export { Ellipse } from './Ellipse'
|
|
6
|
+
export { Polygon } from './Polygon'
|
|
7
|
+
export { Star } from './Star'
|
|
8
|
+
export { Line } from './Line'
|
|
9
|
+
export { Path } from './Path'
|
|
10
|
+
export { Vector } from './Vector'
|
|
11
|
+
export { Text } from './Text'
|
|
12
|
+
export { Image } from './Image'
|
|
13
|
+
|