vislite 1.4.0-alpha.0 → 1.4.0
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/CHANGELOG +307 -307
- package/lib/BarLayout/index.es.js +437 -437
- package/lib/BarLayout/index.es.min.js +2 -2
- package/lib/Buffer/index.es.js +35 -35
- package/lib/Buffer/index.es.min.js +1 -1
- package/lib/Canvas/index.es.js +774 -774
- package/lib/Canvas/index.es.min.js +1 -1
- package/lib/Cardinal/index.es.js +90 -90
- package/lib/Cardinal/index.es.min.js +1 -1
- package/lib/Eoap/index.es.js +33 -33
- package/lib/Eoap/index.es.min.js +1 -1
- package/lib/Hermite/index.es.js +35 -35
- package/lib/Hermite/index.es.min.js +1 -1
- package/lib/MapCoordinate/index.es.js +199 -199
- package/lib/MapCoordinate/index.es.min.js +1 -1
- package/lib/Matrix4/index.es.js +124 -124
- package/lib/Matrix4/index.es.min.js +1 -1
- package/lib/Mercator/index.es.js +19 -19
- package/lib/Mercator/index.es.min.js +1 -1
- package/lib/PieLayout/index.es.js +213 -213
- package/lib/PieLayout/index.es.min.js +2 -2
- package/lib/RawCanvas/index.es.js +704 -704
- package/lib/RawCanvas/index.es.min.js +1 -1
- package/lib/SVG/index.es.js +514 -514
- package/lib/SVG/index.es.min.js +1 -1
- package/lib/Shader/index.es.js +35 -35
- package/lib/Shader/index.es.min.js +1 -1
- package/lib/Texture/index.es.js +53 -53
- package/lib/Texture/index.es.min.js +1 -1
- package/lib/TreeLayout/index.es.js +397 -397
- package/lib/TreeLayout/index.es.min.js +2 -2
- package/lib/animation/index.es.js +110 -106
- package/lib/animation/index.es.min.js +3 -3
- package/lib/assemble/index.es.js +17 -17
- package/lib/assemble/index.es.min.js +1 -1
- package/lib/getLoopColors/index.es.js +35 -35
- package/lib/getLoopColors/index.es.min.js +1 -1
- package/lib/getWebGLContext/index.es.js +62 -62
- package/lib/getWebGLContext/index.es.min.js +1 -1
- package/lib/index.umd.js +2795 -2791
- package/lib/index.umd.min.js +5 -5
- package/lib/initOption/index.es.js +6 -6
- package/lib/initOption/index.es.min.js +1 -1
- package/lib/mergeOption/index.es.js +34 -34
- package/lib/mergeOption/index.es.min.js +1 -1
- package/lib/move/index.es.js +7 -7
- package/lib/move/index.es.min.js +1 -1
- package/lib/rotate/index.es.js +7 -7
- package/lib/rotate/index.es.min.js +1 -1
- package/lib/ruler/index.es.js +137 -137
- package/lib/ruler/index.es.min.js +1 -1
- package/lib/scale/index.es.js +6 -6
- package/lib/scale/index.es.min.js +1 -1
- package/lib/throttle/index.es.js +51 -51
- package/lib/throttle/index.es.min.js +2 -2
- package/package/BarLayout/index.ts +2 -2
- package/package/PieLayout/index.ts +2 -2
- package/package/animation/index.ts +6 -3
- package/package/index.ts +84 -84
- package/package/throttle/index.ts +2 -2
- package/package.json +75 -75
- package/src/SVG.ts +55 -55
- package/src/common/canvas/gradient.ts +31 -31
- package/src/common/svg/default.ts +29 -29
- package/src/common/svg/gradient.ts +53 -53
- package/src/common/svg/index.ts +332 -332
- package/src/common/tree/toPlainTree.ts +135 -135
- package/src/common/webgl/texture.ts +98 -98
- package/src/layout/BarLayout.ts +248 -248
- package/src/layout/PieLayout.ts +141 -141
- package/src/layout/TreeLayout.ts +197 -197
- package/types/Bar.d.ts +91 -91
- package/types/BarConfig.d.ts +4 -4
- package/types/BarLayout.d.ts +48 -48
- package/types/BarOption.d.ts +31 -31
- package/types/Pie.d.ts +73 -73
- package/types/PieConfig.d.ts +26 -26
- package/types/PieLayout.d.ts +40 -40
- package/types/PieOption.d.ts +21 -21
- package/types/SVG.d.ts +247 -247
- package/types/animation.d.ts +11 -5
- package/types/index.d.ts +195 -195
- package/types/throttle.d.ts +5 -5
package/src/layout/PieLayout.ts
CHANGED
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
import type PieLayoutType from '../../types/PieLayout'
|
|
2
|
-
import type { PieResultType } from '../../types/Pie'
|
|
3
|
-
import type PieOptionType from '../../types/PieOption'
|
|
4
|
-
import type { default as PieConfigType, nameType, valueType } from '../../types/PieConfig'
|
|
5
|
-
|
|
6
|
-
import { initOption } from '../common/option'
|
|
7
|
-
import rotate from '../rotate'
|
|
8
|
-
import { animation } from "oipage/web/animation/index"
|
|
9
|
-
|
|
10
|
-
class PieLayout implements PieLayoutType {
|
|
11
|
-
readonly name: string = 'PieLayout'
|
|
12
|
-
|
|
13
|
-
private __config: PieConfigType
|
|
14
|
-
|
|
15
|
-
constructor(config: PieConfigType = {}) {
|
|
16
|
-
this.__config = initOption(config, {
|
|
17
|
-
name: (pieData: any, initPie: Array<any>) => pieData.name,
|
|
18
|
-
value: (pieData: any, initPie: Array<any>) => pieData.value
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
private __option = {
|
|
23
|
-
cx: 200,
|
|
24
|
-
cy: 200,
|
|
25
|
-
radius: [50, 100],
|
|
26
|
-
duration: 200,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setOption(option: PieOptionType) {
|
|
30
|
-
initOption(option, this.__option)
|
|
31
|
-
return this
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private __rback: (pie: PieResultType) => void
|
|
35
|
-
private __oralPie: any
|
|
36
|
-
private __prePie: PieResultType | null
|
|
37
|
-
|
|
38
|
-
private __hoverIndex = -1 // 表示当前悬浮的序号
|
|
39
|
-
|
|
40
|
-
use(initPie: Array<any>, hoverIndex: number = -1) {
|
|
41
|
-
let pie: PieResultType = {
|
|
42
|
-
count: initPie.length,
|
|
43
|
-
cx: this.__option.cx,
|
|
44
|
-
cy: this.__option.cy,
|
|
45
|
-
radius: this.__option.radius,
|
|
46
|
-
hoverIndex,
|
|
47
|
-
node: []
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let totalValue = 0, names = [], values = []
|
|
51
|
-
for (let i = 0; i < initPie.length; i++) {
|
|
52
|
-
names[i] = (this.__config.name as nameType)(initPie[i], initPie)
|
|
53
|
-
values[i] = (this.__config.value as valueType)(initPie[i], initPie)
|
|
54
|
-
|
|
55
|
-
totalValue += values[i]
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
let beginDeg = Math.PI * -0.5, currenDeg
|
|
59
|
-
for (let i = 0; i < initPie.length; i++) {
|
|
60
|
-
currenDeg = values[i] / totalValue * Math.PI * 2
|
|
61
|
-
let radius = [this.__option.radius[0], this.__option.radius[1] * (1 + (hoverIndex === i ? 0.05 : 0))]
|
|
62
|
-
|
|
63
|
-
let pdeg = beginDeg + currenDeg * 0.5, pradius = Math.max(this.__option.radius[0], this.__option.radius[1])
|
|
64
|
-
let p0 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius, pie.cy)
|
|
65
|
-
let p1 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius + 15, pie.cy)
|
|
66
|
-
|
|
67
|
-
let pflag = p0[0] > pie.cx ? 1 : -1
|
|
68
|
-
let p2 = [p1[0] + pflag * 20, p1[1]]
|
|
69
|
-
let p3 = [p1[0] + pflag * 25, p1[1]]
|
|
70
|
-
|
|
71
|
-
pie.node[i] = {
|
|
72
|
-
value: values[i],
|
|
73
|
-
name: names[i],
|
|
74
|
-
beginDeg,
|
|
75
|
-
deg: currenDeg,
|
|
76
|
-
isHover: hoverIndex === i,
|
|
77
|
-
radius,
|
|
78
|
-
label: {
|
|
79
|
-
line: [p0, p1, p2],
|
|
80
|
-
position: p3,
|
|
81
|
-
align: pflag === -1 ? "right" : "left"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
beginDeg += currenDeg
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return pie
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
bind(initPie: Array<any>, renderBack: (pie: PieResultType) => void) {
|
|
92
|
-
this.__rback = renderBack
|
|
93
|
-
this.__oralPie = initPie
|
|
94
|
-
|
|
95
|
-
this.__prePie = this.use(this.__oralPie, this.__hoverIndex)
|
|
96
|
-
this.__rback(this.__prePie)
|
|
97
|
-
|
|
98
|
-
return this
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
unbind() {
|
|
102
|
-
this.__rback = () => null
|
|
103
|
-
this.__oralPie = null
|
|
104
|
-
this.__prePie = null
|
|
105
|
-
this.__hoverIndex = -1
|
|
106
|
-
return this
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
setHover(index: number) {
|
|
110
|
-
if (!this.__prePie || this.__hoverIndex === index) return this
|
|
111
|
-
|
|
112
|
-
this.__hoverIndex = index
|
|
113
|
-
|
|
114
|
-
this.doUpdate()
|
|
115
|
-
return this
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
doUpdate() {
|
|
119
|
-
const newPie = this.use(this.__oralPie, this.__hoverIndex)
|
|
120
|
-
|
|
121
|
-
const cachePie = JSON.parse(JSON.stringify(newPie))
|
|
122
|
-
|
|
123
|
-
animation((deep) => {
|
|
124
|
-
|
|
125
|
-
if (this.__prePie) {
|
|
126
|
-
for (let i = 0; i < cachePie.count; i++) {
|
|
127
|
-
cachePie.node[i].radius[1] = this.__prePie.node[i].radius[1] + (newPie.node[i].radius[1] - this.__prePie.node[i].radius[1]) * deep
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
this.__rback(cachePie)
|
|
132
|
-
|
|
133
|
-
}, this.__option.duration, () => {
|
|
134
|
-
this.__prePie = newPie
|
|
135
|
-
this.__rback(this.__prePie)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
return this
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
1
|
+
import type PieLayoutType from '../../types/PieLayout'
|
|
2
|
+
import type { PieResultType } from '../../types/Pie'
|
|
3
|
+
import type PieOptionType from '../../types/PieOption'
|
|
4
|
+
import type { default as PieConfigType, nameType, valueType } from '../../types/PieConfig'
|
|
5
|
+
|
|
6
|
+
import { initOption } from '../common/option'
|
|
7
|
+
import rotate from '../rotate'
|
|
8
|
+
import { animation } from "oipage/web/animation/index"
|
|
9
|
+
|
|
10
|
+
class PieLayout implements PieLayoutType {
|
|
11
|
+
readonly name: string = 'PieLayout'
|
|
12
|
+
|
|
13
|
+
private __config: PieConfigType
|
|
14
|
+
|
|
15
|
+
constructor(config: PieConfigType = {}) {
|
|
16
|
+
this.__config = initOption(config, {
|
|
17
|
+
name: (pieData: any, initPie: Array<any>) => pieData.name,
|
|
18
|
+
value: (pieData: any, initPie: Array<any>) => pieData.value
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private __option = {
|
|
23
|
+
cx: 200,
|
|
24
|
+
cy: 200,
|
|
25
|
+
radius: [50, 100],
|
|
26
|
+
duration: 200,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setOption(option: PieOptionType) {
|
|
30
|
+
initOption(option, this.__option)
|
|
31
|
+
return this
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private __rback: (pie: PieResultType) => void
|
|
35
|
+
private __oralPie: any
|
|
36
|
+
private __prePie: PieResultType | null
|
|
37
|
+
|
|
38
|
+
private __hoverIndex = -1 // 表示当前悬浮的序号
|
|
39
|
+
|
|
40
|
+
use(initPie: Array<any>, hoverIndex: number = -1) {
|
|
41
|
+
let pie: PieResultType = {
|
|
42
|
+
count: initPie.length,
|
|
43
|
+
cx: this.__option.cx,
|
|
44
|
+
cy: this.__option.cy,
|
|
45
|
+
radius: this.__option.radius,
|
|
46
|
+
hoverIndex,
|
|
47
|
+
node: []
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let totalValue = 0, names = [], values = []
|
|
51
|
+
for (let i = 0; i < initPie.length; i++) {
|
|
52
|
+
names[i] = (this.__config.name as nameType)(initPie[i], initPie)
|
|
53
|
+
values[i] = (this.__config.value as valueType)(initPie[i], initPie)
|
|
54
|
+
|
|
55
|
+
totalValue += values[i]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let beginDeg = Math.PI * -0.5, currenDeg
|
|
59
|
+
for (let i = 0; i < initPie.length; i++) {
|
|
60
|
+
currenDeg = values[i] / totalValue * Math.PI * 2
|
|
61
|
+
let radius = [this.__option.radius[0], this.__option.radius[1] * (1 + (hoverIndex === i ? 0.05 : 0))]
|
|
62
|
+
|
|
63
|
+
let pdeg = beginDeg + currenDeg * 0.5, pradius = Math.max(this.__option.radius[0], this.__option.radius[1])
|
|
64
|
+
let p0 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius, pie.cy)
|
|
65
|
+
let p1 = rotate(pie.cx, pie.cy, pdeg, pie.cx + pradius + 15, pie.cy)
|
|
66
|
+
|
|
67
|
+
let pflag = p0[0] > pie.cx ? 1 : -1
|
|
68
|
+
let p2 = [p1[0] + pflag * 20, p1[1]]
|
|
69
|
+
let p3 = [p1[0] + pflag * 25, p1[1]]
|
|
70
|
+
|
|
71
|
+
pie.node[i] = {
|
|
72
|
+
value: values[i],
|
|
73
|
+
name: names[i],
|
|
74
|
+
beginDeg,
|
|
75
|
+
deg: currenDeg,
|
|
76
|
+
isHover: hoverIndex === i,
|
|
77
|
+
radius,
|
|
78
|
+
label: {
|
|
79
|
+
line: [p0, p1, p2],
|
|
80
|
+
position: p3,
|
|
81
|
+
align: pflag === -1 ? "right" : "left"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
beginDeg += currenDeg
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return pie
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
bind(initPie: Array<any>, renderBack: (pie: PieResultType) => void) {
|
|
92
|
+
this.__rback = renderBack
|
|
93
|
+
this.__oralPie = initPie
|
|
94
|
+
|
|
95
|
+
this.__prePie = this.use(this.__oralPie, this.__hoverIndex)
|
|
96
|
+
this.__rback(this.__prePie)
|
|
97
|
+
|
|
98
|
+
return this
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
unbind() {
|
|
102
|
+
this.__rback = () => null
|
|
103
|
+
this.__oralPie = null
|
|
104
|
+
this.__prePie = null
|
|
105
|
+
this.__hoverIndex = -1
|
|
106
|
+
return this
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
setHover(index: number) {
|
|
110
|
+
if (!this.__prePie || this.__hoverIndex === index) return this
|
|
111
|
+
|
|
112
|
+
this.__hoverIndex = index
|
|
113
|
+
|
|
114
|
+
this.doUpdate()
|
|
115
|
+
return this
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
doUpdate() {
|
|
119
|
+
const newPie = this.use(this.__oralPie, this.__hoverIndex)
|
|
120
|
+
|
|
121
|
+
const cachePie = JSON.parse(JSON.stringify(newPie))
|
|
122
|
+
|
|
123
|
+
animation((deep) => {
|
|
124
|
+
|
|
125
|
+
if (this.__prePie) {
|
|
126
|
+
for (let i = 0; i < cachePie.count; i++) {
|
|
127
|
+
cachePie.node[i].radius[1] = this.__prePie.node[i].radius[1] + (newPie.node[i].radius[1] - this.__prePie.node[i].radius[1]) * deep
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.__rback(cachePie)
|
|
132
|
+
|
|
133
|
+
}, this.__option.duration, () => {
|
|
134
|
+
this.__prePie = newPie
|
|
135
|
+
this.__rback(this.__prePie)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
142
|
export default PieLayout
|
package/src/layout/TreeLayout.ts
CHANGED
|
@@ -1,198 +1,198 @@
|
|
|
1
|
-
import type TreeLayoutType from '../../types/TreeLayout'
|
|
2
|
-
import type { TreeResultType } from '../../types/Tree'
|
|
3
|
-
import type TreeOptionType from '../../types/TreeOption'
|
|
4
|
-
|
|
5
|
-
import Tree from '../common/tree/index'
|
|
6
|
-
import { initOption } from '../common/option'
|
|
7
|
-
import { animation } from "oipage/web/animation/index"
|
|
8
|
-
import rotate from '../rotate'
|
|
9
|
-
|
|
10
|
-
class TreeLayout extends Tree implements TreeLayoutType {
|
|
11
|
-
readonly name: string = 'TreeLayout'
|
|
12
|
-
|
|
13
|
-
private __option = {
|
|
14
|
-
offsetX: 0,
|
|
15
|
-
offsetY: 0,
|
|
16
|
-
duration: 500,
|
|
17
|
-
type: "plain",
|
|
18
|
-
direction: "LR",
|
|
19
|
-
x: 100,
|
|
20
|
-
y: 100,
|
|
21
|
-
width: 100,
|
|
22
|
-
height: 100,
|
|
23
|
-
radius: 100
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private __rback: (tree: TreeResultType) => void
|
|
27
|
-
private __oralTree: any
|
|
28
|
-
private __preTree: TreeResultType | null
|
|
29
|
-
|
|
30
|
-
private __noOpens = {}
|
|
31
|
-
|
|
32
|
-
setOption(option: TreeOptionType) {
|
|
33
|
-
initOption(option, this.__option)
|
|
34
|
-
return this
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
use(initTree: any, noOpens = {}) {
|
|
38
|
-
const tree = super.use(initTree, noOpens)
|
|
39
|
-
|
|
40
|
-
// 校对偏差
|
|
41
|
-
if (this.__option.offsetX != 0 || this.__option.offsetY != 0) {
|
|
42
|
-
for (const key in tree.node) {
|
|
43
|
-
if (!tree.node[key].show) {
|
|
44
|
-
|
|
45
|
-
let deep = 0, pid = key
|
|
46
|
-
do {
|
|
47
|
-
pid = tree.node[pid].pid
|
|
48
|
-
deep++
|
|
49
|
-
} while (!tree.node[pid].show)
|
|
50
|
-
|
|
51
|
-
tree.node[key].left += this.__option.offsetX * deep
|
|
52
|
-
tree.node[key].top += this.__option.offsetY * deep
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (this.__option.type == 'rect') {
|
|
58
|
-
if (this.__option.direction == 'LR' || this.__option.direction == "RL") {
|
|
59
|
-
|
|
60
|
-
const perW = this.__option.height / tree.size
|
|
61
|
-
const perD = this.__option.width / (tree.deep - 1)
|
|
62
|
-
|
|
63
|
-
const balanceW = this.__option.y - this.__option.height * 0.5
|
|
64
|
-
const flag = this.__option.direction == 'LR' ? 1 : -1
|
|
65
|
-
|
|
66
|
-
for (const key in tree.node) {
|
|
67
|
-
if (tree.deep == 1) {
|
|
68
|
-
tree.node[key].left = this.__option.x + this.__option.width * 0.5 * flag
|
|
69
|
-
tree.node[key].top = this.__option.y
|
|
70
|
-
} else {
|
|
71
|
-
tree.node[key].left = this.__option.x + (tree.node[key].left - 0.5) * perD * flag
|
|
72
|
-
tree.node[key].top = tree.node[key].top * perW + balanceW
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
} else if (this.__option.direction == 'TB' || this.__option.direction == "BT") {
|
|
76
|
-
|
|
77
|
-
const perW = this.__option.width / tree.size
|
|
78
|
-
const perD = this.__option.height / (tree.deep - 1)
|
|
79
|
-
|
|
80
|
-
const balanceW = this.__option.x - this.__option.width * 0.5
|
|
81
|
-
const flag = this.__option.direction == 'TB' ? 1 : -1
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for (const key in tree.node) {
|
|
86
|
-
tree.node[key].deg = this.__option.direction == 'TB' ? Math.PI * 0.5 : Math.PI * -0.5
|
|
87
|
-
|
|
88
|
-
if (tree.deep == 1) {
|
|
89
|
-
tree.node[key].left = this.__option.x
|
|
90
|
-
tree.node[key].top = this.__option.y + this.__option.height * 0.5 * flag
|
|
91
|
-
} else {
|
|
92
|
-
const left = tree.node[key].left
|
|
93
|
-
tree.node[key].left = tree.node[key].top * perW + balanceW
|
|
94
|
-
tree.node[key].top = this.__option.y + (left - 0.5) * perD * flag
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
} else if (this.__option.type == 'circle') {
|
|
101
|
-
const cx = this.__option.x, cy = this.__option.y
|
|
102
|
-
const deg = Math.PI * 2 / tree.size
|
|
103
|
-
const per = this.__option.radius / (tree.deep - 1)
|
|
104
|
-
|
|
105
|
-
for (const key in tree.node) {
|
|
106
|
-
if (tree.node[key].left == 0.5) {
|
|
107
|
-
tree.node[key].left = cx
|
|
108
|
-
tree.node[key].top = cy
|
|
109
|
-
} else {
|
|
110
|
-
const position = rotate(cx, cy, deg * tree.node[key].top, cx + (tree.node[key].left - 0.5) * per, cy)
|
|
111
|
-
|
|
112
|
-
tree.node[key].deg = deg * tree.node[key].top
|
|
113
|
-
tree.node[key].left = position[0]
|
|
114
|
-
tree.node[key].top = position[1]
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return tree
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
bind(initTree: any, renderBack: (tree: TreeResultType) => void, noOpens = {}) {
|
|
123
|
-
this.__rback = renderBack
|
|
124
|
-
this.__oralTree = initTree
|
|
125
|
-
this.__noOpens = noOpens
|
|
126
|
-
|
|
127
|
-
this.__preTree = this.use(this.__oralTree, this.__noOpens)
|
|
128
|
-
this.__rback(this.__preTree)
|
|
129
|
-
|
|
130
|
-
return this
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
unbind() {
|
|
134
|
-
this.__rback = () => null
|
|
135
|
-
this.__oralTree = null
|
|
136
|
-
this.__preTree = null
|
|
137
|
-
this.__noOpens = {}
|
|
138
|
-
return this
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
doUpdate() {
|
|
142
|
-
const newTree = this.use(this.__oralTree, this.__noOpens)
|
|
143
|
-
|
|
144
|
-
const cacheTree = JSON.parse(JSON.stringify(newTree))
|
|
145
|
-
|
|
146
|
-
animation((deep) => {
|
|
147
|
-
|
|
148
|
-
if (this.__preTree) {
|
|
149
|
-
for (const key in cacheTree.node) {
|
|
150
|
-
if (newTree.node[key].show || this.__preTree.node[key].show) {
|
|
151
|
-
cacheTree.node[key].show = true
|
|
152
|
-
|
|
153
|
-
cacheTree.node[key].left = this.__preTree.node[key].left + (newTree.node[key].left - this.__preTree.node[key].left) * deep
|
|
154
|
-
cacheTree.node[key].top = this.__preTree.node[key].top + (newTree.node[key].top - this.__preTree.node[key].top) * deep
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
this.__rback(cacheTree)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}, this.__option.duration, () => {
|
|
162
|
-
this.__preTree = newTree
|
|
163
|
-
this.__rback(this.__preTree)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
return this
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
closeNode(id: string) {
|
|
170
|
-
if (!this.__preTree) return this
|
|
171
|
-
// @ts-ignore
|
|
172
|
-
this.__noOpens[id] = true
|
|
173
|
-
|
|
174
|
-
this.doUpdate()
|
|
175
|
-
return this
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
openNode(id: string) {
|
|
179
|
-
if (!this.__preTree) return this
|
|
180
|
-
// @ts-ignore
|
|
181
|
-
this.__noOpens[id] = false
|
|
182
|
-
|
|
183
|
-
this.doUpdate()
|
|
184
|
-
return this
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
toggleNode(id: string) {
|
|
188
|
-
if (!this.__preTree) return this
|
|
189
|
-
// @ts-ignore
|
|
190
|
-
this.__noOpens[id] = !this.__noOpens[id]
|
|
191
|
-
|
|
192
|
-
this.doUpdate()
|
|
193
|
-
return this
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
1
|
+
import type TreeLayoutType from '../../types/TreeLayout'
|
|
2
|
+
import type { TreeResultType } from '../../types/Tree'
|
|
3
|
+
import type TreeOptionType from '../../types/TreeOption'
|
|
4
|
+
|
|
5
|
+
import Tree from '../common/tree/index'
|
|
6
|
+
import { initOption } from '../common/option'
|
|
7
|
+
import { animation } from "oipage/web/animation/index"
|
|
8
|
+
import rotate from '../rotate'
|
|
9
|
+
|
|
10
|
+
class TreeLayout extends Tree implements TreeLayoutType {
|
|
11
|
+
readonly name: string = 'TreeLayout'
|
|
12
|
+
|
|
13
|
+
private __option = {
|
|
14
|
+
offsetX: 0,
|
|
15
|
+
offsetY: 0,
|
|
16
|
+
duration: 500,
|
|
17
|
+
type: "plain",
|
|
18
|
+
direction: "LR",
|
|
19
|
+
x: 100,
|
|
20
|
+
y: 100,
|
|
21
|
+
width: 100,
|
|
22
|
+
height: 100,
|
|
23
|
+
radius: 100
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private __rback: (tree: TreeResultType) => void
|
|
27
|
+
private __oralTree: any
|
|
28
|
+
private __preTree: TreeResultType | null
|
|
29
|
+
|
|
30
|
+
private __noOpens = {}
|
|
31
|
+
|
|
32
|
+
setOption(option: TreeOptionType) {
|
|
33
|
+
initOption(option, this.__option)
|
|
34
|
+
return this
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
use(initTree: any, noOpens = {}) {
|
|
38
|
+
const tree = super.use(initTree, noOpens)
|
|
39
|
+
|
|
40
|
+
// 校对偏差
|
|
41
|
+
if (this.__option.offsetX != 0 || this.__option.offsetY != 0) {
|
|
42
|
+
for (const key in tree.node) {
|
|
43
|
+
if (!tree.node[key].show) {
|
|
44
|
+
|
|
45
|
+
let deep = 0, pid = key
|
|
46
|
+
do {
|
|
47
|
+
pid = tree.node[pid].pid
|
|
48
|
+
deep++
|
|
49
|
+
} while (!tree.node[pid].show)
|
|
50
|
+
|
|
51
|
+
tree.node[key].left += this.__option.offsetX * deep
|
|
52
|
+
tree.node[key].top += this.__option.offsetY * deep
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (this.__option.type == 'rect') {
|
|
58
|
+
if (this.__option.direction == 'LR' || this.__option.direction == "RL") {
|
|
59
|
+
|
|
60
|
+
const perW = this.__option.height / tree.size
|
|
61
|
+
const perD = this.__option.width / (tree.deep - 1)
|
|
62
|
+
|
|
63
|
+
const balanceW = this.__option.y - this.__option.height * 0.5
|
|
64
|
+
const flag = this.__option.direction == 'LR' ? 1 : -1
|
|
65
|
+
|
|
66
|
+
for (const key in tree.node) {
|
|
67
|
+
if (tree.deep == 1) {
|
|
68
|
+
tree.node[key].left = this.__option.x + this.__option.width * 0.5 * flag
|
|
69
|
+
tree.node[key].top = this.__option.y
|
|
70
|
+
} else {
|
|
71
|
+
tree.node[key].left = this.__option.x + (tree.node[key].left - 0.5) * perD * flag
|
|
72
|
+
tree.node[key].top = tree.node[key].top * perW + balanceW
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} else if (this.__option.direction == 'TB' || this.__option.direction == "BT") {
|
|
76
|
+
|
|
77
|
+
const perW = this.__option.width / tree.size
|
|
78
|
+
const perD = this.__option.height / (tree.deep - 1)
|
|
79
|
+
|
|
80
|
+
const balanceW = this.__option.x - this.__option.width * 0.5
|
|
81
|
+
const flag = this.__option.direction == 'TB' ? 1 : -1
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
for (const key in tree.node) {
|
|
86
|
+
tree.node[key].deg = this.__option.direction == 'TB' ? Math.PI * 0.5 : Math.PI * -0.5
|
|
87
|
+
|
|
88
|
+
if (tree.deep == 1) {
|
|
89
|
+
tree.node[key].left = this.__option.x
|
|
90
|
+
tree.node[key].top = this.__option.y + this.__option.height * 0.5 * flag
|
|
91
|
+
} else {
|
|
92
|
+
const left = tree.node[key].left
|
|
93
|
+
tree.node[key].left = tree.node[key].top * perW + balanceW
|
|
94
|
+
tree.node[key].top = this.__option.y + (left - 0.5) * perD * flag
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
} else if (this.__option.type == 'circle') {
|
|
101
|
+
const cx = this.__option.x, cy = this.__option.y
|
|
102
|
+
const deg = Math.PI * 2 / tree.size
|
|
103
|
+
const per = this.__option.radius / (tree.deep - 1)
|
|
104
|
+
|
|
105
|
+
for (const key in tree.node) {
|
|
106
|
+
if (tree.node[key].left == 0.5) {
|
|
107
|
+
tree.node[key].left = cx
|
|
108
|
+
tree.node[key].top = cy
|
|
109
|
+
} else {
|
|
110
|
+
const position = rotate(cx, cy, deg * tree.node[key].top, cx + (tree.node[key].left - 0.5) * per, cy)
|
|
111
|
+
|
|
112
|
+
tree.node[key].deg = deg * tree.node[key].top
|
|
113
|
+
tree.node[key].left = position[0]
|
|
114
|
+
tree.node[key].top = position[1]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return tree
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
bind(initTree: any, renderBack: (tree: TreeResultType) => void, noOpens = {}) {
|
|
123
|
+
this.__rback = renderBack
|
|
124
|
+
this.__oralTree = initTree
|
|
125
|
+
this.__noOpens = noOpens
|
|
126
|
+
|
|
127
|
+
this.__preTree = this.use(this.__oralTree, this.__noOpens)
|
|
128
|
+
this.__rback(this.__preTree)
|
|
129
|
+
|
|
130
|
+
return this
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
unbind() {
|
|
134
|
+
this.__rback = () => null
|
|
135
|
+
this.__oralTree = null
|
|
136
|
+
this.__preTree = null
|
|
137
|
+
this.__noOpens = {}
|
|
138
|
+
return this
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
doUpdate() {
|
|
142
|
+
const newTree = this.use(this.__oralTree, this.__noOpens)
|
|
143
|
+
|
|
144
|
+
const cacheTree = JSON.parse(JSON.stringify(newTree))
|
|
145
|
+
|
|
146
|
+
animation((deep) => {
|
|
147
|
+
|
|
148
|
+
if (this.__preTree) {
|
|
149
|
+
for (const key in cacheTree.node) {
|
|
150
|
+
if (newTree.node[key].show || this.__preTree.node[key].show) {
|
|
151
|
+
cacheTree.node[key].show = true
|
|
152
|
+
|
|
153
|
+
cacheTree.node[key].left = this.__preTree.node[key].left + (newTree.node[key].left - this.__preTree.node[key].left) * deep
|
|
154
|
+
cacheTree.node[key].top = this.__preTree.node[key].top + (newTree.node[key].top - this.__preTree.node[key].top) * deep
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
this.__rback(cacheTree)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
}, this.__option.duration, () => {
|
|
162
|
+
this.__preTree = newTree
|
|
163
|
+
this.__rback(this.__preTree)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
return this
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
closeNode(id: string) {
|
|
170
|
+
if (!this.__preTree) return this
|
|
171
|
+
// @ts-ignore
|
|
172
|
+
this.__noOpens[id] = true
|
|
173
|
+
|
|
174
|
+
this.doUpdate()
|
|
175
|
+
return this
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
openNode(id: string) {
|
|
179
|
+
if (!this.__preTree) return this
|
|
180
|
+
// @ts-ignore
|
|
181
|
+
this.__noOpens[id] = false
|
|
182
|
+
|
|
183
|
+
this.doUpdate()
|
|
184
|
+
return this
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
toggleNode(id: string) {
|
|
188
|
+
if (!this.__preTree) return this
|
|
189
|
+
// @ts-ignore
|
|
190
|
+
this.__noOpens[id] = !this.__noOpens[id]
|
|
191
|
+
|
|
192
|
+
this.doUpdate()
|
|
193
|
+
return this
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
198
|
export default TreeLayout
|