@shijiu/jsview-vue 0.9.631 → 0.9.684
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/dom/bin/jsview-browser-debug-dom.min.js +1 -1
- package/dom/bin/jsview-dom.min.js +1 -1
- package/dom/bin/jsview-engine-js-browser.min.js +1 -0
- package/dom/target_core_revision.js +4 -4
- package/package.json +1 -1
- package/samples/Basic/components/text/TextOverflow.vue +8 -3
- package/samples/DemoHomepage/router.js +5 -0
- package/samples/Marquee/App.vue +176 -40
- package/samples/Marquee/longText.js +14 -0
- package/samples/MetroWidgetDemos/Advanced/App.vue +5 -6
- package/samples/MetroWidgetDemos/Advanced/ButtonItem.vue +1 -1
- package/samples/MetroWidgetDemos/Advanced/Buttons.vue +5 -5
- package/samples/MetroWidgetDemos/Advanced/Mixed.vue +4 -4
- package/samples/MetroWidgetDemos/Advanced/widgets/Item.vue +83 -0
- package/samples/MetroWidgetDemos/Advanced/widgets/WidgetItem.vue +89 -0
- package/samples/MetroWidgetDemos/Advanced/{Widgets.vue → widgets/Widgets.vue} +56 -11
- package/samples/MetroWidgetDemos/Advanced/widgets/focus1.png +0 -0
- package/samples/MetroWidgetDemos/Item.vue +20 -2
- package/samples/MetroWidgetDemos/Simple/AbsoluteTemplate.vue +2 -2
- package/samples/MetroWidgetDemos/Simple/App.vue +2 -2
- package/samples/MetroWidgetDemos/Simple/RelativeTemplate.vue +4 -4
- package/samples/MetroWidgetDemos/data.js +2 -1
- package/samples/ScaleDownNeon/App.vue +107 -0
- package/samples/TextBox/App.vue +7 -81
- package/samples/TextBox/RenderCenter.vue +40 -16
- package/samples/TextBox/RenderLeft.vue +48 -19
- package/samples/TextBox/RenderOneLine.vue +30 -49
- package/samples/TextBox/RenderRight.vue +40 -16
- package/samples/TextShadowDemo/App.vue +11 -17
- package/samples/TextureSize/App.vue +3 -3
- package/utils/JsViewEngineWidget/MetroWidget/Const.js +11 -0
- package/utils/JsViewEngineWidget/MetroWidget/MetroWidget.vue +188 -80
- package/utils/JsViewEngineWidget/TemplateParser.js +89 -32
- package/utils/JsViewEngineWidget/WidgetCommon.js +3 -4
- package/utils/JsViewEngineWidget/index.js +3 -2
- package/utils/JsViewPlugin/JsvPlayer/JsvMedia.js +61 -12
- package/utils/JsViewPlugin/JsvPlayer/JsvPlayer.vue +8 -1
- package/utils/JsViewPlugin/JsvPlayer/index.js +14 -0
- package/utils/JsViewPlugin/JsvPlayer/version.js +4 -4
- package/utils/JsViewVueWidget/JsvMarquee.vue +178 -205
- package/utils/JsViewVueWidget/JsvNativeSharedDiv.vue +35 -27
- package/utils/JsViewVueWidget/JsvNinePatch.vue +1 -2
- package/utils/JsViewVueWidget/JsvSwiper/JsvSwiper.vue +18 -2
- package/utils/JsViewVueWidget/JsvSwiper3D/JsvSwiper.vue +22 -2
- package/utils/JsViewVueWidget/JsvTextBox.vue +35 -72
- package/utils/JsViewVueWidget/JsvTouchContainer.vue +3 -4
- package/utils/JsViewVueWidget/utils/index.js +8 -0
- package/utils/JsViewVueWidget/utils/text.js +19 -0
- package/utils/JsViewEngineWidget/MetroPage.js +0 -2128
- package/utils/JsViewEngineWidget/SimpleWidget/ContentView.vue +0 -51
- package/utils/JsViewEngineWidget/SimpleWidget/Dispatcher.js +0 -19
- package/utils/JsViewEngineWidget/SimpleWidget/DivWrapper.vue +0 -53
- package/utils/JsViewEngineWidget/SimpleWidget/ItemView.vue +0 -142
- package/utils/JsViewEngineWidget/SimpleWidget/RootView.vue +0 -140
- package/utils/JsViewEngineWidget/SimpleWidget/SimpleWidget.vue +0 -1629
|
@@ -1,1629 +0,0 @@
|
|
|
1
|
-
<!--
|
|
2
|
-
* @Author: ChenChanghua
|
|
3
|
-
* @Date: 2021-09-22 16:08:58
|
|
4
|
-
* @LastEditors: ChenChanghua
|
|
5
|
-
* @LastEditTime: 2022-02-28 18:14:29
|
|
6
|
-
* @Description: file content
|
|
7
|
-
-->
|
|
8
|
-
|
|
9
|
-
<!--
|
|
10
|
-
* 【界面概述】
|
|
11
|
-
* 展示SimpleWidget控件的用法
|
|
12
|
-
*
|
|
13
|
-
* 【控件介绍】
|
|
14
|
-
* SimpleWidget:
|
|
15
|
-
* props:
|
|
16
|
-
* top {int} 控件的y,默认为0
|
|
17
|
-
* left {int} 控件的x, 默认为0
|
|
18
|
-
* width {int} (必选)控件的宽
|
|
19
|
-
* height {int} (必选)控件的高
|
|
20
|
-
* layoutType {String} 布局的类型, 目前支持 "relative"(默认)|"absolute", relative为自动布局,
|
|
21
|
-
absolute为依据measures中给的top, left布局
|
|
22
|
-
*
|
|
23
|
-
* name {string} 用于设置焦点的名称
|
|
24
|
-
* padding {object} 控件内边距, 默认为{left: 0, right: 0, top: 0, bottom: 0}
|
|
25
|
-
* direction {enum} (必选)控件方向 HORIZONTAL/VERTICAL
|
|
26
|
-
* loopFocus {boolean} 焦点到边界后自动转到下一行,默认false
|
|
27
|
-
* initFocusId {int} 初始焦点,默认为0
|
|
28
|
-
* slideSetting {SlideSetting} 页面滑动的设置, 目前SlideSetting有三个子类, 具体见 WidgetCommon 中的说明
|
|
29
|
-
WholePageSlide
|
|
30
|
-
@description 整页滚动的设置类
|
|
31
|
-
@constructor {Object} {speed, easing, boundProtect}
|
|
32
|
-
SeamlessSlide
|
|
33
|
-
@description 平滑滚动的设置类
|
|
34
|
-
@constructor {Object} {startPercent, endPercent, speed, easing, boundProtect}
|
|
35
|
-
FixPositionSlide
|
|
36
|
-
@description 固定位置滚动的设置类
|
|
37
|
-
@constructor {Object} {fixPercent, speed, easing, boundProtect}
|
|
38
|
-
* itemConfig {Function (item) => {takeOverSlide: true}} 返回item的配置信息
|
|
39
|
-
|
|
40
|
-
* data {array} (必选)数据列表
|
|
41
|
-
* measures {function} (必选)返回item的模板信息的回调,
|
|
42
|
-
* @params item {object} data中的数据
|
|
43
|
-
* @return 模板信息,
|
|
44
|
-
{
|
|
45
|
-
left: 绝对布局时的left,
|
|
46
|
-
top: 绝对布局时的top,
|
|
47
|
-
width: item的宽,
|
|
48
|
-
height: item的高,
|
|
49
|
-
focusable: item是否可以获得焦点,
|
|
50
|
-
marginBottom: item的下方margin,
|
|
51
|
-
marginRight: item的右方margin,
|
|
52
|
-
findNextAnchor: 自定义上下左右四条边寻找临近item的基准位置,值为0-1 {left: 0.5, right: 0.5, top: 0.5, bottom: 0.5}
|
|
53
|
-
}
|
|
54
|
-
*
|
|
55
|
-
* onFocus {function} 控件获取焦点的回调
|
|
56
|
-
* onBlur {function} 控件失去焦点的回调
|
|
57
|
-
* onEdge {function} 焦点移动到边缘时的回调
|
|
58
|
-
* @params {object} edgeInfo {
|
|
59
|
-
"direction": {EdgeDirection}边缘方向,
|
|
60
|
-
"rect": 到达边缘时的区域{x: 0, y: 0, width: 0,height: 0}
|
|
61
|
-
}
|
|
62
|
-
*
|
|
63
|
-
* enableTouch {boolean} 支持触控
|
|
64
|
-
* loadAll {boolean} 加载不显示的view,触控场景使用
|
|
65
|
-
* flingPageWidth {}
|
|
66
|
-
* flingPageEdge {}
|
|
67
|
-
* methods:
|
|
68
|
-
getFocusBlockRef 获取此SimpleWidget的 jsv-focus-block句柄,可以使用requestFocus完成获焦
|
|
69
|
-
|
|
70
|
-
slideTo
|
|
71
|
-
@description 滚动到指定位置
|
|
72
|
-
@params {int} position 滚动目标位置
|
|
73
|
-
@params {boolean} doAnim 是否做动画
|
|
74
|
-
slideToItem
|
|
75
|
-
@description 滚动到指定item
|
|
76
|
-
@params {int} index 目标item的index, 注意与item的id区别, id是可获焦item的序号
|
|
77
|
-
@params {boolean} doAnim 是否做动画
|
|
78
|
-
setEnterFocusId
|
|
79
|
-
@description 设置落焦时的焦点
|
|
80
|
-
@params {int} id 落焦时的焦点id
|
|
81
|
-
setEnterFocusRect
|
|
82
|
-
@description 设置落焦时的焦点查找去区域
|
|
83
|
-
@params {Object} rectInfo 焦点移入时的区域,SimpleWidget 将会根据此区域寻找最近的item
|
|
84
|
-
{
|
|
85
|
-
direction: {EdgeDirection}
|
|
86
|
-
rect: {
|
|
87
|
-
x: {int},
|
|
88
|
-
y: {int},
|
|
89
|
-
width: {int},
|
|
90
|
-
height: {int}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
setFocusId
|
|
94
|
-
@description 设置焦点
|
|
95
|
-
@params {int} id 焦点id
|
|
96
|
-
@params {boolean} needSlide 是否需要滚动
|
|
97
|
-
@params {boolean} doAnim 滚动时是否做动画
|
|
98
|
-
|
|
99
|
-
* 【技巧说明】
|
|
100
|
-
* Q: 插槽props如何使用?
|
|
101
|
-
* A: data: 当前item的数据
|
|
102
|
-
* query: 获取一些额外信息的对象
|
|
103
|
-
{
|
|
104
|
-
id: {int} item的id,
|
|
105
|
-
position: {Function} (index : int) => {left: 0, top: 0, width: 0, height: 0}
|
|
106
|
-
获取 item 相对 SimpleWidget 左上角坐标
|
|
107
|
-
templatePosition: {Function} (index : int) => {left: 0, top: 0, width: 0, height: 0}
|
|
108
|
-
获取 item 的布局坐标, 一般用于自定义滚动
|
|
109
|
-
absolutePosition: {Function} (index : int) => {left: 0, top: 0, width: 0, height: 0}
|
|
110
|
-
获取 item 的绝对坐标, 一般用于控制焦点
|
|
111
|
-
getCurrentFocusId: {Function} () => {id: 0, index: 0}
|
|
112
|
-
获取当前焦点信息,id 为在可获得焦点元素列表中的索引,index 为在所有元素列表中的索引
|
|
113
|
-
slideTo: {Function} (targetPosition : int, doAnim : Boolean) => void
|
|
114
|
-
滚动到指定位置,注意这个位置是 item 的布局坐标,另外当某些item需要接管滚动时,itemConfig中takeOverSlide要为true。
|
|
115
|
-
}
|
|
116
|
-
* onEdge: 若单元格内另有可接管按键的控件(如SimpleWidget),该控件到达边缘需要通知SimpleWidget时的回调
|
|
117
|
-
* onAction: 单元格内控件需要通过onAction.register方法向SimpleWidget注册 item 的回调,回调函数有
|
|
118
|
-
onFocus, onBlur, onClick, onWidgetEdge
|
|
119
|
-
*
|
|
120
|
-
* Q: 如何进行布局,定制每个格的尺寸?
|
|
121
|
-
* A: 首先选定一个布局的方式,一列列地横向布局(HROIZONTAL)还是一行行地纵向(VERTICAL)布局,设置给属性direction
|
|
122
|
-
* 然后将单元格尺寸反馈器(函数)设置到measures中,进行布局时,组件会回调measures函数获得每个单元格的尺寸,
|
|
123
|
-
* 当一列放满单元格后(如果是纵向布局,则是一行放满后),自动换列去布局下一列。
|
|
124
|
-
*
|
|
125
|
-
* Q: 单元格的普通状态,焦点状态,失焦状态如何渲染?
|
|
126
|
-
* A: 在单元的空间中通过往onAction注册的onFocus,onBlur控制显示
|
|
127
|
-
*
|
|
128
|
-
* Q: 控件中的导航处理(上下左右,OK键)需要什么响应的开发?
|
|
129
|
-
* A: 上下左右键已经由控件接管,不需要开发者而外处理,上下左右键会触发翻页时间,翻页的形式由属性slideStyle来定制。
|
|
130
|
-
* 另外,通过OnClick属性可以注册按键回调函数,来处理用户的OK键动作。
|
|
131
|
-
*
|
|
132
|
-
* Q: 边缘格获取焦点放大后显示不全?
|
|
133
|
-
* A: 设置padding,注意item的排布范围是控件的宽高减去对应的padding
|
|
134
|
-
*
|
|
135
|
-
* Q: 焦点怎么移出控件?
|
|
136
|
-
* A: 当焦点移动到控件边缘时,会调用onEdge回调。在回调中通过参数传递的值来决定焦点转移的行为
|
|
137
|
-
*
|
|
138
|
-
* Q: item内是可获焦的元素时该如何处理?
|
|
139
|
-
* A: 焦点处理: item内的元素需要在注册的onFocus和onBlue回调中管理焦点. 即在onFocus时把焦点设置到内部的可获焦节点;
|
|
140
|
-
onBlur时将焦点给回父SimpleWidget, 注意此时是焦点树上的子节点往父节点切换, 此时为了把子节点blur掉,
|
|
141
|
-
requestFocus函数需要传递一个false参数
|
|
142
|
-
-->
|
|
143
|
-
<script>
|
|
144
|
-
import { ref, reactive } from "vue";
|
|
145
|
-
import RootView from "./RootView.vue";
|
|
146
|
-
import Forge from "../ForgeDefine";
|
|
147
|
-
import { TemplateParser } from "../TemplateParser";
|
|
148
|
-
import { SingleRangeModel } from "../RangeModel";
|
|
149
|
-
import Dispatcher from "./Dispatcher";
|
|
150
|
-
import {
|
|
151
|
-
EdgeDirection,
|
|
152
|
-
VERTICAL,
|
|
153
|
-
HORIZONTAL,
|
|
154
|
-
SlideSetting,
|
|
155
|
-
SeamlessSlide,
|
|
156
|
-
getPositionRelativeToView,
|
|
157
|
-
} from "../WidgetCommon";
|
|
158
|
-
|
|
159
|
-
let emptyFunc = () => {};
|
|
160
|
-
// randomColor() {
|
|
161
|
-
// let randomColor = Math.round(Math.random() * 2 ** 24).toString(16);
|
|
162
|
-
// return (
|
|
163
|
-
// "#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
|
|
164
|
-
// );
|
|
165
|
-
// },
|
|
166
|
-
const _getPadding = function (padding) {
|
|
167
|
-
let result = {
|
|
168
|
-
left: 0,
|
|
169
|
-
right: 0,
|
|
170
|
-
top: 0,
|
|
171
|
-
bottom: 0,
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
if (typeof padding !== "undefined" && padding !== null) {
|
|
175
|
-
Object.assign(result, padding);
|
|
176
|
-
}
|
|
177
|
-
return result;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const _AddTemplateItem = function (
|
|
181
|
-
data,
|
|
182
|
-
measure_func,
|
|
183
|
-
template_parser,
|
|
184
|
-
start_index
|
|
185
|
-
) {
|
|
186
|
-
for (let i = start_index; i < data.length; i++) {
|
|
187
|
-
let block_item = measure_func(data[i]);
|
|
188
|
-
template_parser.ParseTemplateItem(block_item, data[i]);
|
|
189
|
-
}
|
|
190
|
-
template_parser.CalculateNeighborWhenAddStop();
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const _getTemplateParser = function (
|
|
194
|
-
width,
|
|
195
|
-
height,
|
|
196
|
-
direction,
|
|
197
|
-
padding,
|
|
198
|
-
support_history_path,
|
|
199
|
-
layout_type
|
|
200
|
-
) {
|
|
201
|
-
let fixed_padding = _getPadding(padding);
|
|
202
|
-
let line_max =
|
|
203
|
-
direction === VERTICAL
|
|
204
|
-
? width - fixed_padding.left - fixed_padding.right
|
|
205
|
-
: height - fixed_padding.top - fixed_padding.bottom;
|
|
206
|
-
return new TemplateParser(
|
|
207
|
-
direction,
|
|
208
|
-
line_max,
|
|
209
|
-
layout_type,
|
|
210
|
-
width,
|
|
211
|
-
height,
|
|
212
|
-
support_history_path
|
|
213
|
-
);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
// direction key 是 vertical 的值
|
|
217
|
-
const directionFreeKeyMap = {
|
|
218
|
-
pos: {
|
|
219
|
-
true: "yPos",
|
|
220
|
-
false: "xPos",
|
|
221
|
-
},
|
|
222
|
-
size: {
|
|
223
|
-
true: "height",
|
|
224
|
-
false: "width",
|
|
225
|
-
},
|
|
226
|
-
neighbor: {
|
|
227
|
-
true: {
|
|
228
|
-
1: "bottom",
|
|
229
|
-
"-1": "top",
|
|
230
|
-
},
|
|
231
|
-
false: {
|
|
232
|
-
1: "bottom",
|
|
233
|
-
"-1": "top",
|
|
234
|
-
},
|
|
235
|
-
},
|
|
236
|
-
margin: {
|
|
237
|
-
true: "marginBottom",
|
|
238
|
-
false: "marginRight",
|
|
239
|
-
},
|
|
240
|
-
center: {
|
|
241
|
-
true: "centerYPos",
|
|
242
|
-
false: "centerXPos",
|
|
243
|
-
},
|
|
244
|
-
};
|
|
245
|
-
|
|
246
|
-
const defaultSlideSetting = new SeamlessSlide(0.2, 0.8);
|
|
247
|
-
const SimpleWidget = {
|
|
248
|
-
components: { RootView },
|
|
249
|
-
props: {
|
|
250
|
-
padding: {
|
|
251
|
-
type: Object,
|
|
252
|
-
default() {
|
|
253
|
-
return {
|
|
254
|
-
top: 0,
|
|
255
|
-
left: 0,
|
|
256
|
-
right: 0,
|
|
257
|
-
bottom: 0,
|
|
258
|
-
};
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
direction: {
|
|
262
|
-
type: Symbol,
|
|
263
|
-
default: HORIZONTAL,
|
|
264
|
-
},
|
|
265
|
-
height: {
|
|
266
|
-
type: Number,
|
|
267
|
-
required: true,
|
|
268
|
-
},
|
|
269
|
-
width: {
|
|
270
|
-
type: Number,
|
|
271
|
-
required: true,
|
|
272
|
-
},
|
|
273
|
-
slideBoundary: {
|
|
274
|
-
validator(value) {
|
|
275
|
-
return !isNaN(value) && value < 0.5;
|
|
276
|
-
},
|
|
277
|
-
default: 0.2,
|
|
278
|
-
},
|
|
279
|
-
onClick: {
|
|
280
|
-
type: Function,
|
|
281
|
-
default: emptyFunc,
|
|
282
|
-
},
|
|
283
|
-
loopFocus: {
|
|
284
|
-
type: Boolean,
|
|
285
|
-
default: false,
|
|
286
|
-
},
|
|
287
|
-
onEdge: {
|
|
288
|
-
type: Function,
|
|
289
|
-
default: emptyFunc,
|
|
290
|
-
},
|
|
291
|
-
onFocus: {
|
|
292
|
-
type: Function,
|
|
293
|
-
default: emptyFunc,
|
|
294
|
-
},
|
|
295
|
-
onBlur: {
|
|
296
|
-
type: Function,
|
|
297
|
-
default: emptyFunc,
|
|
298
|
-
},
|
|
299
|
-
loadAll: {
|
|
300
|
-
type: Boolean,
|
|
301
|
-
default: false,
|
|
302
|
-
},
|
|
303
|
-
enableTouch: {
|
|
304
|
-
type: Boolean,
|
|
305
|
-
default: false,
|
|
306
|
-
},
|
|
307
|
-
flingPageWidth: {
|
|
308
|
-
type: Number,
|
|
309
|
-
default: -1,
|
|
310
|
-
},
|
|
311
|
-
flingPageEdge: {
|
|
312
|
-
type: Number,
|
|
313
|
-
default: 1 / 4,
|
|
314
|
-
},
|
|
315
|
-
dispatcher: {
|
|
316
|
-
type: Object,
|
|
317
|
-
},
|
|
318
|
-
measures: {
|
|
319
|
-
type: Function,
|
|
320
|
-
required: true,
|
|
321
|
-
},
|
|
322
|
-
baseAnchor: {
|
|
323
|
-
type: Object,
|
|
324
|
-
},
|
|
325
|
-
initFocusId: {
|
|
326
|
-
type: Number,
|
|
327
|
-
default: 0,
|
|
328
|
-
},
|
|
329
|
-
data: {
|
|
330
|
-
type: Array,
|
|
331
|
-
},
|
|
332
|
-
left: {
|
|
333
|
-
type: Number,
|
|
334
|
-
default: 0,
|
|
335
|
-
},
|
|
336
|
-
top: {
|
|
337
|
-
type: Number,
|
|
338
|
-
default: 0,
|
|
339
|
-
},
|
|
340
|
-
name: {
|
|
341
|
-
type: String,
|
|
342
|
-
},
|
|
343
|
-
supportHistoryPath: {
|
|
344
|
-
type: Boolean,
|
|
345
|
-
default: true,
|
|
346
|
-
},
|
|
347
|
-
itemConfig: {
|
|
348
|
-
type: Function,
|
|
349
|
-
},
|
|
350
|
-
onFocusChange: {
|
|
351
|
-
type: Function,
|
|
352
|
-
},
|
|
353
|
-
slideSetting: {
|
|
354
|
-
type: SlideSetting,
|
|
355
|
-
default: defaultSlideSetting,
|
|
356
|
-
},
|
|
357
|
-
layoutType: {
|
|
358
|
-
type: String,
|
|
359
|
-
default: "relative",
|
|
360
|
-
},
|
|
361
|
-
enableItemRenderBreak: {
|
|
362
|
-
type: Boolean,
|
|
363
|
-
default: false,
|
|
364
|
-
},
|
|
365
|
-
provideData: {
|
|
366
|
-
type: Function,
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
watch: {
|
|
370
|
-
data: function (value, oldValue) {
|
|
371
|
-
console.log("watch data change ", value, oldValue);
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
setup(props) {
|
|
375
|
-
return {
|
|
376
|
-
token: ref(0),
|
|
377
|
-
templateParser: null,
|
|
378
|
-
innerData: [],
|
|
379
|
-
dataList: [],
|
|
380
|
-
|
|
381
|
-
enterFocusId: -1,
|
|
382
|
-
enterFocusRect: null,
|
|
383
|
-
focusId: 0,
|
|
384
|
-
preFocusId: -1,
|
|
385
|
-
preEdgeRect: null,
|
|
386
|
-
isFocus: false,
|
|
387
|
-
perAnchor: null,
|
|
388
|
-
rootElement: null,
|
|
389
|
-
|
|
390
|
-
visibleStart: 0,
|
|
391
|
-
visibleRange: 0,
|
|
392
|
-
visibleRangeWithPadding: 0,
|
|
393
|
-
|
|
394
|
-
visibleItemIndexList: [],
|
|
395
|
-
needHideItemIndexList: [],
|
|
396
|
-
|
|
397
|
-
visibleRangeSearchBaseItem: 0,
|
|
398
|
-
|
|
399
|
-
touchContainerW: 0,
|
|
400
|
-
touchContainerH: 0,
|
|
401
|
-
touchListener: null,
|
|
402
|
-
innerPadding: null,
|
|
403
|
-
slidePile: null,
|
|
404
|
-
dragDirection: Forge.DragSetting.DIRECTION_HORIZONTAL,
|
|
405
|
-
vertical: props.direction == VERTICAL,
|
|
406
|
-
preAnchorItemIndex: -1,
|
|
407
|
-
wholePageHeadItem: {},
|
|
408
|
-
};
|
|
409
|
-
},
|
|
410
|
-
methods: {
|
|
411
|
-
//供外部获取SimpleWidget内部状态
|
|
412
|
-
_injectHandler() {
|
|
413
|
-
return {
|
|
414
|
-
getPosition: this._getPosition,
|
|
415
|
-
getTemplatePosition: this._getTemplatePosition,
|
|
416
|
-
getAbsolutePosition: this._getAbsolutePosition,
|
|
417
|
-
registerItemFunc: this._registerItemFunc,
|
|
418
|
-
getCurrentFocusId: this._getCurrentId,
|
|
419
|
-
isFocus: this._isFocus,
|
|
420
|
-
customerSlide: this.slideTo,
|
|
421
|
-
updateMounted: this._updateMounted,
|
|
422
|
-
registerItemRef: this._registerItemRef,
|
|
423
|
-
onFocusChange: this._onFocusChange,
|
|
424
|
-
};
|
|
425
|
-
},
|
|
426
|
-
|
|
427
|
-
_onFocusChange(id) {
|
|
428
|
-
this.onFocusChange?.(id);
|
|
429
|
-
},
|
|
430
|
-
|
|
431
|
-
_isFocus() {
|
|
432
|
-
return this.isFocus;
|
|
433
|
-
},
|
|
434
|
-
|
|
435
|
-
_getCurrentId() {
|
|
436
|
-
return {
|
|
437
|
-
id: this.focusId,
|
|
438
|
-
index: this.templateParser.FocusIdToIndex(this.focusId),
|
|
439
|
-
};
|
|
440
|
-
},
|
|
441
|
-
|
|
442
|
-
_registerItemFunc(index, handlerObj) {
|
|
443
|
-
this.innerData[index].itemHandler = handlerObj;
|
|
444
|
-
},
|
|
445
|
-
|
|
446
|
-
_registerItemRef(index, itemRef) {
|
|
447
|
-
this.innerData[index].itemRef = itemRef;
|
|
448
|
-
},
|
|
449
|
-
|
|
450
|
-
_updateMounted(index, mounted) {
|
|
451
|
-
if (index >= this.innerData.length) {
|
|
452
|
-
console.warn("sw updateMounted error: over range");
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
this.innerData[index].mounted = mounted;
|
|
456
|
-
},
|
|
457
|
-
|
|
458
|
-
_getPosition(index) {
|
|
459
|
-
let item = this.templateParser.GetItem(index);
|
|
460
|
-
let x_offset = this.direction === VERTICAL ? 0 : -this.visibleStart;
|
|
461
|
-
let y_offset = this.direction === VERTICAL ? -this.visibleStart : 0;
|
|
462
|
-
return {
|
|
463
|
-
left: item.xPos + x_offset,
|
|
464
|
-
top: item.yPos + y_offset,
|
|
465
|
-
width: item.width,
|
|
466
|
-
height: item.height,
|
|
467
|
-
};
|
|
468
|
-
},
|
|
469
|
-
|
|
470
|
-
_getTemplatePosition(index) {
|
|
471
|
-
let item = this.templateParser.GetItem(index);
|
|
472
|
-
return {
|
|
473
|
-
left: item.xPos,
|
|
474
|
-
top: item.yPos,
|
|
475
|
-
width: item.width,
|
|
476
|
-
height: item.height,
|
|
477
|
-
};
|
|
478
|
-
},
|
|
479
|
-
|
|
480
|
-
_getAbsolutePosition(index, targetEle) {
|
|
481
|
-
return getPositionRelativeToView(
|
|
482
|
-
this.innerData[index].itemRef?.getDivElement(),
|
|
483
|
-
targetEle
|
|
484
|
-
);
|
|
485
|
-
},
|
|
486
|
-
|
|
487
|
-
_dispatchEvent(event) {
|
|
488
|
-
switch (event.type) {
|
|
489
|
-
case Dispatcher.Type.setEnterFocusId:
|
|
490
|
-
this.setEnterFocusId(event.data);
|
|
491
|
-
break;
|
|
492
|
-
case Dispatcher.Type.setEnterFocusRect:
|
|
493
|
-
this.setEnterFocusRect(event.data);
|
|
494
|
-
break;
|
|
495
|
-
case Dispatcher.Type.updateItem:
|
|
496
|
-
break;
|
|
497
|
-
case Dispatcher.Type.slideToItem:
|
|
498
|
-
if (event.data) {
|
|
499
|
-
this.slideToItem(event.data?.id, event.data?.doAnim);
|
|
500
|
-
}
|
|
501
|
-
break;
|
|
502
|
-
case Dispatcher.Type.setFocusId:
|
|
503
|
-
this.setFocusId(
|
|
504
|
-
event.data?.id,
|
|
505
|
-
event.data?.needSlide,
|
|
506
|
-
event.data?.doAnim
|
|
507
|
-
);
|
|
508
|
-
break;
|
|
509
|
-
default:
|
|
510
|
-
break;
|
|
511
|
-
}
|
|
512
|
-
},
|
|
513
|
-
|
|
514
|
-
setFocusId(id, needSlide = true, doAnim = false) {
|
|
515
|
-
let next_focus_item = this.templateParser.GetItemById(id);
|
|
516
|
-
if (next_focus_item) {
|
|
517
|
-
if (needSlide) {
|
|
518
|
-
this.slideToItem(this.templateParser.FocusIdToIndex(id), doAnim);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
const cur_focus_item = this.templateParser.GetItemById(this.focusId);
|
|
522
|
-
this.preFocusId = this.focusId;
|
|
523
|
-
this.focusId = next_focus_item.id;
|
|
524
|
-
|
|
525
|
-
let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
|
|
526
|
-
let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
|
|
527
|
-
this.preEdgeRect = {
|
|
528
|
-
direction: null,
|
|
529
|
-
rect: {
|
|
530
|
-
x: x_off_set,
|
|
531
|
-
y: y_off_set,
|
|
532
|
-
width: cur_focus_item.width,
|
|
533
|
-
height: cur_focus_item.height,
|
|
534
|
-
},
|
|
535
|
-
};
|
|
536
|
-
this._updateBlurItem();
|
|
537
|
-
this._updateFocusItem();
|
|
538
|
-
if (this.isFocus) {
|
|
539
|
-
this.innerData[
|
|
540
|
-
this.templateParser.FocusIdToIndex(this.preFocusId)
|
|
541
|
-
].itemHandler.onBlur?.();
|
|
542
|
-
}
|
|
543
|
-
if (
|
|
544
|
-
this.isFocus &&
|
|
545
|
-
this.innerData[this.templateParser.FocusIdToIndex(this.focusId)]
|
|
546
|
-
.mounted
|
|
547
|
-
) {
|
|
548
|
-
this.innerData[
|
|
549
|
-
this.templateParser.FocusIdToIndex(this.focusId)
|
|
550
|
-
].itemHandler.onFocus?.(this.preEdgeRect);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
},
|
|
554
|
-
|
|
555
|
-
setEnterFocusId(id) {
|
|
556
|
-
this.enterFocusId = id;
|
|
557
|
-
},
|
|
558
|
-
|
|
559
|
-
setEnterFocusRect(rect) {
|
|
560
|
-
this.enterFocusRect = rect;
|
|
561
|
-
},
|
|
562
|
-
|
|
563
|
-
slideTo(position, doAnim) {
|
|
564
|
-
if (
|
|
565
|
-
typeof position !== "undefined" &&
|
|
566
|
-
position != null &&
|
|
567
|
-
this.visibleStart !== position
|
|
568
|
-
) {
|
|
569
|
-
this.visibleStart = position;
|
|
570
|
-
let animObj = null;
|
|
571
|
-
if (doAnim) {
|
|
572
|
-
animObj = {
|
|
573
|
-
easing: this.slideSetting.Easing,
|
|
574
|
-
onstart: null,
|
|
575
|
-
speed: this.slideSetting.Speed,
|
|
576
|
-
onend: this._onSlideEnd,
|
|
577
|
-
};
|
|
578
|
-
}
|
|
579
|
-
this.visibleRangeSearchBaseItem = this.focusId;
|
|
580
|
-
this._updateVisibleList(
|
|
581
|
-
this.focusId,
|
|
582
|
-
this.visibleStart,
|
|
583
|
-
this.visibleStart + this.visibleRangeWithPadding - 1
|
|
584
|
-
);
|
|
585
|
-
this._slideTo(this.visibleStart, animObj);
|
|
586
|
-
}
|
|
587
|
-
},
|
|
588
|
-
|
|
589
|
-
slideToItem(index, doAnim) {
|
|
590
|
-
const targetItem = this.templateParser.GetItem(index);
|
|
591
|
-
if (targetItem) {
|
|
592
|
-
const direction = index - this.preAnchorItemIndex > 0 ? 1 : -1;
|
|
593
|
-
const visible_start = this._calculateVisibleStart(
|
|
594
|
-
targetItem,
|
|
595
|
-
direction
|
|
596
|
-
);
|
|
597
|
-
this.slideTo(visible_start, doAnim);
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
|
-
|
|
601
|
-
freshData(force_update) {
|
|
602
|
-
//由于data不支持reactive, 因此数据的更新只通过provideData
|
|
603
|
-
if (!this.provideData) {
|
|
604
|
-
console.error("freshData: provideData is null.");
|
|
605
|
-
return;
|
|
606
|
-
}
|
|
607
|
-
let new_list = this.provideData();
|
|
608
|
-
let new_index = 0;
|
|
609
|
-
let template_list = this.templateParser.GetTemplate().List;
|
|
610
|
-
if (!force_update) {
|
|
611
|
-
for (new_index = 0; new_index < new_list.length; ++new_index) {
|
|
612
|
-
let already_add = false;
|
|
613
|
-
for (let j = 0; j < template_list.length; ++j) {
|
|
614
|
-
if (new_list[new_index] === template_list[j].data) {
|
|
615
|
-
already_add = true;
|
|
616
|
-
break;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
if (!already_add) {
|
|
620
|
-
break;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
let need_update_content = false;
|
|
625
|
-
if (new_index === template_list.length) {
|
|
626
|
-
//原始数据都在
|
|
627
|
-
if (new_index !== new_list.length) {
|
|
628
|
-
//增加数据
|
|
629
|
-
need_update_content = true;
|
|
630
|
-
_AddTemplateItem(
|
|
631
|
-
new_list,
|
|
632
|
-
this.measures,
|
|
633
|
-
this.templateParser,
|
|
634
|
-
new_index
|
|
635
|
-
);
|
|
636
|
-
} else {
|
|
637
|
-
//数据没变
|
|
638
|
-
}
|
|
639
|
-
} else {
|
|
640
|
-
//数据更改
|
|
641
|
-
need_update_content = true;
|
|
642
|
-
let template_parser = _getTemplateParser(
|
|
643
|
-
this.width,
|
|
644
|
-
this.height,
|
|
645
|
-
this.direction,
|
|
646
|
-
this.padding,
|
|
647
|
-
this.supportHistoryPath,
|
|
648
|
-
this.layoutType
|
|
649
|
-
);
|
|
650
|
-
_AddTemplateItem(new_list, this.measures, template_parser, 0);
|
|
651
|
-
this.templateParser = template_parser;
|
|
652
|
-
}
|
|
653
|
-
if (need_update_content) {
|
|
654
|
-
let template_list = this.templateParser.GetTemplate().List;
|
|
655
|
-
let last_item = template_list[template_list.length - 1];
|
|
656
|
-
this.touchListener = this._getTouchListener();
|
|
657
|
-
this.innerPadding = _getPadding(this.padding);
|
|
658
|
-
this.touchContainerW =
|
|
659
|
-
this.direction === VERTICAL
|
|
660
|
-
? this.width
|
|
661
|
-
: last_item.xPos + last_item.width;
|
|
662
|
-
this.touchContainerH =
|
|
663
|
-
this.direction === VERTICAL
|
|
664
|
-
? last_item.yPos + last_item.height
|
|
665
|
-
: this.height;
|
|
666
|
-
this.slidePile = new Forge.RectArea(
|
|
667
|
-
0,
|
|
668
|
-
0,
|
|
669
|
-
this.width - this.innerPadding.left - this.innerPadding.right,
|
|
670
|
-
this.height - this.innerPadding.top - this.innerPadding.bottom
|
|
671
|
-
);
|
|
672
|
-
this.dragDirection =
|
|
673
|
-
this.direction === VERTICAL
|
|
674
|
-
? Forge.DragSetting.DIRECTION_VERTICAL
|
|
675
|
-
: Forge.DragSetting.DIRECTION_HORIZONTAL;
|
|
676
|
-
this.innerData = template_list.map((item, index) => {
|
|
677
|
-
return {
|
|
678
|
-
data: item,
|
|
679
|
-
index: index,
|
|
680
|
-
controller: reactive({
|
|
681
|
-
visible: false,
|
|
682
|
-
zIndex: 0,
|
|
683
|
-
}),
|
|
684
|
-
mounted: false,
|
|
685
|
-
itemRef: null,
|
|
686
|
-
//之前的update时itemView不一定会重新create,因此注册的函数可以重复使用。若create了则会覆盖。
|
|
687
|
-
itemHandler: this.innerData[index]
|
|
688
|
-
? { ...this.innerData[index].itemHandler }
|
|
689
|
-
: {},
|
|
690
|
-
itemConfig: this.itemConfig?.(item.data),
|
|
691
|
-
};
|
|
692
|
-
});
|
|
693
|
-
this.token++;
|
|
694
|
-
}
|
|
695
|
-
if (this.focusId >= new_list.length) {
|
|
696
|
-
this.focusId = 0;
|
|
697
|
-
this.preFocusId = -1;
|
|
698
|
-
this.visibleRangeSearchBaseItem = 0;
|
|
699
|
-
if (this.visibleStart !== 0) {
|
|
700
|
-
this.visibleStart = 0;
|
|
701
|
-
this._slideTo(0, null);
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
//重新获取可视itemlist
|
|
705
|
-
this.visibleItemIndexList = this._getVisibleItemIndexList(
|
|
706
|
-
this.visibleRangeSearchBaseItem,
|
|
707
|
-
this.visibleStart,
|
|
708
|
-
this.visibleStart + this.visibleRange - 1
|
|
709
|
-
);
|
|
710
|
-
if (
|
|
711
|
-
this.isFocus &&
|
|
712
|
-
this.innerData[this.templateParser.FocusIdToIndex(this.focusId)].mounted
|
|
713
|
-
) {
|
|
714
|
-
this._updateFocusItem();
|
|
715
|
-
this.innerData[
|
|
716
|
-
this.templateParser.FocusIdToIndex(this.focusId)
|
|
717
|
-
].itemHandler.onFocus?.(null);
|
|
718
|
-
}
|
|
719
|
-
},
|
|
720
|
-
|
|
721
|
-
_getVisibleItemIndexList(id, start, end) {
|
|
722
|
-
// 扩展可视范围,避免快速滚动时闪烁
|
|
723
|
-
let s = start - 100 > 0 ? start - 100 : 0;
|
|
724
|
-
let e = end + 100;
|
|
725
|
-
let visible_info = this.templateParser.GetVisibleItemList(s, e, id);
|
|
726
|
-
let start_index = visible_info.visibleStart;
|
|
727
|
-
let end_index = visible_info.visibleEnd;
|
|
728
|
-
|
|
729
|
-
let index_list = new Array(end_index - start_index + 1);
|
|
730
|
-
for (let i = start_index; i <= end_index; i++) {
|
|
731
|
-
index_list[i - start_index] = i;
|
|
732
|
-
}
|
|
733
|
-
return index_list;
|
|
734
|
-
},
|
|
735
|
-
|
|
736
|
-
_calculateNearestItemByRect(visible_item_index_list, enter_rect_info) {
|
|
737
|
-
let edge_direction = enter_rect_info.direction;
|
|
738
|
-
let rect = enter_rect_info.rect;
|
|
739
|
-
var direction = "";
|
|
740
|
-
var point = { x: 0, y: 0 };
|
|
741
|
-
switch (edge_direction) {
|
|
742
|
-
case EdgeDirection.left:
|
|
743
|
-
direction = "left";
|
|
744
|
-
point.x = rect.x;
|
|
745
|
-
point.y = rect.y + rect.height / 4;
|
|
746
|
-
break;
|
|
747
|
-
case EdgeDirection.right:
|
|
748
|
-
direction = "right";
|
|
749
|
-
point.x = rect.x + rect.width;
|
|
750
|
-
point.y = rect.y + rect.height / 4;
|
|
751
|
-
break;
|
|
752
|
-
case EdgeDirection.top:
|
|
753
|
-
direction = "up";
|
|
754
|
-
point.x = rect.x + rect.width / 4;
|
|
755
|
-
point.y = rect.y;
|
|
756
|
-
break;
|
|
757
|
-
case EdgeDirection.bottom:
|
|
758
|
-
direction = "down";
|
|
759
|
-
point.x = rect.x + rect.width / 4;
|
|
760
|
-
point.y = rect.y + rect.height;
|
|
761
|
-
break;
|
|
762
|
-
default:
|
|
763
|
-
break;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
var src_x_range = new SingleRangeModel(point.x, point.x);
|
|
767
|
-
var src_y_range = new SingleRangeModel(point.y, point.y);
|
|
768
|
-
|
|
769
|
-
var min_distance_item = null;
|
|
770
|
-
var min_distance = -1;
|
|
771
|
-
var min_direction_weighted = 0;
|
|
772
|
-
var distance = 0;
|
|
773
|
-
var direction_weighted = 0; // 根据进入方向决定的权值,用于保证
|
|
774
|
-
|
|
775
|
-
let key_pos = this.direction === VERTICAL ? "yPos" : "xPos";
|
|
776
|
-
let key_width = this.direction === VERTICAL ? "height" : "width";
|
|
777
|
-
for (let index of visible_item_index_list) {
|
|
778
|
-
let item = this.templateParser.GetItem(index);
|
|
779
|
-
if (!item.focusable) continue;
|
|
780
|
-
let full_show =
|
|
781
|
-
item[key_pos] >= this.visibleStart &&
|
|
782
|
-
item[key_pos] + item[key_width] - 1 <=
|
|
783
|
-
this.visibleStart + this.visibleRange - 1;
|
|
784
|
-
if (full_show) {
|
|
785
|
-
let x_pos =
|
|
786
|
-
this.direction === VERTICAL
|
|
787
|
-
? item.xPos
|
|
788
|
-
: item.xPos - this.visibleStart;
|
|
789
|
-
let y_pos =
|
|
790
|
-
this.direction === VERTICAL
|
|
791
|
-
? item.yPos - this.visibleStart
|
|
792
|
-
: item.yPos;
|
|
793
|
-
var target_x_range = new SingleRangeModel(
|
|
794
|
-
x_pos,
|
|
795
|
-
x_pos + item.width - 1
|
|
796
|
-
);
|
|
797
|
-
var target_y_range = new SingleRangeModel(
|
|
798
|
-
y_pos,
|
|
799
|
-
y_pos + item.height - 1
|
|
800
|
-
);
|
|
801
|
-
switch (direction) {
|
|
802
|
-
case "left":
|
|
803
|
-
if (point.x < x_pos + item.width - 1) {
|
|
804
|
-
// 这个点在item左侧,不可能左移到item
|
|
805
|
-
continue;
|
|
806
|
-
}
|
|
807
|
-
if (point.y < y_pos) {
|
|
808
|
-
//1.该点在其上,计算point和item右上角的距离
|
|
809
|
-
distance =
|
|
810
|
-
Math.pow(point.x - (x_pos + item.width - 1), 2) +
|
|
811
|
-
Math.pow(y_pos - point.y, 2);
|
|
812
|
-
} else if (src_y_range.IsInterAct(target_y_range)) {
|
|
813
|
-
//2.该点在其中,计算point和item右边框的垂直距离
|
|
814
|
-
distance = Math.pow(point.x - (x_pos + item.width - 1), 2);
|
|
815
|
-
} else if (point.y > y_pos + item.height - 1) {
|
|
816
|
-
//3.该点在其下,计算point到item右下角的距离
|
|
817
|
-
distance =
|
|
818
|
-
Math.pow(point.x - (x_pos + item.width - 1), 2) +
|
|
819
|
-
Math.pow(point.y - (y_pos + item.height - 1), 2);
|
|
820
|
-
}
|
|
821
|
-
// point与item右边框的距离作为权值
|
|
822
|
-
direction_weighted = Math.abs(point.x - (x_pos + item.width - 1));
|
|
823
|
-
break;
|
|
824
|
-
case "right":
|
|
825
|
-
if (point.x > x_pos) {
|
|
826
|
-
// 这个点在item右侧,不可能右移到item
|
|
827
|
-
continue;
|
|
828
|
-
}
|
|
829
|
-
if (point.y < y_pos) {
|
|
830
|
-
//1.该点在其上, 计算point和item左上角的距离
|
|
831
|
-
distance =
|
|
832
|
-
Math.pow(x_pos - point.x, 2) + Math.pow(y_pos - point.y, 2);
|
|
833
|
-
} else if (src_y_range.IsInterAct(target_y_range)) {
|
|
834
|
-
//2.该点在其中,计算point和item左边框的垂直距离
|
|
835
|
-
distance = Math.pow(x_pos - point.x, 2);
|
|
836
|
-
//(x2-x1)^2
|
|
837
|
-
} else if (point.y > y_pos + item.height - 1) {
|
|
838
|
-
//3.该点在其下,计算point和item左下角的距离
|
|
839
|
-
distance =
|
|
840
|
-
Math.pow(x_pos - point.x, 2) +
|
|
841
|
-
Math.pow(point.y - (y_pos + item.height - 1), 2);
|
|
842
|
-
}
|
|
843
|
-
// point与item左边框的距离作为权值
|
|
844
|
-
direction_weighted = Math.abs(point.x - x_pos);
|
|
845
|
-
break;
|
|
846
|
-
case "up":
|
|
847
|
-
if (point.y < y_pos + item.height - 1) {
|
|
848
|
-
// 这个点在item上侧,不可能上移到item
|
|
849
|
-
continue;
|
|
850
|
-
}
|
|
851
|
-
if (point.x < x_pos) {
|
|
852
|
-
//1.该点在其前,计算point和item右下角的距离
|
|
853
|
-
distance =
|
|
854
|
-
Math.pow(point.x - x_pos, 2) +
|
|
855
|
-
Math.pow(point.y - (y_pos + item.height - 1), 2);
|
|
856
|
-
} else if (src_x_range.IsInterAct(target_x_range)) {
|
|
857
|
-
//2.该点在其中,计算point和item下边框的垂直距离
|
|
858
|
-
distance = Math.pow(point.y - (y_pos + item.height - 1), 2);
|
|
859
|
-
} else if (point.x > x_pos + item.width - 1) {
|
|
860
|
-
//3.该点在其后,计算point和item左下角的距离
|
|
861
|
-
distance =
|
|
862
|
-
Math.pow(point.x - (x_pos + item.width - 1), 2) +
|
|
863
|
-
Math.pow(point.y - (y_pos + item.height - 1), 2);
|
|
864
|
-
}
|
|
865
|
-
// point与item下边框的距离作为权值
|
|
866
|
-
direction_weighted = Math.abs(
|
|
867
|
-
point.y - (y_pos + item.height - 1)
|
|
868
|
-
);
|
|
869
|
-
break;
|
|
870
|
-
case "down":
|
|
871
|
-
if (point.y > y_pos) {
|
|
872
|
-
// 这个点在item下侧,不可能下移到item
|
|
873
|
-
continue;
|
|
874
|
-
}
|
|
875
|
-
if (point.x < x_pos) {
|
|
876
|
-
//1.该点在其前,计算point和item右上角的距离
|
|
877
|
-
distance =
|
|
878
|
-
Math.pow(point.x - x_pos, 2) + Math.pow(y_pos - point.y, 2);
|
|
879
|
-
} else if (src_x_range.IsInterAct(target_x_range)) {
|
|
880
|
-
//2.该点在其中,计算point和item上边框的垂直距离
|
|
881
|
-
distance = Math.pow(y_pos - point.y, 2);
|
|
882
|
-
} else if (point.x > x_pos + item.width - 1) {
|
|
883
|
-
//3.该点在其后,计算point和item左上角的距离
|
|
884
|
-
distance =
|
|
885
|
-
Math.pow(point.x - (x_pos + item.width - 1), 2) +
|
|
886
|
-
Math.pow(y_pos - point.y, 2);
|
|
887
|
-
}
|
|
888
|
-
// point与item上边框的距离作为权值
|
|
889
|
-
direction_weighted = Math.abs(point.y - y_pos);
|
|
890
|
-
break;
|
|
891
|
-
default:
|
|
892
|
-
console.log("direction is error:" + direction);
|
|
893
|
-
break;
|
|
894
|
-
}
|
|
895
|
-
if (min_distance < 0) {
|
|
896
|
-
// 设置首个找到的项目
|
|
897
|
-
min_distance = distance;
|
|
898
|
-
min_direction_weighted = direction_weighted;
|
|
899
|
-
min_distance_item = item;
|
|
900
|
-
} else {
|
|
901
|
-
if (
|
|
902
|
-
min_direction_weighted > direction_weighted ||
|
|
903
|
-
(min_direction_weighted === direction_weighted &&
|
|
904
|
-
min_distance > distance)
|
|
905
|
-
) {
|
|
906
|
-
// 先进行权值比较,在权值相等时,再比较距离
|
|
907
|
-
min_distance = distance;
|
|
908
|
-
min_direction_weighted = direction_weighted;
|
|
909
|
-
min_distance_item = item;
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
if (min_distance_item) {
|
|
916
|
-
return min_distance_item.id;
|
|
917
|
-
} else {
|
|
918
|
-
return 0;
|
|
919
|
-
}
|
|
920
|
-
},
|
|
921
|
-
|
|
922
|
-
_updateItemVisibility(item_index_list, visibility) {
|
|
923
|
-
for (let index of item_index_list) {
|
|
924
|
-
this.innerData[index].controller.visible = visibility;
|
|
925
|
-
}
|
|
926
|
-
},
|
|
927
|
-
|
|
928
|
-
_onClick(index) {
|
|
929
|
-
return this.innerData[index].itemHandler.onClick?.();
|
|
930
|
-
},
|
|
931
|
-
|
|
932
|
-
onKeyDown(ev) {
|
|
933
|
-
let horizontal_direction = 0;
|
|
934
|
-
let vertical_direction = 0;
|
|
935
|
-
switch (ev.keyCode) {
|
|
936
|
-
case 37:
|
|
937
|
-
horizontal_direction = -1;
|
|
938
|
-
this._moveToNext(horizontal_direction, vertical_direction);
|
|
939
|
-
break;
|
|
940
|
-
case 38:
|
|
941
|
-
vertical_direction = -1;
|
|
942
|
-
this._moveToNext(horizontal_direction, vertical_direction);
|
|
943
|
-
break;
|
|
944
|
-
case 39:
|
|
945
|
-
horizontal_direction = 1;
|
|
946
|
-
this._moveToNext(horizontal_direction, vertical_direction);
|
|
947
|
-
break;
|
|
948
|
-
case 40:
|
|
949
|
-
vertical_direction = 1;
|
|
950
|
-
this._moveToNext(horizontal_direction, vertical_direction);
|
|
951
|
-
break;
|
|
952
|
-
case 13:
|
|
953
|
-
this._onClick(this.templateParser.FocusIdToIndex(this.focusId));
|
|
954
|
-
break;
|
|
955
|
-
default:
|
|
956
|
-
//只接受上下左右确定键
|
|
957
|
-
return false;
|
|
958
|
-
}
|
|
959
|
-
return true;
|
|
960
|
-
},
|
|
961
|
-
|
|
962
|
-
_updateVisibleList(baseItemId, cur_visible_start, cur_visible_end) {
|
|
963
|
-
let pre_visible_list = this.visibleItemIndexList;
|
|
964
|
-
this.visibleItemIndexList = this._getVisibleItemIndexList(
|
|
965
|
-
baseItemId,
|
|
966
|
-
cur_visible_start,
|
|
967
|
-
cur_visible_end
|
|
968
|
-
);
|
|
969
|
-
for (let index of pre_visible_list) {
|
|
970
|
-
if (
|
|
971
|
-
this.visibleItemIndexList.indexOf(index) < 0 &&
|
|
972
|
-
this.needHideItemIndexList.indexOf(index) < 0
|
|
973
|
-
) {
|
|
974
|
-
this.needHideItemIndexList.push(index);
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
for (let index of this.visibleItemIndexList) {
|
|
978
|
-
let i = this.needHideItemIndexList.indexOf(index);
|
|
979
|
-
if (i >= 0) {
|
|
980
|
-
this.needHideItemIndexList.splice(i, 1);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
this.visibleStart = cur_visible_start;
|
|
985
|
-
//可见的item设置visibility
|
|
986
|
-
this._updateItemVisibility(this.visibleItemIndexList, true);
|
|
987
|
-
},
|
|
988
|
-
|
|
989
|
-
_slideTo(target, animObj) {
|
|
990
|
-
if (this.direction === HORIZONTAL) {
|
|
991
|
-
this.rootElement.updatePosition(-target, 0, animObj);
|
|
992
|
-
} else {
|
|
993
|
-
this.rootElement.updatePosition(0, -target, animObj);
|
|
994
|
-
}
|
|
995
|
-
},
|
|
996
|
-
|
|
997
|
-
_moveToNext(horizontal_direction, vertical_direction, item_edge_rect) {
|
|
998
|
-
let cur_focus_item = this.templateParser.GetItemById(this.focusId);
|
|
999
|
-
let next_item_id = this.templateParser.GetNextItem(
|
|
1000
|
-
this.focusId,
|
|
1001
|
-
vertical_direction,
|
|
1002
|
-
horizontal_direction,
|
|
1003
|
-
this.loopFocus
|
|
1004
|
-
);
|
|
1005
|
-
if (next_item_id >= 0) {
|
|
1006
|
-
this.preFocusId = this.focusId;
|
|
1007
|
-
let next_focus_item = this.templateParser.GetItemById(next_item_id);
|
|
1008
|
-
this.focusId = next_focus_item.id;
|
|
1009
|
-
let direction =
|
|
1010
|
-
this.direction === VERTICAL
|
|
1011
|
-
? vertical_direction
|
|
1012
|
-
: horizontal_direction;
|
|
1013
|
-
|
|
1014
|
-
let cur_visible_start = this._calculateVisibleStart(
|
|
1015
|
-
next_focus_item,
|
|
1016
|
-
direction
|
|
1017
|
-
);
|
|
1018
|
-
if (
|
|
1019
|
-
!this.innerData[this.templateParser.FocusIdToIndex(next_item_id)]
|
|
1020
|
-
.itemConfig?.takeOverSlide &&
|
|
1021
|
-
this.visibleStart !== cur_visible_start
|
|
1022
|
-
) {
|
|
1023
|
-
this.visibleStart = cur_visible_start;
|
|
1024
|
-
let animObj = {
|
|
1025
|
-
easing: "",
|
|
1026
|
-
onstart: null,
|
|
1027
|
-
speed: this.slideSetting.Speed,
|
|
1028
|
-
onend: this._onSlideEnd,
|
|
1029
|
-
};
|
|
1030
|
-
this._slideTo(this.visibleStart, animObj);
|
|
1031
|
-
this.visibleRangeSearchBaseItem = next_item_id;
|
|
1032
|
-
this._updateVisibleList(
|
|
1033
|
-
next_item_id,
|
|
1034
|
-
cur_visible_start,
|
|
1035
|
-
cur_visible_start + this.visibleRangeWithPadding - 1
|
|
1036
|
-
);
|
|
1037
|
-
} else {
|
|
1038
|
-
// 无滚动, 通知父滚动
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
let rect;
|
|
1042
|
-
let x_off_set = cur_focus_item.xPos - next_focus_item.xPos;
|
|
1043
|
-
let y_off_set = cur_focus_item.yPos - next_focus_item.yPos;
|
|
1044
|
-
if (item_edge_rect) {
|
|
1045
|
-
item_edge_rect.rect.x += x_off_set;
|
|
1046
|
-
item_edge_rect.rect.y += y_off_set;
|
|
1047
|
-
rect = item_edge_rect;
|
|
1048
|
-
} else {
|
|
1049
|
-
rect = {
|
|
1050
|
-
direction: null,
|
|
1051
|
-
rect: {
|
|
1052
|
-
x: x_off_set,
|
|
1053
|
-
y: y_off_set,
|
|
1054
|
-
width: cur_focus_item.width,
|
|
1055
|
-
height: cur_focus_item.height,
|
|
1056
|
-
},
|
|
1057
|
-
};
|
|
1058
|
-
}
|
|
1059
|
-
this.preEdgeRect = rect;
|
|
1060
|
-
this._updateBlurItem();
|
|
1061
|
-
this._updateFocusItem();
|
|
1062
|
-
if (this.isFocus) {
|
|
1063
|
-
this.innerData[
|
|
1064
|
-
this.templateParser.FocusIdToIndex(this.preFocusId)
|
|
1065
|
-
].itemHandler.onBlur?.();
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
if (
|
|
1069
|
-
this.isFocus &&
|
|
1070
|
-
this.innerData[this.templateParser.FocusIdToIndex(this.focusId)]
|
|
1071
|
-
.mounted
|
|
1072
|
-
) {
|
|
1073
|
-
this.innerData[
|
|
1074
|
-
this.templateParser.FocusIdToIndex(this.focusId)
|
|
1075
|
-
].itemHandler.onFocus?.(this.preEdgeRect);
|
|
1076
|
-
}
|
|
1077
|
-
} else {
|
|
1078
|
-
let x_off_set = this.direction === VERTICAL ? 0 : this.visibleStart;
|
|
1079
|
-
let y_off_set = this.direction === VERTICAL ? this.visibleStart : 0;
|
|
1080
|
-
let edge;
|
|
1081
|
-
if (horizontal_direction === 1) {
|
|
1082
|
-
edge = EdgeDirection.right;
|
|
1083
|
-
}
|
|
1084
|
-
if (horizontal_direction === -1) {
|
|
1085
|
-
edge = EdgeDirection.left;
|
|
1086
|
-
}
|
|
1087
|
-
if (vertical_direction === 1) {
|
|
1088
|
-
edge = EdgeDirection.bottom;
|
|
1089
|
-
}
|
|
1090
|
-
if (vertical_direction === -1) {
|
|
1091
|
-
edge = EdgeDirection.top;
|
|
1092
|
-
}
|
|
1093
|
-
let rect = {
|
|
1094
|
-
x: cur_focus_item.xPos - x_off_set,
|
|
1095
|
-
y: cur_focus_item.yPos - y_off_set,
|
|
1096
|
-
width: cur_focus_item.width,
|
|
1097
|
-
height: cur_focus_item.height,
|
|
1098
|
-
};
|
|
1099
|
-
if (this.onEdge) {
|
|
1100
|
-
this.onEdge({ direction: edge, rect: rect });
|
|
1101
|
-
}
|
|
1102
|
-
this.innerData[
|
|
1103
|
-
this.templateParser.FocusIdToIndex(this.focusId)
|
|
1104
|
-
].itemHandler.reachEdge?.({
|
|
1105
|
-
direction: edge,
|
|
1106
|
-
});
|
|
1107
|
-
}
|
|
1108
|
-
},
|
|
1109
|
-
|
|
1110
|
-
_adjustToValidPosition(visible_start, adjust_end) {
|
|
1111
|
-
//TODO 优化
|
|
1112
|
-
let last_item = this.templateParser.GetItem(-1);
|
|
1113
|
-
let pos_key = directionFreeKeyMap.pos[this.direction === VERTICAL];
|
|
1114
|
-
let size_key = directionFreeKeyMap.size[this.direction === VERTICAL];
|
|
1115
|
-
let padding = _getPadding(this.padding);
|
|
1116
|
-
|
|
1117
|
-
let padding_offset =
|
|
1118
|
-
this.direction === VERTICAL
|
|
1119
|
-
? padding["bottom"] + padding["top"]
|
|
1120
|
-
: padding["right"] + padding["left"];
|
|
1121
|
-
let visible_range =
|
|
1122
|
-
(this.direction === VERTICAL ? this.height : this.width) -
|
|
1123
|
-
padding_offset;
|
|
1124
|
-
|
|
1125
|
-
let last_position = last_item[pos_key] + last_item[size_key];
|
|
1126
|
-
let last_item_off_set = last_position - visible_range;
|
|
1127
|
-
last_item_off_set = last_item_off_set < 0 ? 0 : last_item_off_set;
|
|
1128
|
-
if (adjust_end && visible_start > last_item_off_set) {
|
|
1129
|
-
return last_item_off_set;
|
|
1130
|
-
} else if (visible_start < 0) {
|
|
1131
|
-
return 0;
|
|
1132
|
-
} else {
|
|
1133
|
-
return visible_start;
|
|
1134
|
-
}
|
|
1135
|
-
},
|
|
1136
|
-
|
|
1137
|
-
_getPageHeadItem(start, end, visible_start, pos_key) {
|
|
1138
|
-
if (start != end) {
|
|
1139
|
-
const center = Math.floor((start + end) / 2);
|
|
1140
|
-
if (this.templateParser.GetItem(center)[pos_key] >= visible_start) {
|
|
1141
|
-
return this._getPageHeadItem(start, center, visible_start, pos_key);
|
|
1142
|
-
} else {
|
|
1143
|
-
return this._getPageHeadItem(center + 1, end, visible_start, pos_key);
|
|
1144
|
-
}
|
|
1145
|
-
} else {
|
|
1146
|
-
return start;
|
|
1147
|
-
}
|
|
1148
|
-
},
|
|
1149
|
-
|
|
1150
|
-
_findNearestPageHeadItem(num) {
|
|
1151
|
-
let max_page = -1;
|
|
1152
|
-
for (let i in this.wholePageHeadItem) {
|
|
1153
|
-
if (i < num && i > max_page) {
|
|
1154
|
-
max_page = i;
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
if (max_page >= 0) {
|
|
1158
|
-
return this.wholePageHeadItem[max_page];
|
|
1159
|
-
} else {
|
|
1160
|
-
return 0;
|
|
1161
|
-
}
|
|
1162
|
-
},
|
|
1163
|
-
|
|
1164
|
-
_calculateVisibleStart(target_item, direction) {
|
|
1165
|
-
if (!target_item) {
|
|
1166
|
-
console.error(
|
|
1167
|
-
"SimpleWidget: _calculateVisibleStart target item is null"
|
|
1168
|
-
);
|
|
1169
|
-
return 0;
|
|
1170
|
-
}
|
|
1171
|
-
this.preAnchorItemIndex = target_item.index;
|
|
1172
|
-
let pos_key = directionFreeKeyMap.pos[this.vertical];
|
|
1173
|
-
let size_key = directionFreeKeyMap.size[this.vertical];
|
|
1174
|
-
let center_key = directionFreeKeyMap.center[this.vertical];
|
|
1175
|
-
let new_visible_start = this.visibleStart;
|
|
1176
|
-
|
|
1177
|
-
let page_start_index;
|
|
1178
|
-
let page_num;
|
|
1179
|
-
switch (this.slideSetting.Type) {
|
|
1180
|
-
case SlideSetting.Type.FIX_POSITION:
|
|
1181
|
-
//FIX_POSITION 模式会将当前 item 的中心固定到指定位置
|
|
1182
|
-
new_visible_start = Math.ceil(
|
|
1183
|
-
target_item[center_key] -
|
|
1184
|
-
this.visibleRange * this.slideSetting.FixPercent
|
|
1185
|
-
);
|
|
1186
|
-
break;
|
|
1187
|
-
case SlideSetting.Type.WHOLE_PAGE:
|
|
1188
|
-
page_num = Math.floor(target_item[pos_key] / this.visibleRange);
|
|
1189
|
-
if (typeof this.wholePageHeadItem[page_num] !== "undefined") {
|
|
1190
|
-
page_start_index = this.wholePageHeadItem[page_num];
|
|
1191
|
-
} else {
|
|
1192
|
-
new_visible_start = page_num * this.visibleRange;
|
|
1193
|
-
page_start_index = this._getPageHeadItem(
|
|
1194
|
-
this._findNearestPageHeadItem(page_num),
|
|
1195
|
-
target_item.index,
|
|
1196
|
-
new_visible_start,
|
|
1197
|
-
pos_key
|
|
1198
|
-
);
|
|
1199
|
-
this.wholePageHeadItem[page_num] = page_start_index;
|
|
1200
|
-
}
|
|
1201
|
-
new_visible_start =
|
|
1202
|
-
this.templateParser.GetItem(page_start_index)[pos_key];
|
|
1203
|
-
break;
|
|
1204
|
-
case SlideSetting.Type.SEAMLESS:
|
|
1205
|
-
if (direction > 0) {
|
|
1206
|
-
if (
|
|
1207
|
-
target_item[pos_key] + target_item[size_key] >
|
|
1208
|
-
this.visibleStart +
|
|
1209
|
-
this.visibleRange * this.slideSetting.EndPercent
|
|
1210
|
-
) {
|
|
1211
|
-
new_visible_start =
|
|
1212
|
-
target_item[pos_key] +
|
|
1213
|
-
target_item[size_key] -
|
|
1214
|
-
this.visibleRange * this.slideSetting.EndPercent;
|
|
1215
|
-
}
|
|
1216
|
-
} else if (direction < 0) {
|
|
1217
|
-
if (
|
|
1218
|
-
target_item[pos_key] <
|
|
1219
|
-
this.visibleStart +
|
|
1220
|
-
this.visibleRange * this.slideSetting.StartPercent
|
|
1221
|
-
) {
|
|
1222
|
-
new_visible_start =
|
|
1223
|
-
target_item[pos_key] -
|
|
1224
|
-
this.visibleRange * this.slideSetting.StartPercent;
|
|
1225
|
-
}
|
|
1226
|
-
} else {
|
|
1227
|
-
//不是沿widget方向的移动
|
|
1228
|
-
if (target_item[pos_key] < this.visibleStart) {
|
|
1229
|
-
new_visible_start =
|
|
1230
|
-
target_item[pos_key] -
|
|
1231
|
-
this.visibleRange * this.slideSetting.StartPercent;
|
|
1232
|
-
} else if (
|
|
1233
|
-
target_item[pos_key] + target_item[size_key] >
|
|
1234
|
-
this.visibleStart + this.visibleRange
|
|
1235
|
-
) {
|
|
1236
|
-
new_visible_start =
|
|
1237
|
-
target_item[pos_key] +
|
|
1238
|
-
target_item[size_key] -
|
|
1239
|
-
this.visibleRange * this.slideSetting.EndPercent;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
break;
|
|
1243
|
-
default:
|
|
1244
|
-
console.error(
|
|
1245
|
-
"SimpleWidget: undefined slide type",
|
|
1246
|
-
this.slideSetting.Type
|
|
1247
|
-
);
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
if (
|
|
1251
|
-
(this.slideSetting.BoundaryProtect & SlideSetting.START_PROTECT) >
|
|
1252
|
-
0
|
|
1253
|
-
) {
|
|
1254
|
-
let boundary = 0;
|
|
1255
|
-
if (!this.templateParser.GetItem(0).focusable) {
|
|
1256
|
-
//首个元素是占位符
|
|
1257
|
-
boundary = this.templateParser.GetItem(0)[size_key];
|
|
1258
|
-
}
|
|
1259
|
-
new_visible_start =
|
|
1260
|
-
new_visible_start < boundary ? 0 : new_visible_start;
|
|
1261
|
-
}
|
|
1262
|
-
if ((this.slideSetting.BoundaryProtect & SlideSetting.END_PROTECT) > 0) {
|
|
1263
|
-
let last_item = this.templateParser.GetItem(-1);
|
|
1264
|
-
let last_visible_start =
|
|
1265
|
-
last_item[pos_key] + last_item[size_key] - this.visibleRange - 1;
|
|
1266
|
-
last_visible_start = last_visible_start < 0 ? 0 : last_visible_start;
|
|
1267
|
-
let boundary = last_visible_start;
|
|
1268
|
-
if (!last_item.focusable) {
|
|
1269
|
-
//最后个元素是占位符
|
|
1270
|
-
boundary = last_item[pos_key] - this.visibleRange;
|
|
1271
|
-
}
|
|
1272
|
-
new_visible_start =
|
|
1273
|
-
new_visible_start > boundary ? last_visible_start : new_visible_start;
|
|
1274
|
-
}
|
|
1275
|
-
return new_visible_start;
|
|
1276
|
-
},
|
|
1277
|
-
|
|
1278
|
-
_onFocusableItemEdge(edge_info) {
|
|
1279
|
-
let horizontal_direction = 0;
|
|
1280
|
-
let vertical_direction = 0;
|
|
1281
|
-
switch (edge_info.direction) {
|
|
1282
|
-
case EdgeDirection.left:
|
|
1283
|
-
horizontal_direction = -1;
|
|
1284
|
-
break;
|
|
1285
|
-
case EdgeDirection.right:
|
|
1286
|
-
horizontal_direction = 1;
|
|
1287
|
-
break;
|
|
1288
|
-
case EdgeDirection.top:
|
|
1289
|
-
vertical_direction = -1;
|
|
1290
|
-
break;
|
|
1291
|
-
case EdgeDirection.bottom:
|
|
1292
|
-
vertical_direction = 1;
|
|
1293
|
-
break;
|
|
1294
|
-
default:
|
|
1295
|
-
break;
|
|
1296
|
-
}
|
|
1297
|
-
this._moveToNext(horizontal_direction, vertical_direction, edge_info);
|
|
1298
|
-
},
|
|
1299
|
-
|
|
1300
|
-
_ifValidEnterRect(rect_info) {
|
|
1301
|
-
return rect_info && rect_info.direction && rect_info.rect;
|
|
1302
|
-
},
|
|
1303
|
-
|
|
1304
|
-
_setZIndex(index, z_index) {
|
|
1305
|
-
this.innerData[index].controller.zIndex = z_index;
|
|
1306
|
-
},
|
|
1307
|
-
|
|
1308
|
-
_onFocus() {
|
|
1309
|
-
let focus_id =
|
|
1310
|
-
typeof this.enterFocusId !== "undefined" &&
|
|
1311
|
-
this.enterFocusId >= 0 &&
|
|
1312
|
-
this.enterFocusId < this.templateParser.GetTemplate().List.length
|
|
1313
|
-
? this.enterFocusId
|
|
1314
|
-
: this.focusId;
|
|
1315
|
-
focus_id = this._ifValidEnterRect(this.enterFocusRect)
|
|
1316
|
-
? this._calculateNearestItemByRect(
|
|
1317
|
-
this.visibleItemIndexList,
|
|
1318
|
-
this.enterFocusRect
|
|
1319
|
-
)
|
|
1320
|
-
: focus_id;
|
|
1321
|
-
|
|
1322
|
-
this.isFocus = true;
|
|
1323
|
-
this.focusId = focus_id;
|
|
1324
|
-
this.preFocusId = -1;
|
|
1325
|
-
this.enterFocusId = -1;
|
|
1326
|
-
this.enterFocusRect = null;
|
|
1327
|
-
this._updateFocusItem();
|
|
1328
|
-
|
|
1329
|
-
if (
|
|
1330
|
-
this.isFocus &&
|
|
1331
|
-
this.innerData[this.templateParser.FocusIdToIndex(this.focusId)].mounted
|
|
1332
|
-
) {
|
|
1333
|
-
this.innerData[
|
|
1334
|
-
this.templateParser.FocusIdToIndex(this.focusId)
|
|
1335
|
-
].itemHandler.onFocus?.(this.preEdgeRect);
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
if (this.onFocus) {
|
|
1339
|
-
this.onFocus();
|
|
1340
|
-
}
|
|
1341
|
-
},
|
|
1342
|
-
|
|
1343
|
-
_onBlur() {
|
|
1344
|
-
this.isFocus = false;
|
|
1345
|
-
this.enterFocusId = -1;
|
|
1346
|
-
this.enterFocusRect = null;
|
|
1347
|
-
|
|
1348
|
-
this.preFocusId = this.focusId;
|
|
1349
|
-
this.preEdgeRect = null;
|
|
1350
|
-
this._updateBlurItem();
|
|
1351
|
-
this.innerData[
|
|
1352
|
-
this.templateParser.FocusIdToIndex(this.preFocusId)
|
|
1353
|
-
].itemHandler.onBlur?.();
|
|
1354
|
-
|
|
1355
|
-
if (this.onBlur) {
|
|
1356
|
-
this.onBlur();
|
|
1357
|
-
}
|
|
1358
|
-
},
|
|
1359
|
-
|
|
1360
|
-
_applyHideItemIndexList() {
|
|
1361
|
-
this._updateItemVisibility(this.needHideItemIndexList, false);
|
|
1362
|
-
this.needHideItemIndexList = [];
|
|
1363
|
-
},
|
|
1364
|
-
|
|
1365
|
-
_onSlideEnd(event) {
|
|
1366
|
-
if (event && event.stopPropagation) {
|
|
1367
|
-
event.stopPropagation();
|
|
1368
|
-
}
|
|
1369
|
-
this._applyHideItemIndexList();
|
|
1370
|
-
},
|
|
1371
|
-
|
|
1372
|
-
_onContentUpdate() {
|
|
1373
|
-
this._updateItemVisibility(this.visibleItemIndexList, true);
|
|
1374
|
-
this._updateFocusItem();
|
|
1375
|
-
},
|
|
1376
|
-
|
|
1377
|
-
_updateFocusItem() {
|
|
1378
|
-
this._setZIndex(
|
|
1379
|
-
this.templateParser.FocusIdToIndex(this.focusId),
|
|
1380
|
-
this.innerData.length
|
|
1381
|
-
);
|
|
1382
|
-
},
|
|
1383
|
-
|
|
1384
|
-
_updateBlurItem() {
|
|
1385
|
-
this._setZIndex(this.templateParser.FocusIdToIndex(this.preFocusId), 0);
|
|
1386
|
-
},
|
|
1387
|
-
|
|
1388
|
-
_updateFocusByDragInfo(viewX, viewY) {
|
|
1389
|
-
let enterFocusRect = null;
|
|
1390
|
-
//模拟最小区域作为输入区域
|
|
1391
|
-
if (this.direction === VERTICAL) {
|
|
1392
|
-
enterFocusRect = {
|
|
1393
|
-
direction: EdgeDirection.top,
|
|
1394
|
-
rect: {
|
|
1395
|
-
x: this.left - viewX,
|
|
1396
|
-
y: this.top - viewY,
|
|
1397
|
-
width: 10,
|
|
1398
|
-
height: 10,
|
|
1399
|
-
},
|
|
1400
|
-
};
|
|
1401
|
-
} else {
|
|
1402
|
-
enterFocusRect = {
|
|
1403
|
-
direction: EdgeDirection.left,
|
|
1404
|
-
rect: {
|
|
1405
|
-
x: this.left - viewX,
|
|
1406
|
-
y: this.top - viewY,
|
|
1407
|
-
width: 10,
|
|
1408
|
-
height: 10,
|
|
1409
|
-
},
|
|
1410
|
-
};
|
|
1411
|
-
}
|
|
1412
|
-
this.focusId = this._calculateNearestItemByRect(
|
|
1413
|
-
this.visibleItemIndexList,
|
|
1414
|
-
enterFocusRect
|
|
1415
|
-
);
|
|
1416
|
-
},
|
|
1417
|
-
|
|
1418
|
-
_registerRootView(ele) {
|
|
1419
|
-
this.rootElement = ele;
|
|
1420
|
-
},
|
|
1421
|
-
|
|
1422
|
-
_tryReoprtVisibleEvent(msg) {
|
|
1423
|
-
if (typeof msg.viewY != "undefined" && typeof msg.viewX != "undefined") {
|
|
1424
|
-
if (this.direction === VERTICAL) {
|
|
1425
|
-
this.visibleStart = -msg.viewY;
|
|
1426
|
-
} else {
|
|
1427
|
-
this.visibleStart = -msg.viewX;
|
|
1428
|
-
}
|
|
1429
|
-
if (this.visibleStart < 0) {
|
|
1430
|
-
this.visibleStart = 0;
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
let cur_visible_start =
|
|
1435
|
-
this.visibleStart - this.visibleRangeWithPadding * 2;
|
|
1436
|
-
let cur_visible_end =
|
|
1437
|
-
this.visibleStart + this.visibleRangeWithPadding * 3 - 1;
|
|
1438
|
-
let baseItemId = this.visibleRangeSearchBaseItem
|
|
1439
|
-
? this.visibleRangeSearchBaseItem
|
|
1440
|
-
: 0;
|
|
1441
|
-
this._updateVisibleList(baseItemId, cur_visible_start, cur_visible_end);
|
|
1442
|
-
},
|
|
1443
|
-
|
|
1444
|
-
_getTouchListener() {
|
|
1445
|
-
if (!this.enableTouch) {
|
|
1446
|
-
return null;
|
|
1447
|
-
}
|
|
1448
|
-
let callback = {
|
|
1449
|
-
OnDragStart: (msg) => {
|
|
1450
|
-
// console.log("SimpleWidget Container OnDragStart:", msg);
|
|
1451
|
-
//删除焦点
|
|
1452
|
-
Promise.resolve().then(() => {
|
|
1453
|
-
this._tryReoprtVisibleEvent(msg);
|
|
1454
|
-
Forge.sRenderBridge.InstantPerformSwap();
|
|
1455
|
-
});
|
|
1456
|
-
return true;
|
|
1457
|
-
},
|
|
1458
|
-
OnMoved: (msg) => {
|
|
1459
|
-
Promise.resolve().then(() => {
|
|
1460
|
-
this._tryReoprtVisibleEvent(msg);
|
|
1461
|
-
Forge.sRenderBridge.InstantPerformSwap();
|
|
1462
|
-
});
|
|
1463
|
-
return true;
|
|
1464
|
-
},
|
|
1465
|
-
OnDragEnd: (msg) => {
|
|
1466
|
-
// console.log("SimpleWidget Container OnDragEnd:", msg);
|
|
1467
|
-
this._tryReoprtVisibleEvent(msg);
|
|
1468
|
-
this._updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
|
|
1469
|
-
this._onSlideEnd();
|
|
1470
|
-
return true;
|
|
1471
|
-
},
|
|
1472
|
-
OnFling: (msg) => {
|
|
1473
|
-
// console.log("SimpleWidget Container OnFling:", msg);
|
|
1474
|
-
this._tryReoprtVisibleEvent(msg);
|
|
1475
|
-
this._updateFocusByDragInfo(msg["viewX"], msg["viewY"]);
|
|
1476
|
-
this._onSlideEnd();
|
|
1477
|
-
return true;
|
|
1478
|
-
},
|
|
1479
|
-
OnRelease: () => {
|
|
1480
|
-
// console.log("SimpleWidget Container OnRelease:", msg);
|
|
1481
|
-
return true;
|
|
1482
|
-
},
|
|
1483
|
-
};
|
|
1484
|
-
return callback;
|
|
1485
|
-
},
|
|
1486
|
-
_getFocusBlockActions() {
|
|
1487
|
-
return {
|
|
1488
|
-
onFocus: this._onFocus,
|
|
1489
|
-
onBlur: this._onBlur,
|
|
1490
|
-
onKeyDown: this.onKeyDown,
|
|
1491
|
-
};
|
|
1492
|
-
},
|
|
1493
|
-
},
|
|
1494
|
-
created() {
|
|
1495
|
-
if (this.dispatcher) {
|
|
1496
|
-
this.dispatcher.registerComponent(this);
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
let template_parser = _getTemplateParser(
|
|
1500
|
-
this.width,
|
|
1501
|
-
this.height,
|
|
1502
|
-
this.direction,
|
|
1503
|
-
this.padding,
|
|
1504
|
-
this.supportHistoryPath,
|
|
1505
|
-
this.layoutType
|
|
1506
|
-
);
|
|
1507
|
-
if (this.provideData) {
|
|
1508
|
-
this.dataList = this.provideData();
|
|
1509
|
-
} else if (this.data) {
|
|
1510
|
-
this.dataList = this.data;
|
|
1511
|
-
}
|
|
1512
|
-
_AddTemplateItem(this.dataList, this.measures, template_parser, 0);
|
|
1513
|
-
this.templateParser = template_parser;
|
|
1514
|
-
let template_list = this.templateParser.GetTemplate().List;
|
|
1515
|
-
let last_item = template_list[template_list.length - 1];
|
|
1516
|
-
this.touchListener = this._getTouchListener();
|
|
1517
|
-
this.innerPadding = _getPadding(this.padding);
|
|
1518
|
-
this.touchContainerW =
|
|
1519
|
-
this.direction === VERTICAL
|
|
1520
|
-
? this.width
|
|
1521
|
-
: last_item.xPos + last_item.width;
|
|
1522
|
-
this.touchContainerH =
|
|
1523
|
-
this.direction === VERTICAL
|
|
1524
|
-
? last_item.yPos + last_item.height
|
|
1525
|
-
: this.height;
|
|
1526
|
-
this.slidePile = new Forge.RectArea(
|
|
1527
|
-
0,
|
|
1528
|
-
0,
|
|
1529
|
-
this.width - this.innerPadding.left - this.innerPadding.right,
|
|
1530
|
-
this.height - this.innerPadding.top - this.innerPadding.bottom
|
|
1531
|
-
);
|
|
1532
|
-
this.dragDirection =
|
|
1533
|
-
this.direction === VERTICAL
|
|
1534
|
-
? Forge.DragSetting.DIRECTION_VERTICAL
|
|
1535
|
-
: Forge.DragSetting.DIRECTION_HORIZONTAL;
|
|
1536
|
-
this.innerData = template_list.map((item, index) => {
|
|
1537
|
-
return {
|
|
1538
|
-
data: item,
|
|
1539
|
-
index: index,
|
|
1540
|
-
controller: reactive({
|
|
1541
|
-
visible: false,
|
|
1542
|
-
zIndex: 0,
|
|
1543
|
-
}),
|
|
1544
|
-
mounted: false,
|
|
1545
|
-
itemRef: null,
|
|
1546
|
-
itemHandler: {},
|
|
1547
|
-
itemConfig: this.itemConfig?.(item.data),
|
|
1548
|
-
};
|
|
1549
|
-
});
|
|
1550
|
-
let visible_base_index = 0;
|
|
1551
|
-
let init_focus_id = 0;
|
|
1552
|
-
let cur_visible_start = 0;
|
|
1553
|
-
this.visibleRange =
|
|
1554
|
-
this.direction === VERTICAL
|
|
1555
|
-
? this.height - this.innerPadding.top - this.innerPadding.bottom
|
|
1556
|
-
: this.width - this.innerPadding.left - this.innerPadding.right;
|
|
1557
|
-
this.visibleRangeWithPadding =
|
|
1558
|
-
this.direction === VERTICAL ? this.height : this.width;
|
|
1559
|
-
if (this.initFocusId) {
|
|
1560
|
-
init_focus_id = this.initFocusId;
|
|
1561
|
-
visible_base_index = this.templateParser.FocusIdToIndex(init_focus_id);
|
|
1562
|
-
cur_visible_start = this._calculateVisibleStart(
|
|
1563
|
-
this.templateParser.GetItemById(this.initFocusId),
|
|
1564
|
-
1
|
|
1565
|
-
);
|
|
1566
|
-
}
|
|
1567
|
-
|
|
1568
|
-
this.visibleItemIndexList = this._getVisibleItemIndexList(
|
|
1569
|
-
visible_base_index,
|
|
1570
|
-
cur_visible_start,
|
|
1571
|
-
cur_visible_start + this.visibleRange - 1
|
|
1572
|
-
);
|
|
1573
|
-
this.focusId = init_focus_id;
|
|
1574
|
-
this.visibleStart = cur_visible_start;
|
|
1575
|
-
},
|
|
1576
|
-
updated() {},
|
|
1577
|
-
mounted() {
|
|
1578
|
-
if (this.visibleStart) {
|
|
1579
|
-
this._slideTo(this.visibleStart, null);
|
|
1580
|
-
}
|
|
1581
|
-
},
|
|
1582
|
-
beforeUnmount() {
|
|
1583
|
-
if (this.dispatcher) {
|
|
1584
|
-
this.dispatcher.unregisterComponent();
|
|
1585
|
-
}
|
|
1586
|
-
},
|
|
1587
|
-
};
|
|
1588
|
-
|
|
1589
|
-
export default SimpleWidget;
|
|
1590
|
-
</script>
|
|
1591
|
-
|
|
1592
|
-
<template>
|
|
1593
|
-
<jsv-focus-block :name="name" :onAction="_getFocusBlockActions()">
|
|
1594
|
-
<div
|
|
1595
|
-
:style="{
|
|
1596
|
-
left: left,
|
|
1597
|
-
top: top,
|
|
1598
|
-
width: width,
|
|
1599
|
-
height: height,
|
|
1600
|
-
overflow: 'hidden',
|
|
1601
|
-
}"
|
|
1602
|
-
>
|
|
1603
|
-
<root-view
|
|
1604
|
-
:token="token"
|
|
1605
|
-
:x="innerPadding.left"
|
|
1606
|
-
:y="innerPadding.top"
|
|
1607
|
-
:width="touchContainerW"
|
|
1608
|
-
:height="touchContainerH"
|
|
1609
|
-
:flingPageWidth="flingPageWidth"
|
|
1610
|
-
:flingPageEdge="flingPageEdge"
|
|
1611
|
-
:slidePile="slidePile"
|
|
1612
|
-
:direction="dragDirection"
|
|
1613
|
-
:touchListener="touchListener"
|
|
1614
|
-
:enableTouch="enableTouch"
|
|
1615
|
-
:loadAll="loadAll"
|
|
1616
|
-
:register="_registerRootView"
|
|
1617
|
-
:data="innerData"
|
|
1618
|
-
:onLoad="_onContentUpdate"
|
|
1619
|
-
:onItemEdge="_onFocusableItemEdge"
|
|
1620
|
-
:widgetHandler="_injectHandler()"
|
|
1621
|
-
:enableItemRenderBreak="enableItemRenderBreak"
|
|
1622
|
-
>
|
|
1623
|
-
<template v-slot:renderItem="slotProps">
|
|
1624
|
-
<slot name="renderItem" v-bind="slotProps"></slot>
|
|
1625
|
-
</template>
|
|
1626
|
-
</root-view>
|
|
1627
|
-
</div>
|
|
1628
|
-
</jsv-focus-block>
|
|
1629
|
-
</template>
|