@leafer/selector 1.0.0-alpha.21 → 1.0.0-alpha.30
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 +5 -5
- package/src/FindPath.ts +141 -0
- package/src/Selector.ts +17 -16
- package/src/PathFinder.ts +0 -128
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafer/selector",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.30",
|
|
4
4
|
"description": "@leafer/selector",
|
|
5
5
|
"author": "Chao (Leafer) Wan",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"leaferjs"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@leafer/event": "1.0.0-alpha.
|
|
23
|
-
"@leafer/math": "1.0.0-alpha.
|
|
24
|
-
"@leafer/list": "1.0.0-alpha.
|
|
22
|
+
"@leafer/event": "1.0.0-alpha.30",
|
|
23
|
+
"@leafer/math": "1.0.0-alpha.30",
|
|
24
|
+
"@leafer/list": "1.0.0-alpha.30"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@leafer/interface": "1.0.0-alpha.
|
|
27
|
+
"@leafer/interface": "1.0.0-alpha.30"
|
|
28
28
|
}
|
|
29
29
|
}
|
package/src/FindPath.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ILeaf, ILeafList, IPointData, IRadiusPointData, ISelectPathResult, ISelectPathOptions, ISelector } from '@leafer/interface'
|
|
2
|
+
import { BoundsHelper } from '@leafer/math'
|
|
3
|
+
import { LeafList } from '@leafer/list'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const { hitRadiusPoint } = BoundsHelper
|
|
7
|
+
|
|
8
|
+
export class FindPath {
|
|
9
|
+
|
|
10
|
+
protected target: ILeaf
|
|
11
|
+
protected selector: ISelector
|
|
12
|
+
|
|
13
|
+
protected findList: ILeaf[]
|
|
14
|
+
protected exclude: ILeafList
|
|
15
|
+
|
|
16
|
+
protected point: IRadiusPointData
|
|
17
|
+
|
|
18
|
+
constructor(target: ILeaf, selector: ISelector) {
|
|
19
|
+
this.target = target
|
|
20
|
+
this.selector = selector
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
|
|
24
|
+
if (!hitRadius) hitRadius = 0
|
|
25
|
+
if (!options) options = {}
|
|
26
|
+
|
|
27
|
+
const through = options.through || false
|
|
28
|
+
const ignoreHittable = options.ignoreHittable || false
|
|
29
|
+
this.exclude = options.exclude || null
|
|
30
|
+
|
|
31
|
+
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius }
|
|
32
|
+
this.findList = []
|
|
33
|
+
|
|
34
|
+
// path
|
|
35
|
+
this.eachFind(this.target.children, this.target.__onlyHitMask)
|
|
36
|
+
|
|
37
|
+
const list = this.findList
|
|
38
|
+
const leaf = this.getBestMatchLeaf()
|
|
39
|
+
const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf)
|
|
40
|
+
|
|
41
|
+
this.clear()
|
|
42
|
+
|
|
43
|
+
return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public getBestMatchLeaf(): ILeaf {
|
|
47
|
+
const { findList: targets } = this
|
|
48
|
+
if (targets.length > 1) {
|
|
49
|
+
let find: ILeaf
|
|
50
|
+
this.findList = []
|
|
51
|
+
const { x, y } = this.point
|
|
52
|
+
const point = { x, y, radiusX: 0, radiusY: 0 }
|
|
53
|
+
for (let i = 0, len = targets.length; i < len; i++) {
|
|
54
|
+
find = targets[i]
|
|
55
|
+
this.hitChild(find, point)
|
|
56
|
+
if (this.findList.length) return this.findList[0]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return targets[0]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public getPath(leaf: ILeaf): LeafList {
|
|
63
|
+
const path = new LeafList()
|
|
64
|
+
while (leaf) {
|
|
65
|
+
path.push(leaf)
|
|
66
|
+
leaf = leaf.parent
|
|
67
|
+
}
|
|
68
|
+
path.push(this.target)
|
|
69
|
+
return path
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public getHitablePath(leaf: ILeaf): LeafList {
|
|
73
|
+
const path = this.getPath(leaf)
|
|
74
|
+
let item: ILeaf, hittablePath = new LeafList()
|
|
75
|
+
for (let i = path.list.length - 1; i > -1; i--) {
|
|
76
|
+
item = path.list[i]
|
|
77
|
+
if (!item.__.hittable) break
|
|
78
|
+
hittablePath.unshift(item)
|
|
79
|
+
if (!item.__.hitChildren) break
|
|
80
|
+
}
|
|
81
|
+
return hittablePath
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public getThroughPath(list: ILeaf[]): LeafList {
|
|
85
|
+
const throughPath = new LeafList()
|
|
86
|
+
const pathList: ILeafList[] = []
|
|
87
|
+
|
|
88
|
+
for (let i = list.length - 1; i > -1; i--) {
|
|
89
|
+
pathList.push(this.getPath(list[i]))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let path: ILeafList, nextPath: ILeafList, leaf: ILeaf
|
|
93
|
+
for (let i = 0, len = pathList.length; i < len; i++) {
|
|
94
|
+
path = pathList[i], nextPath = pathList[i + 1]
|
|
95
|
+
for (let j = 0, jLen = path.length; j < jLen; j++) {
|
|
96
|
+
leaf = path.list[j]
|
|
97
|
+
if (nextPath && nextPath.has(leaf)) break
|
|
98
|
+
throughPath.push(leaf)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return throughPath
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
protected eachFind(children: Array<ILeaf>, hitMask: boolean): void {
|
|
107
|
+
let child: ILeaf, hit: boolean
|
|
108
|
+
const { point } = this, len = children.length
|
|
109
|
+
for (let i = len - 1; i > -1; i--) {
|
|
110
|
+
child = children[i]
|
|
111
|
+
if (hitMask && !child.isMask) continue
|
|
112
|
+
hit = hitRadiusPoint(child.__world, point)
|
|
113
|
+
|
|
114
|
+
if (child.isBranch) {
|
|
115
|
+
if (hit || child.__ignoreHitWorld) {
|
|
116
|
+
this.eachFind(child.children, child.__onlyHitMask)
|
|
117
|
+
if (child.isBranchLeaf && !this.findList.length) this.hitChild(child, point) // like frame
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
if (hit) this.hitChild(child, point)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
protected hitChild(child: ILeaf, point: IRadiusPointData): void {
|
|
126
|
+
if (this.exclude && this.exclude.has(child)) return
|
|
127
|
+
if (child.__hitWorld(point)) this.findList.push(child)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
protected clear(): void {
|
|
131
|
+
this.point = null
|
|
132
|
+
this.findList = null
|
|
133
|
+
this.exclude = null
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
public destroy(): void {
|
|
137
|
+
this.target = null
|
|
138
|
+
this.selector = null
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
}
|
package/src/Selector.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { ILeaf, ILeafArrayMap, ILeafMap, ISelector, ISelectPathResult, ISelectPathOptions, IPointData,
|
|
2
|
-
import { ChildEvent } from '@leafer/event'
|
|
3
|
-
import {
|
|
1
|
+
import { ILeaf, ILeafArrayMap, ILeafMap, ISelector, ISelectPathResult, ISelectPathOptions, IPointData, IEventListenerId, ISelectorConfig } from '@leafer/interface'
|
|
2
|
+
import { ChildEvent, LayoutEvent } from '@leafer/event'
|
|
3
|
+
import { DataHelper } from '@leafer/data'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { FindPath } from './FindPath'
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
interface IFind {
|
|
@@ -13,9 +13,10 @@ interface IFind {
|
|
|
13
13
|
export class Selector implements ISelector {
|
|
14
14
|
|
|
15
15
|
public target: ILeaf
|
|
16
|
-
public defaultPath: ILeafList
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
public config: ISelectorConfig = {}
|
|
18
|
+
|
|
19
|
+
protected findPath: FindPath
|
|
19
20
|
|
|
20
21
|
protected innerIdList: ILeafMap = {}
|
|
21
22
|
protected idList: ILeafMap = {}
|
|
@@ -24,18 +25,18 @@ export class Selector implements ISelector {
|
|
|
24
25
|
|
|
25
26
|
protected __eventIds: IEventListenerId[]
|
|
26
27
|
|
|
27
|
-
constructor(target: ILeaf) {
|
|
28
|
+
constructor(target: ILeaf, userConfig?: ISelectorConfig) {
|
|
28
29
|
this.target = target
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
30
|
+
if (userConfig) this.config = DataHelper.default(userConfig, this.config)
|
|
31
|
+
this.findPath = new FindPath(target, this)
|
|
31
32
|
this.__listenEvents()
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
public
|
|
35
|
-
|
|
35
|
+
public getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
|
|
36
|
+
this.target.emit(LayoutEvent.CHECK_UPDATE)
|
|
37
|
+
return this.findPath.getByPoint(hitPoint, hitRadius, options)
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
|
|
39
40
|
public find(name: number | string, branch?: ILeaf): ILeaf | ILeaf[] {
|
|
40
41
|
if (typeof name === 'number') {
|
|
41
42
|
return this.getByInnerId(name, branch)
|
|
@@ -96,7 +97,7 @@ export class Selector implements ISelector {
|
|
|
96
97
|
if (!branch) branch = this.target
|
|
97
98
|
let find: Array<ILeaf | ILeaf> = []
|
|
98
99
|
this.loopFind(branch, (leaf) => {
|
|
99
|
-
if (leaf.
|
|
100
|
+
if (leaf.__tag === name) find.push(leaf)
|
|
100
101
|
return false
|
|
101
102
|
})
|
|
102
103
|
return find
|
|
@@ -108,7 +109,7 @@ export class Selector implements ISelector {
|
|
|
108
109
|
for (let i = 0, len = children.length; i < len; i++) {
|
|
109
110
|
branch = children[i] as ILeaf
|
|
110
111
|
if (find(branch)) return
|
|
111
|
-
if (branch.
|
|
112
|
+
if (branch.isBranch) this.loopFind(branch, find)
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -132,10 +133,10 @@ export class Selector implements ISelector {
|
|
|
132
133
|
public destroy(): void {
|
|
133
134
|
if (this.target) {
|
|
134
135
|
this.__removeListenEvents()
|
|
135
|
-
this.
|
|
136
|
+
this.findPath.destroy()
|
|
136
137
|
|
|
137
138
|
this.target = null
|
|
138
|
-
this.
|
|
139
|
+
this.findPath = null
|
|
139
140
|
this.innerIdList = null
|
|
140
141
|
this.idList = null
|
|
141
142
|
this.classNameList = null
|
package/src/PathFinder.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { ILeaf, ILeafList, IPointData, IRadiusPointData, ISelectPathResult, ISelectPathOptions, ISelector } from '@leafer/interface'
|
|
2
|
-
import { BoundsHelper } from '@leafer/math'
|
|
3
|
-
import { LeafList } from '@leafer/list'
|
|
4
|
-
|
|
5
|
-
const { hitRadiusPoint } = BoundsHelper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export class PathFinder {
|
|
9
|
-
|
|
10
|
-
protected target: ILeaf
|
|
11
|
-
protected selector: ISelector
|
|
12
|
-
|
|
13
|
-
protected leaf?: ILeaf
|
|
14
|
-
protected throughPath: ILeafList
|
|
15
|
-
protected exclude: ILeafList
|
|
16
|
-
|
|
17
|
-
protected point: IRadiusPointData
|
|
18
|
-
protected isStop: boolean
|
|
19
|
-
|
|
20
|
-
constructor(target: ILeaf, selector: ISelector) {
|
|
21
|
-
this.target = target
|
|
22
|
-
this.selector = selector
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public getHitPointPath(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
|
|
26
|
-
const through = options ? options.through : false
|
|
27
|
-
this.exclude = options ? options.exclude : null
|
|
28
|
-
|
|
29
|
-
this.isStop = false
|
|
30
|
-
this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius }
|
|
31
|
-
|
|
32
|
-
// path
|
|
33
|
-
this.eachFind(this.target.children)
|
|
34
|
-
|
|
35
|
-
const { leaf } = this
|
|
36
|
-
const { defaultPath } = this.selector
|
|
37
|
-
const path = this.getPath(leaf)
|
|
38
|
-
path.pushList(defaultPath.list)
|
|
39
|
-
|
|
40
|
-
let result: ISelectPathResult
|
|
41
|
-
|
|
42
|
-
// throughPath
|
|
43
|
-
if (through) {
|
|
44
|
-
const throughPath = this.throughPath = new LeafList()
|
|
45
|
-
this.eachThroughFind(this.target.children)
|
|
46
|
-
throughPath.pushList(defaultPath.list)
|
|
47
|
-
result = { path, leaf, throughPath }
|
|
48
|
-
} else {
|
|
49
|
-
result = { path, leaf }
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
this.clear()
|
|
53
|
-
|
|
54
|
-
return result
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
public getPath(leaf: ILeaf): LeafList {
|
|
59
|
-
const list: LeafList = new LeafList()
|
|
60
|
-
while (leaf) {
|
|
61
|
-
list.push(leaf)
|
|
62
|
-
leaf = leaf.parent
|
|
63
|
-
}
|
|
64
|
-
return list
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected eachThroughFind(children: Array<ILeaf>): void {
|
|
68
|
-
let child: ILeaf
|
|
69
|
-
const { point } = this, len = children.length
|
|
70
|
-
for (let i = len - 1; i > -1; i--) {
|
|
71
|
-
child = children[i]
|
|
72
|
-
if (child.__.hittable) {
|
|
73
|
-
if (hitRadiusPoint(child.__world, point)) {
|
|
74
|
-
if (child.__isBranch && child.__.hitChildren) this.eachThroughFind(child.children)
|
|
75
|
-
|
|
76
|
-
if (this.exclude && this.exclude.has(child)) continue
|
|
77
|
-
if (child.__hitWorld(point)) this.throughPath.push(child)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
protected eachFind(children: Array<ILeaf>): void {
|
|
84
|
-
let child: ILeaf
|
|
85
|
-
const { point } = this, len = children.length
|
|
86
|
-
for (let i = len - 1; i > -1; i--) {
|
|
87
|
-
child = children[i]
|
|
88
|
-
if (child.__.hittable) {
|
|
89
|
-
if (hitRadiusPoint(child.__world, point)) {
|
|
90
|
-
if (child.__isBranch) {
|
|
91
|
-
|
|
92
|
-
if (child.__.hitChildren) this.eachFind(child.children)
|
|
93
|
-
|
|
94
|
-
if (child.__isBranchLeaf) { // 填充了背景色的Group, 如画板/Frame元素
|
|
95
|
-
if (!this.isStop) this.hitChild(child, point)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
} else {
|
|
99
|
-
this.hitChild(child, point)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (this.isStop) break
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
protected hitChild(child: ILeaf, point: IRadiusPointData): void {
|
|
109
|
-
if (this.exclude && this.exclude.has(child)) return
|
|
110
|
-
if (child.__hitWorld(point)) {
|
|
111
|
-
this.leaf = child
|
|
112
|
-
this.isStop = true
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
protected clear(): void {
|
|
117
|
-
this.point = null
|
|
118
|
-
this.leaf = null
|
|
119
|
-
this.throughPath = null
|
|
120
|
-
this.exclude = null
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
public destroy(): void {
|
|
124
|
-
this.target = null
|
|
125
|
-
this.selector = null
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
}
|