@leafer/selector 1.0.0-alpha.7 → 1.0.0-bate

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/selector",
3
- "version": "1.0.0-alpha.7",
3
+ "version": "1.0.0-bate",
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.7",
23
- "@leafer/math": "1.0.0-alpha.7",
24
- "@leafer/list": "1.0.0-alpha.7"
22
+ "@leafer/event": "1.0.0-bate",
23
+ "@leafer/math": "1.0.0-bate",
24
+ "@leafer/list": "1.0.0-bate"
25
25
  },
26
26
  "devDependencies": {
27
- "@leafer/interface": "1.0.0-alpha.7"
27
+ "@leafer/interface": "1.0.0-bate"
28
28
  }
29
29
  }
@@ -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, ILeafList, IEventListenerId } from '@leafer/interface'
2
- import { ChildEvent } from '@leafer/event'
3
- import { LeafList } from '@leafer/list'
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 { PathFinder } from './PathFinder'
5
+ import { FindPath } from './FindPath'
6
6
 
7
7
 
8
8
  interface IFind {
@@ -13,45 +13,30 @@ interface IFind {
13
13
  export class Selector implements ISelector {
14
14
 
15
15
  public target: ILeaf
16
- protected pathFinder: PathFinder
17
16
 
18
- public defaultPath: ILeafList
17
+ public config: ISelectorConfig = {}
19
18
 
20
- protected eventIds: IEventListenerId[]
19
+ protected findPath: FindPath
21
20
 
22
21
  protected innerIdList: ILeafMap = {}
23
22
  protected idList: ILeafMap = {}
24
23
  protected classNameList: ILeafArrayMap = {}
25
24
  protected tagNameList: ILeafArrayMap = {}
26
25
 
27
- constructor(target: ILeaf) {
28
- this.target = target
29
- this.defaultPath = new LeafList(target)
30
- this.pathFinder = new PathFinder(target, this)
31
- this.listenEvents()
32
- }
33
-
34
- protected listenEvents(): void {
35
- this.eventIds = [
36
- this.target.on__(ChildEvent.REMOVE, this.onRemoveChild, this)
37
- ]
38
- }
26
+ protected __eventIds: IEventListenerId[]
39
27
 
40
- protected removeListenEvents(): void {
41
- this.target.off__(this.eventIds)
42
- }
43
-
44
- protected onRemoveChild(event: ChildEvent): void {
45
- const target = event.target as ILeaf
46
- if (this.idList[target.id]) this.idList[target.id] = undefined
47
- if (this.innerIdList[target.id]) this.innerIdList[target.innerId] = undefined
28
+ constructor(target: ILeaf, userConfig?: ISelectorConfig) {
29
+ this.target = target
30
+ if (userConfig) this.config = DataHelper.default(userConfig, this.config)
31
+ this.findPath = new FindPath(target, this)
32
+ this.__listenEvents()
48
33
  }
49
34
 
50
- public getHitPointPath(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
51
- return this.pathFinder.getHitPointPath(hitPoint, hitRadius, options)
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)
52
38
  }
53
39
 
54
-
55
40
  public find(name: number | string, branch?: ILeaf): ILeaf | ILeaf[] {
56
41
  if (typeof name === 'number') {
57
42
  return this.getByInnerId(name, branch)
@@ -112,7 +97,7 @@ export class Selector implements ISelector {
112
97
  if (!branch) branch = this.target
113
98
  let find: Array<ILeaf | ILeaf> = []
114
99
  this.loopFind(branch, (leaf) => {
115
- if (leaf.tag === name) find.push(leaf)
100
+ if (leaf.__tag === name) find.push(leaf)
116
101
  return false
117
102
  })
118
103
  return find
@@ -124,21 +109,38 @@ export class Selector implements ISelector {
124
109
  for (let i = 0, len = children.length; i < len; i++) {
125
110
  branch = children[i] as ILeaf
126
111
  if (find(branch)) return
127
- if (branch.__isBranch) this.loopFind(branch, find)
112
+ if (branch.isBranch) this.loopFind(branch, find)
128
113
  }
129
114
  }
130
115
 
116
+ protected __onRemoveChild(event: ChildEvent): void {
117
+ const target = event.target as ILeaf
118
+ if (this.idList[target.id]) this.idList[target.id] = null
119
+ if (this.innerIdList[target.id]) this.innerIdList[target.innerId] = null
120
+ }
121
+
122
+
123
+ protected __listenEvents(): void {
124
+ this.__eventIds = [
125
+ this.target.on_(ChildEvent.REMOVE, this.__onRemoveChild, this)
126
+ ]
127
+ }
128
+
129
+ protected __removeListenEvents(): void {
130
+ this.target.off_(this.__eventIds)
131
+ }
132
+
131
133
  public destroy(): void {
132
134
  if (this.target) {
133
- this.removeListenEvents()
134
- this.pathFinder.destroy()
135
-
136
- this.target = undefined
137
- this.pathFinder = undefined
138
- this.innerIdList = undefined
139
- this.idList = undefined
140
- this.classNameList = undefined
141
- this.tagNameList = undefined
135
+ this.__removeListenEvents()
136
+ this.findPath.destroy()
137
+
138
+ this.target = null
139
+ this.findPath = null
140
+ this.innerIdList = null
141
+ this.idList = null
142
+ this.classNameList = null
143
+ this.tagNameList = null
142
144
  }
143
145
  }
144
146
 
package/src/PathFinder.ts DELETED
@@ -1,131 +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 : undefined
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.__interactionOff) continue
73
-
74
- if (hitRadiusPoint(child.__world, point)) {
75
- if (child.__isBranch) {
76
- child.__childrenInteractionOff || this.eachThroughFind(child.children)
77
- }
78
-
79
- if (this.exclude && this.exclude.has(child)) continue
80
- if (child.__hitWorld(point)) this.throughPath.push(child)
81
- }
82
-
83
- }
84
- }
85
-
86
- protected eachFind(children: Array<ILeaf>): void {
87
- let child: ILeaf
88
- const { point } = this, len = children.length
89
- for (let i = len - 1; i > -1; i--) {
90
- child = children[i]
91
- if (child.__interactionOff) continue
92
-
93
- if (hitRadiusPoint(child.__world, point)) {
94
- if (child.__isBranch) {
95
-
96
- child.__childrenInteractionOff || this.eachFind(child.children)
97
-
98
- if (child.__isBranchLeaf) { // 填充了背景色的Group, 如画板/Frame元素
99
- if (!this.isStop) this.hitChild(child, point)
100
- }
101
-
102
- } else {
103
- this.hitChild(child, point)
104
- }
105
- }
106
-
107
- if (this.isStop) break
108
- }
109
- }
110
-
111
- protected hitChild(child: ILeaf, point: IRadiusPointData): void {
112
- if (this.exclude && this.exclude.has(child)) return
113
- if (child.__hitWorld(point)) {
114
- this.leaf = child
115
- this.isStop = true
116
- }
117
- }
118
-
119
- protected clear(): void {
120
- this.point = undefined
121
- this.leaf = undefined
122
- this.throughPath = undefined
123
- this.exclude = undefined
124
- }
125
-
126
- public destroy(): void {
127
- this.target = undefined
128
- this.selector = undefined
129
- }
130
-
131
- }