@leafer/selector 1.0.0-rc.8 → 1.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leafer/selector",
3
- "version": "1.0.0-rc.8",
3
+ "version": "1.0.0",
4
4
  "description": "@leafer/selector",
5
5
  "author": "Chao (Leafer) Wan",
6
6
  "license": "MIT",
@@ -15,16 +15,16 @@
15
15
  "type": "git",
16
16
  "url": "https://github.com/leaferjs/leafer.git"
17
17
  },
18
- "homepage": "https://github.com/leaferjs/leafer/tree/main/packages/selector",
18
+ "homepage": "https://github.com/leaferjs/leafer/tree/main/packages/partner/selector",
19
19
  "bugs": "https://github.com/leaferjs/leafer/issues",
20
20
  "keywords": [
21
21
  "leafer",
22
22
  "leaferjs"
23
23
  ],
24
24
  "dependencies": {
25
- "@leafer/core": "1.0.0-rc.8"
25
+ "@leafer/core": "1.0.0"
26
26
  },
27
27
  "devDependencies": {
28
- "@leafer/interface": "1.0.0-rc.8"
28
+ "@leafer/interface": "1.0.0"
29
29
  }
30
30
  }
@@ -1,15 +1,15 @@
1
- import { ILeaf, ILeafList, IPointData, IRadiusPointData, ISelectPathResult, ISelectPathOptions, ISelector } from '@leafer/interface'
1
+ import { ILeaf, ILeafList, IPointData, IRadiusPointData, IPickResult, IPickOptions, ISelector, IPickBottom } from '@leafer/interface'
2
2
  import { BoundsHelper, LeafList, LeafHelper } from '@leafer/core'
3
3
 
4
4
 
5
5
  const { hitRadiusPoint } = BoundsHelper
6
6
 
7
- export class Pather {
7
+ export class Picker {
8
8
 
9
9
  protected target: ILeaf
10
10
  protected selector: ISelector
11
11
 
12
- protected findList: ILeaf[]
12
+ protected findList: ILeafList
13
13
  protected exclude: ILeafList
14
14
 
15
15
  protected point: IRadiusPointData
@@ -19,45 +19,53 @@ export class Pather {
19
19
  this.selector = selector
20
20
  }
21
21
 
22
- public getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
22
+ public getByPoint(hitPoint: IPointData, hitRadius: number, options?: IPickOptions): IPickResult {
23
23
  if (!hitRadius) hitRadius = 0
24
24
  if (!options) options = {}
25
25
 
26
26
  const through = options.through || false
27
27
  const ignoreHittable = options.ignoreHittable || false
28
+ const target = options.target || this.target
28
29
  this.exclude = options.exclude || null
29
30
 
30
31
  this.point = { x: hitPoint.x, y: hitPoint.y, radiusX: hitRadius, radiusY: hitRadius }
31
- this.findList = []
32
+ this.findList = new LeafList(options.findList)
32
33
 
33
34
  // path
34
- this.eachFind(this.target.children, this.target.__onlyHitMask)
35
+ if (!options.findList) this.hitBranch(target) // 包含through元素
35
36
 
36
- const list = this.findList
37
- const leaf = this.getBestMatchLeaf()
37
+ const { list } = this.findList
38
+ const leaf = this.getBestMatchLeaf(list, options.bottomList, ignoreHittable)
38
39
  const path = ignoreHittable ? this.getPath(leaf) : this.getHitablePath(leaf)
39
40
 
40
41
  this.clear()
41
42
 
42
- return through ? { path, leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, leaf }
43
+ return through ? { path, target: leaf, throughPath: list.length ? this.getThroughPath(list) : path } : { path, target: leaf }
43
44
  }
44
45
 
45
- public getBestMatchLeaf(): ILeaf {
46
- const { findList: targets } = this
47
- if (targets.length > 1) {
46
+ public getBestMatchLeaf(list: ILeaf[], bottomList: IPickBottom[], ignoreHittable: boolean): ILeaf {
47
+ if (list.length) {
48
48
  let find: ILeaf
49
- this.findList = []
49
+ this.findList = new LeafList()
50
50
  const { x, y } = this.point
51
51
  const point = { x, y, radiusX: 0, radiusY: 0 }
52
- for (let i = 0, len = targets.length; i < len; i++) {
53
- find = targets[i]
54
- if (LeafHelper.worldHittable(find)) {
52
+ for (let i = 0, len = list.length; i < len; i++) {
53
+ find = list[i]
54
+ if (ignoreHittable || LeafHelper.worldHittable(find)) {
55
55
  this.hitChild(find, point)
56
- if (this.findList.length) return this.findList[0]
56
+ if (this.findList.length) return this.findList.list[0]
57
57
  }
58
58
  }
59
59
  }
60
- return targets[0]
60
+
61
+ if (bottomList) { // 底部虚拟元素
62
+ for (let i = 0, len = bottomList.length; i < len; i++) {
63
+ this.hitChild(bottomList[i].target, this.point, bottomList[i].proxy)
64
+ if (this.findList.length) return this.findList.list[0]
65
+ }
66
+ }
67
+
68
+ return list[0]
61
69
  }
62
70
 
63
71
  public getPath(leaf: ILeaf): LeafList {
@@ -71,7 +79,7 @@ export class Pather {
71
79
  }
72
80
 
73
81
  public getHitablePath(leaf: ILeaf): LeafList {
74
- const path = this.getPath(leaf)
82
+ const path = this.getPath(leaf && leaf.hittable ? leaf : null)
75
83
  let item: ILeaf, hittablePath = new LeafList()
76
84
  for (let i = path.list.length - 1; i > -1; i--) {
77
85
  item = path.list[i]
@@ -103,13 +111,16 @@ export class Pather {
103
111
  return throughPath
104
112
  }
105
113
 
114
+ protected hitBranch(branch: ILeaf): void {
115
+ this.eachFind(branch.children, branch.__onlyHitMask)
116
+ }
106
117
 
107
118
  protected eachFind(children: ILeaf[], hitMask: boolean): void {
108
119
  let child: ILeaf, hit: boolean
109
120
  const { point } = this, len = children.length
110
121
  for (let i = len - 1; i > -1; i--) {
111
122
  child = children[i]
112
- if (!child.__.visible || (hitMask && !child.__.isMask)) continue
123
+ if (!child.__.visible || (hitMask && !child.__.mask)) continue
113
124
  hit = child.__.hitRadius ? true : hitRadiusPoint(child.__world, point)
114
125
 
115
126
  if (child.isBranch) {
@@ -123,9 +134,13 @@ export class Pather {
123
134
  }
124
135
  }
125
136
 
126
- protected hitChild(child: ILeaf, point: IRadiusPointData): void {
137
+ protected hitChild(child: ILeaf, point: IRadiusPointData, proxy?: ILeaf): void {
127
138
  if (this.exclude && this.exclude.has(child)) return
128
- if (child.__hitWorld(point)) this.findList.push(child)
139
+ if (child.__hitWorld(point)) {
140
+ const { parent } = child
141
+ if (parent && parent.__hasMask && !child.__.mask && !parent.children.some(item => item.__.mask && item.__hitWorld(point))) return
142
+ this.findList.add(proxy || child)
143
+ }
129
144
  }
130
145
 
131
146
  protected clear(): void {
package/src/Selector.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { ILeaf, ILeafMap, ISelector, ISelectorProxy, ISelectPathResult, ISelectPathOptions, IPointData, IEventListenerId, ISelectorConfig, IFindMethod, AnswerType } from '@leafer/interface'
2
- import { ChildEvent, LayoutEvent, DataHelper, Platform, PropertyEvent, LeafHelper } from '@leafer/core'
1
+ import { ILeaf, ILeafMap, ISelector, ISelectorProxy, IPickResult, IPickOptions, IPointData, IEventListenerId, ISelectorConfig, IFindMethod, IAnswer, IFindCondition, IBooleanMap } from '@leafer/interface'
2
+ import { ChildEvent, LayoutEvent, DataHelper, Answer, Platform, PropertyEvent, LeafHelper } from '@leafer/core'
3
3
 
4
- import { Pather } from './Pather'
4
+ import { Picker } from './Picker'
5
5
 
6
6
 
7
- const { Yes, NoAndSkip, YesAndSkip } = AnswerType
8
-
7
+ const { Yes, NoAndSkip, YesAndSkip } = Answer
8
+ const idCondition = {} as IFindCondition, classNameCondition = {} as IFindCondition, tagCondition = {} as IFindCondition
9
9
  export class Selector implements ISelector {
10
10
 
11
11
  public target: ILeaf
@@ -14,7 +14,7 @@ export class Selector implements ISelector {
14
14
 
15
15
  public config: ISelectorConfig = {}
16
16
 
17
- protected pather: Pather
17
+ protected picker: Picker
18
18
 
19
19
  protected innerIdMap: ILeafMap = {}
20
20
  protected idMap: ILeafMap = {}
@@ -25,7 +25,8 @@ export class Selector implements ISelector {
25
25
  id: (leaf: ILeaf, name: string) => leaf.id === name ? (this.idMap[name] = leaf, 1) : 0,
26
26
  innerId: (leaf: ILeaf, innerId: number) => leaf.innerId === innerId ? (this.innerIdMap[innerId] = leaf, 1) : 0,
27
27
  className: (leaf: ILeaf, name: string) => leaf.className === name ? 1 : 0,
28
- tag: (leaf: ILeaf, name: string) => leaf.__tag === name ? 1 : 0
28
+ tag: (leaf: ILeaf, name: string) => leaf.__tag === name ? 1 : 0,
29
+ tags: (leaf: ILeaf, nameMap: IBooleanMap) => nameMap[leaf.__tag] ? 1 : 0
29
30
  }
30
31
 
31
32
  protected __eventIds: IEventListenerId[]
@@ -34,11 +35,11 @@ export class Selector implements ISelector {
34
35
  constructor(target: ILeaf, userConfig?: ISelectorConfig) {
35
36
  this.target = target
36
37
  if (userConfig) this.config = DataHelper.default(userConfig, this.config)
37
- this.pather = new Pather(target, this)
38
+ this.picker = new Picker(target, this)
38
39
  this.__listenEvents()
39
40
  }
40
41
 
41
- public getBy(condition: number | string | IFindMethod, branch?: ILeaf, one?: boolean, options?: any): ILeaf | ILeaf[] {
42
+ public getBy(condition: number | string | IFindCondition | IFindMethod, branch?: ILeaf, one?: boolean, options?: any): ILeaf | ILeaf[] {
42
43
  switch (typeof condition) {
43
44
  case 'number':
44
45
  const leaf = this.getByInnerId(condition, branch)
@@ -46,21 +47,30 @@ export class Selector implements ISelector {
46
47
  case 'string':
47
48
  switch (condition[0]) {
48
49
  case '#':
49
- const leaf = this.getById(condition.substring(1), branch)
50
- return one ? leaf : (leaf ? [leaf] : [])
50
+ idCondition.id = condition.substring(1), condition = idCondition; break
51
51
  case '.':
52
- return this.getByMethod(this.methods.className, branch, one, condition.substring(1)) // className
52
+ classNameCondition.className = condition.substring(1), condition = classNameCondition; break
53
53
  default:
54
- return this.getByMethod(this.methods.tag, branch, one, condition) // tagName
54
+ tagCondition.tag = condition, condition = tagCondition
55
+ }
56
+ case 'object':
57
+ if (condition.id !== undefined) {
58
+ const leaf = this.getById(condition.id as string, branch)
59
+ return one ? leaf : (leaf ? [leaf] : [])
60
+ } else if (condition.tag) {
61
+ const { tag } = condition, isArray = tag instanceof Array
62
+ return this.getByMethod(isArray ? this.methods.tags : this.methods.tag, branch, one, isArray ? DataHelper.toMap(tag) : tag)
63
+ } else {
64
+ return this.getByMethod(this.methods.className, branch, one, condition.className)
55
65
  }
56
66
  case 'function':
57
67
  return this.getByMethod(condition as IFindMethod, branch, one, options)
58
68
  }
59
69
  }
60
70
 
61
- public getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult {
71
+ public getByPoint(hitPoint: IPointData, hitRadius: number, options?: IPickOptions): IPickResult {
62
72
  if (Platform.name === 'node') this.target.emit(LayoutEvent.CHECK_UPDATE)
63
- return this.pather.getByPoint(hitPoint, hitRadius, options)
73
+ return this.picker.getByPoint(hitPoint, hitRadius, options)
64
74
  }
65
75
 
66
76
  public getByInnerId(innerId: number, branch?: ILeaf): ILeaf {
@@ -93,7 +103,7 @@ export class Selector implements ISelector {
93
103
 
94
104
 
95
105
  protected eachFind(children: ILeaf[], method: IFindMethod, list?: ILeaf[], options?: any): void {
96
- let child: ILeaf, result: AnswerType
106
+ let child: ILeaf, result: IAnswer
97
107
  for (let i = 0, len = children.length; i < len; i++) {
98
108
  child = children[i]
99
109
  result = method(child, options)
@@ -144,7 +154,7 @@ export class Selector implements ISelector {
144
154
  public destroy(): void {
145
155
  if (this.__eventIds.length) {
146
156
  this.__removeListenEvents()
147
- this.pather.destroy()
157
+ this.picker.destroy()
148
158
  this.findLeaf = null
149
159
  this.innerIdMap = {}
150
160
  this.idMap = {}
package/types/index.d.ts CHANGED
@@ -1,20 +1,21 @@
1
- import { ILeaf, ISelector, ILeafList, IRadiusPointData, IPointData, ISelectPathOptions, ISelectPathResult, ISelectorProxy, ISelectorConfig, ILeafMap, IEventListenerId, IFindMethod } from '@leafer/interface';
1
+ import { ILeaf, ISelector, ILeafList, IRadiusPointData, IPointData, IPickOptions, IPickResult, IPickBottom, ISelectorProxy, ISelectorConfig, ILeafMap, IBooleanMap, IEventListenerId, IFindCondition, IFindMethod } from '@leafer/interface';
2
2
  import { LeafList, ChildEvent, PropertyEvent } from '@leafer/core';
3
3
 
4
- declare class Pather {
4
+ declare class Picker {
5
5
  protected target: ILeaf;
6
6
  protected selector: ISelector;
7
- protected findList: ILeaf[];
7
+ protected findList: ILeafList;
8
8
  protected exclude: ILeafList;
9
9
  protected point: IRadiusPointData;
10
10
  constructor(target: ILeaf, selector: ISelector);
11
- getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult;
12
- getBestMatchLeaf(): ILeaf;
11
+ getByPoint(hitPoint: IPointData, hitRadius: number, options?: IPickOptions): IPickResult;
12
+ getBestMatchLeaf(list: ILeaf[], bottomList: IPickBottom[], ignoreHittable: boolean): ILeaf;
13
13
  getPath(leaf: ILeaf): LeafList;
14
14
  getHitablePath(leaf: ILeaf): LeafList;
15
15
  getThroughPath(list: ILeaf[]): LeafList;
16
+ protected hitBranch(branch: ILeaf): void;
16
17
  protected eachFind(children: ILeaf[], hitMask: boolean): void;
17
- protected hitChild(child: ILeaf, point: IRadiusPointData): void;
18
+ protected hitChild(child: ILeaf, point: IRadiusPointData, proxy?: ILeaf): void;
18
19
  protected clear(): void;
19
20
  destroy(): void;
20
21
  }
@@ -23,7 +24,7 @@ declare class Selector implements ISelector {
23
24
  target: ILeaf;
24
25
  proxy?: ISelectorProxy;
25
26
  config: ISelectorConfig;
26
- protected pather: Pather;
27
+ protected picker: Picker;
27
28
  protected innerIdMap: ILeafMap;
28
29
  protected idMap: ILeafMap;
29
30
  protected findLeaf: ILeaf;
@@ -32,11 +33,12 @@ declare class Selector implements ISelector {
32
33
  innerId: (leaf: ILeaf, innerId: number) => 1 | 0;
33
34
  className: (leaf: ILeaf, name: string) => 1 | 0;
34
35
  tag: (leaf: ILeaf, name: string) => 1 | 0;
36
+ tags: (leaf: ILeaf, nameMap: IBooleanMap) => 1 | 0;
35
37
  };
36
38
  protected __eventIds: IEventListenerId[];
37
39
  constructor(target: ILeaf, userConfig?: ISelectorConfig);
38
- getBy(condition: number | string | IFindMethod, branch?: ILeaf, one?: boolean, options?: any): ILeaf | ILeaf[];
39
- getByPoint(hitPoint: IPointData, hitRadius: number, options?: ISelectPathOptions): ISelectPathResult;
40
+ getBy(condition: number | string | IFindCondition | IFindMethod, branch?: ILeaf, one?: boolean, options?: any): ILeaf | ILeaf[];
41
+ getByPoint(hitPoint: IPointData, hitRadius: number, options?: IPickOptions): IPickResult;
40
42
  getByInnerId(innerId: number, branch?: ILeaf): ILeaf;
41
43
  getById(id: string, branch?: ILeaf): ILeaf;
42
44
  getByClassName(className: string, branch?: ILeaf): ILeaf[];