@shijiu/jsview-vue-samples 2.2.35 → 2.2.128
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/BakeViewDemo/AnimatePic.vue +93 -0
- package/BakeViewDemo/App.vue +109 -0
- package/ClickDivDemo/App.vue +150 -0
- package/DemoHomepage/components/Dialog.vue +37 -11
- package/DemoHomepage/components/TabFrame.vue +8 -1
- package/DemoHomepage/router.js +61 -26
- package/DemoHomepage/views/Homepage.vue +30 -13
- package/FocusMoveStyle/App.vue +21 -4
- package/FocusMoveStyle/FoldableItem.vue +39 -12
- package/FreeMoveChildAttract/App.vue +105 -0
- package/FreeMoveLink/App.vue +55 -0
- package/FreeMoveResize/App.vue +102 -0
- package/LongText/App.vue +1 -3
- package/LongText/LongTextScroll.vue +78 -33
- package/LongTextLatex/App.vue +93 -0
- package/LongTextLatex/Button.vue +50 -0
- package/LongTextLatex/ButtonItem.vue +44 -0
- package/LongTextLatex/LongTextScroll.vue +189 -0
- package/LongTextLatex/Scroll.vue +14 -0
- package/MetroWidgetDemos/MassiveItems/App.vue +87 -0
- package/MetroWidgetDemos/MassiveItems/ContentItem.vue +388 -0
- package/MetroWidgetDemos/MassiveItems/Item.vue +203 -0
- package/MetroWidgetDemos/MassiveItems/WidgetItem.vue +101 -0
- package/MetroWidgetDemos/MassiveItems/data.js +17 -0
- package/MetroWidgetDemos/PingPong/AppPage.vue +19 -9
- package/MetroWidgetDemos/routeList.js +6 -0
- package/ScrollBoxTest/App.vue +160 -0
- package/TestNativeSharedView/App.vue +166 -73
- package/TextureAnimation/App2.vue +17 -6
- package/TombSweepingDayTest/Raining/RainScene.vue +36 -24
- package/package.json +1 -1
package/FocusMoveStyle/App.vue
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
getTextWidth,
|
|
6
6
|
FixPositionSlide,
|
|
7
7
|
ListWidget,
|
|
8
|
+
SeamlessSlide,
|
|
9
|
+
METRO_WIDGET_CONST
|
|
8
10
|
} from "jsview";
|
|
9
11
|
import FoldableItem from "./FoldableItem.vue";
|
|
10
12
|
import redCircle from "./assets/redCircle.png";
|
|
@@ -17,20 +19,33 @@ const randomColor = () => {
|
|
|
17
19
|
"#" + new Array(6 - randomColor.length).fill("0").join("") + randomColor
|
|
18
20
|
);
|
|
19
21
|
};
|
|
20
|
-
const slideType = new FixPositionSlide();
|
|
22
|
+
// const slideType = new FixPositionSlide();
|
|
23
|
+
const slideType = new SeamlessSlide({ startPercent: .5, endPercent: .5});
|
|
24
|
+
|
|
21
25
|
const focusHub = useFocusHub();
|
|
22
26
|
|
|
23
27
|
const creepFocus = ref(null);
|
|
24
28
|
const showFocus = ref(true);
|
|
25
29
|
let currentFocusRect = {};
|
|
30
|
+
let expandItemCount = 0;
|
|
26
31
|
const focusFrameController = {
|
|
27
|
-
focusVisible: (visible) => {
|
|
28
|
-
showFocus.value = visible ? true : false;
|
|
29
|
-
},
|
|
30
32
|
onFocusChange: (rect, focusIndex, doAnim) => {
|
|
31
33
|
creepFocus.value?.changeRect(rect, doAnim);
|
|
32
34
|
currentFocusRect = rect;
|
|
33
35
|
},
|
|
36
|
+
onItemSizeChange: (ifExpand) => {
|
|
37
|
+
if (ifExpand) {
|
|
38
|
+
expandItemCount++;
|
|
39
|
+
} else {
|
|
40
|
+
expandItemCount--;
|
|
41
|
+
}
|
|
42
|
+
if (expandItemCount <= 0) {
|
|
43
|
+
showFocus.value = true;
|
|
44
|
+
expandItemCount = 0;
|
|
45
|
+
} else {
|
|
46
|
+
showFocus.value = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
34
49
|
};
|
|
35
50
|
provide("focusFrameController", focusFrameController);
|
|
36
51
|
|
|
@@ -85,6 +100,7 @@ for (let i = 0; i < 12; ++i) {
|
|
|
85
100
|
content: contentData[i],
|
|
86
101
|
marginRight: 10,
|
|
87
102
|
name: "item_" + i, // focus name
|
|
103
|
+
expandWhenFocus: contentData[i] == "云影院" || contentData[i] == "综艺",
|
|
88
104
|
childTab: {
|
|
89
105
|
width: totalWidth, //4个item + 3个gap
|
|
90
106
|
list: childList,
|
|
@@ -110,6 +126,7 @@ const measures = (item) => {
|
|
|
110
126
|
width: item.width,
|
|
111
127
|
height: item.height,
|
|
112
128
|
marginRight: item.marginRight,
|
|
129
|
+
itemSlide: item.expandWhenFocus ? METRO_WIDGET_CONST.ITEM_SLIDE.DISABLE : METRO_WIDGET_CONST.ITEM_SLIDE.ACT_ITEM_FOCUS
|
|
113
130
|
};
|
|
114
131
|
};
|
|
115
132
|
|
|
@@ -30,6 +30,12 @@ const width = ref(props.data.width);
|
|
|
30
30
|
const widgetRef = shallowRef(null);
|
|
31
31
|
const widgetLeft = ref(0);
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* 关键代码
|
|
35
|
+
* 焦点快速往复移动时, 复用一个子widget会导致slideToDiv焦点位置的偏移, 因此每次缩放时都创建新的widget
|
|
36
|
+
*/
|
|
37
|
+
const changeToken = ref(0);
|
|
38
|
+
|
|
33
39
|
const focusRectController = {
|
|
34
40
|
onFocusChange: (rect) => {
|
|
35
41
|
creepFocus.value?.changeRect(rect);
|
|
@@ -51,15 +57,17 @@ const measures = (data) => {
|
|
|
51
57
|
|
|
52
58
|
// 注册回调
|
|
53
59
|
const onFocus = () => {
|
|
54
|
-
focusFrameController.focusVisible(true);
|
|
55
60
|
focused.value = true;
|
|
56
61
|
folded.value = true;
|
|
62
|
+
if (props.data.expandWhenFocus) {
|
|
63
|
+
expand();
|
|
64
|
+
}
|
|
57
65
|
};
|
|
58
66
|
|
|
59
67
|
const foldSubTab = () => {
|
|
60
68
|
if (!folded.value) {
|
|
61
69
|
if (width.value == props.data.childTab.width) {
|
|
62
|
-
|
|
70
|
+
changeToken.value++;
|
|
63
71
|
width.value = props.data.width;
|
|
64
72
|
let index =
|
|
65
73
|
widgetRef.value?.getCurrentFocusIndex() ?? props.data.initFocus;
|
|
@@ -86,13 +94,16 @@ const foldSubTab = () => {
|
|
|
86
94
|
},
|
|
87
95
|
{
|
|
88
96
|
duration: DURATION,
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
anchor: getAnchor(widgetRef.value.getCurrentFocusIndex()),
|
|
98
|
+
onEnd: (cancel) => {
|
|
99
|
+
if (!(focused.value && props.data.expandWhenFocus)) {
|
|
100
|
+
folded.value = true;
|
|
101
|
+
}
|
|
102
|
+
console.log("fold anim end.", cancel);
|
|
93
103
|
},
|
|
94
104
|
}
|
|
95
105
|
);
|
|
106
|
+
focusFrameController.onItemSizeChange(false);
|
|
96
107
|
}
|
|
97
108
|
focusHub.returnFocusToParent();
|
|
98
109
|
}
|
|
@@ -166,11 +177,16 @@ const getAnchor = (index) => {
|
|
|
166
177
|
return anchor;
|
|
167
178
|
};
|
|
168
179
|
|
|
169
|
-
const
|
|
180
|
+
const expand = () => {
|
|
170
181
|
if (folded.value) {
|
|
182
|
+
changeToken.value++;
|
|
183
|
+
|
|
171
184
|
itemKeepScale.value = false;
|
|
172
185
|
showFocus.value = true;
|
|
173
186
|
widgetLeft.value = 0;
|
|
187
|
+
/**
|
|
188
|
+
* 动画未结束时, widgetLeft不为0, 此时又获焦那一帧同时设置的widgetLeft值未同步到div, slideToDiv获取的就不是展开后item的正确位置
|
|
189
|
+
*/
|
|
174
190
|
folded.value = false;
|
|
175
191
|
width.value = props.data.childTab.width;
|
|
176
192
|
//为了居中而计算锚点
|
|
@@ -195,8 +211,16 @@ const onClick = () => {
|
|
|
195
211
|
}
|
|
196
212
|
);
|
|
197
213
|
|
|
198
|
-
focusHub.setFocus(props.data.name);
|
|
199
|
-
focusFrameController.
|
|
214
|
+
focusHub.setFocus(props.data.name + changeToken.value);
|
|
215
|
+
focusFrameController.onItemSizeChange(true);
|
|
216
|
+
|
|
217
|
+
// focusFrameController.focusVisible(false);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
const onClick = () => {
|
|
222
|
+
if (!props.data.expandWhenFocus) {
|
|
223
|
+
expand();
|
|
200
224
|
}
|
|
201
225
|
};
|
|
202
226
|
props.onAction.register("onFocus", onFocus);
|
|
@@ -205,8 +229,10 @@ props.onAction.register("onClick", onClick);
|
|
|
205
229
|
|
|
206
230
|
const onKeyDown = (ev) => {
|
|
207
231
|
if (ev.keyCode === 10000 || ev.keyCode === 8 || ev.keyCode === 27) {
|
|
208
|
-
|
|
209
|
-
|
|
232
|
+
if (!props.data.expandWhenFocus) {
|
|
233
|
+
itemKeepScale.value = true;
|
|
234
|
+
foldSubTab();
|
|
235
|
+
}
|
|
210
236
|
return true;
|
|
211
237
|
}
|
|
212
238
|
return false;
|
|
@@ -251,8 +277,9 @@ const onKeyDown = (ev) => {
|
|
|
251
277
|
}"
|
|
252
278
|
>
|
|
253
279
|
<list-widget
|
|
280
|
+
:key="changeToken"
|
|
254
281
|
ref="widgetRef"
|
|
255
|
-
:name="data.name"
|
|
282
|
+
:name="data.name + changeToken"
|
|
256
283
|
:width="data.childTab.width"
|
|
257
284
|
:height="data.height"
|
|
258
285
|
:provideData="provideData"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<jsv-focus-block autoFocus :onKeyDown="procKeyDown">
|
|
3
|
+
<div class="bgStyle">
|
|
4
|
+
<jsv-free-move-div
|
|
5
|
+
ref="mActRef1"
|
|
6
|
+
:style="{
|
|
7
|
+
top: 200,
|
|
8
|
+
left: 400,
|
|
9
|
+
width: 500,
|
|
10
|
+
height: 350,
|
|
11
|
+
backgroundColor: '#00F00F',
|
|
12
|
+
}"
|
|
13
|
+
>
|
|
14
|
+
<jsv-free-move-div
|
|
15
|
+
ref="mActRef2"
|
|
16
|
+
:style="{
|
|
17
|
+
width: 50,
|
|
18
|
+
height: 50,
|
|
19
|
+
backgroundColor: '#FF0000',
|
|
20
|
+
}"
|
|
21
|
+
/>
|
|
22
|
+
</jsv-free-move-div>
|
|
23
|
+
</div>
|
|
24
|
+
</jsv-focus-block>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
import { JsvFreeMoveDiv, ForgeConst } from "jsview";
|
|
29
|
+
import { shallowRef, onMounted, watch } from "vue";
|
|
30
|
+
import { useRouter } from "vue-router";
|
|
31
|
+
|
|
32
|
+
const router = useRouter();
|
|
33
|
+
const procKeyDown = (ev) => {
|
|
34
|
+
// 8:Backspace, 27:Escape, 10000:盒子返回键
|
|
35
|
+
if (ev.keyCode == 8 || ev.keyCode == 27 || ev.keyCode == 10000) {
|
|
36
|
+
router.go(-1); // 有router时,是从DemoHomepage进入,回退
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return false;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const mActRef1 = shallowRef(null);
|
|
44
|
+
const mActRef2 = shallowRef(null);
|
|
45
|
+
let mActControl1 = null;
|
|
46
|
+
let mActControl2 = null;
|
|
47
|
+
|
|
48
|
+
onMounted(() => {
|
|
49
|
+
mActControl1 = mActRef1.value.control;
|
|
50
|
+
mActControl2 = mActRef2.value.control;
|
|
51
|
+
|
|
52
|
+
mActControl1
|
|
53
|
+
.getBindedView()
|
|
54
|
+
.DragEnables?.(ForgeConst.DragFlags.TOUCH_RECV_FIRST_START);
|
|
55
|
+
mActControl2
|
|
56
|
+
.getBindedView()
|
|
57
|
+
.DragEnables?.(
|
|
58
|
+
ForgeConst.DragFlags.TOUCH_RECV_MOVE_BIT |
|
|
59
|
+
ForgeConst.DragFlags.TOUCH_RECV_FIRST_START |
|
|
60
|
+
ForgeConst.DragFlags.TOUCH_RECV_LAST_END
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
mActControl1.run([mActControl1.state().setTouchAttractChild(mActControl2)]);
|
|
64
|
+
|
|
65
|
+
console.log(`OnMoved starting onMovement`);
|
|
66
|
+
mActControl2.run([
|
|
67
|
+
mActControl2
|
|
68
|
+
.condition(0, true) // 通过第二个参数设置回调为多次触发
|
|
69
|
+
.onMovement(12) // 设置x或y移动超过12时才触发回调,以此减少回调的频次,规避js的性能影响
|
|
70
|
+
.then([
|
|
71
|
+
(pointInfo) => {
|
|
72
|
+
console.log(`OnMoved x=${pointInfo.xPos} y=${pointInfo.yPos}`);
|
|
73
|
+
},
|
|
74
|
+
]),
|
|
75
|
+
]);
|
|
76
|
+
window.DebugControl = mActControl1;
|
|
77
|
+
});
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
81
|
+
<style scoped>
|
|
82
|
+
.bgStyle {
|
|
83
|
+
width: 1280;
|
|
84
|
+
height: 720;
|
|
85
|
+
background-color: #007788;
|
|
86
|
+
}
|
|
87
|
+
.box {
|
|
88
|
+
width: 150;
|
|
89
|
+
height: 150;
|
|
90
|
+
font-size: 30;
|
|
91
|
+
color: #000000;
|
|
92
|
+
background-color: #3fb524;
|
|
93
|
+
}
|
|
94
|
+
.tip {
|
|
95
|
+
width: 300;
|
|
96
|
+
height: 30;
|
|
97
|
+
line-height: 28;
|
|
98
|
+
font-size: 28;
|
|
99
|
+
left: 980;
|
|
100
|
+
top: 680;
|
|
101
|
+
text-align: center;
|
|
102
|
+
font-weight: bold;
|
|
103
|
+
color: #ffffff;
|
|
104
|
+
}
|
|
105
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref, onMounted } from "vue";
|
|
3
|
+
import { FreeMoveFunc, ForgeConst } from "jsview";
|
|
4
|
+
|
|
5
|
+
const div1 = ref();
|
|
6
|
+
const div2 = ref();
|
|
7
|
+
|
|
8
|
+
const control1 = new FreeMoveFunc.ActControlDebug();
|
|
9
|
+
const control2 = new FreeMoveFunc.ActControlDebug();
|
|
10
|
+
|
|
11
|
+
onMounted(() => {
|
|
12
|
+
const linkNexusId = FreeMoveFunc.newNexus();
|
|
13
|
+
|
|
14
|
+
let div1View = div1.value.jsvGetProxyView();
|
|
15
|
+
control1.bindForgeView(div1View, true);
|
|
16
|
+
div1View.DragEnables?.(ForgeConst.DragFlags.TOUCH_RECV_MOVE_BIT); // 只激活drag
|
|
17
|
+
|
|
18
|
+
control1.run([
|
|
19
|
+
control1.state().startMovementSync(linkNexusId, -200, -200, 200, 200, 0b11),
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
let div2View = div2.value.jsvGetProxyView();
|
|
23
|
+
control2.bindForgeView(div2View, true);
|
|
24
|
+
div2View.DragEnables?.(ForgeConst.DragFlags.TOUCH_RECV_MOVE_BIT); // 只激活drag
|
|
25
|
+
control2.run([
|
|
26
|
+
control2
|
|
27
|
+
.condition()
|
|
28
|
+
.movementSync(linkNexusId)
|
|
29
|
+
.then([control2.action().ackMovementSync(-100, -100, 100, 100, 0b11, 1)]),
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<template>
|
|
35
|
+
<div
|
|
36
|
+
ref="div1"
|
|
37
|
+
:style="{
|
|
38
|
+
left: 50,
|
|
39
|
+
top: 50,
|
|
40
|
+
width: 300,
|
|
41
|
+
height: 300,
|
|
42
|
+
backgroundColor: '#FF0000',
|
|
43
|
+
}"
|
|
44
|
+
></div>
|
|
45
|
+
<div
|
|
46
|
+
ref="div2"
|
|
47
|
+
:style="{
|
|
48
|
+
left: 550,
|
|
49
|
+
top: 50,
|
|
50
|
+
width: 100,
|
|
51
|
+
height: 100,
|
|
52
|
+
backgroundColor: '#00FF00',
|
|
53
|
+
}"
|
|
54
|
+
></div>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<jsv-focus-block autoFocus :onKeyDown="procKeyDown">
|
|
3
|
+
<div class="bgStyle">
|
|
4
|
+
<jsv-free-move-div
|
|
5
|
+
ref="mActRef1"
|
|
6
|
+
:style="{
|
|
7
|
+
top: 100,
|
|
8
|
+
left: 200,
|
|
9
|
+
width: 500,
|
|
10
|
+
height: 350,
|
|
11
|
+
backgroundColor: '#00F00F',
|
|
12
|
+
overflow: 'hidden',
|
|
13
|
+
}"
|
|
14
|
+
:sizeMode="true"
|
|
15
|
+
>
|
|
16
|
+
<div
|
|
17
|
+
:style="{
|
|
18
|
+
width: 400,
|
|
19
|
+
height: 400,
|
|
20
|
+
fontSize: 50,
|
|
21
|
+
backgroundColor: '#FF0000',
|
|
22
|
+
}"
|
|
23
|
+
>
|
|
24
|
+
{{ "测试文字" }}
|
|
25
|
+
</div>
|
|
26
|
+
</jsv-free-move-div>
|
|
27
|
+
</div>
|
|
28
|
+
</jsv-focus-block>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup>
|
|
32
|
+
import { JsvFreeMoveDiv, FreeMoveDef } from "jsview";
|
|
33
|
+
import { shallowRef, onMounted, watch } from "vue";
|
|
34
|
+
import { useRouter } from "vue-router";
|
|
35
|
+
|
|
36
|
+
const router = useRouter();
|
|
37
|
+
const procKeyDown = (ev) => {
|
|
38
|
+
// 8:Backspace, 27:Escape, 10000:盒子返回键
|
|
39
|
+
if (ev.keyCode == 8 || ev.keyCode == 27 || ev.keyCode == 10000) {
|
|
40
|
+
router.go(-1); // 有router时,是从DemoHomepage进入,回退
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const mActRef1 = shallowRef(null);
|
|
48
|
+
let mActControl1 = null;
|
|
49
|
+
|
|
50
|
+
onMounted(() => {
|
|
51
|
+
mActControl1 = mActRef1.value.control;
|
|
52
|
+
window.DebugControl = mActControl1;
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// 预设动画控制
|
|
56
|
+
function MoveToRightBottom() {
|
|
57
|
+
mActControl1.run([
|
|
58
|
+
mActControl1.state().clearAllConditions(),
|
|
59
|
+
mActControl1.action().moveTo(600, 500, undefined, 3),
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function MoveToLeftTop() {
|
|
64
|
+
mActControl1.run([
|
|
65
|
+
mActControl1.state().clearAllConditions(),
|
|
66
|
+
mActControl1.action().moveTo(100, 200, 3, undefined),
|
|
67
|
+
]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 暴露给devtool去使用
|
|
71
|
+
window.DebugFreeMove = {
|
|
72
|
+
MoveToRightBottom,
|
|
73
|
+
MoveToLeftTop,
|
|
74
|
+
};
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
78
|
+
<style scoped>
|
|
79
|
+
.bgStyle {
|
|
80
|
+
width: 1280;
|
|
81
|
+
height: 720;
|
|
82
|
+
background-color: #007788;
|
|
83
|
+
}
|
|
84
|
+
.box {
|
|
85
|
+
width: 150;
|
|
86
|
+
height: 150;
|
|
87
|
+
font-size: 30;
|
|
88
|
+
color: #000000;
|
|
89
|
+
background-color: #3fb524;
|
|
90
|
+
}
|
|
91
|
+
.tip {
|
|
92
|
+
width: 300;
|
|
93
|
+
height: 30;
|
|
94
|
+
line-height: 28;
|
|
95
|
+
font-size: 28;
|
|
96
|
+
left: 980;
|
|
97
|
+
top: 680;
|
|
98
|
+
text-align: center;
|
|
99
|
+
font-weight: bold;
|
|
100
|
+
color: #ffffff;
|
|
101
|
+
}
|
|
102
|
+
</style>
|
package/LongText/App.vue
CHANGED
|
@@ -62,7 +62,7 @@ onMounted(() => {
|
|
|
62
62
|
backgroundColor: 'rgba(27,38,151,0.8)',
|
|
63
63
|
}"
|
|
64
64
|
>
|
|
65
|
-
可展示篇幅超过一屏的文字
|
|
65
|
+
可展示篇幅超过一屏的文字(支持触控拖拽)
|
|
66
66
|
</div>
|
|
67
67
|
<div :style="{ left: 140, top: 100 }">
|
|
68
68
|
<LongTextScroll
|
|
@@ -89,5 +89,3 @@ onMounted(() => {
|
|
|
89
89
|
</div>
|
|
90
90
|
</jsv-focus-block>
|
|
91
91
|
</template>
|
|
92
|
-
|
|
93
|
-
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import Scroll from "./Scroll.vue";
|
|
3
|
-
import { ref, onMounted } from "vue";
|
|
4
|
-
import {
|
|
3
|
+
import { ref, onMounted, shallowRef } from "vue";
|
|
4
|
+
import {
|
|
5
|
+
useFocusHub,
|
|
6
|
+
JsvFlexDiv,
|
|
7
|
+
VERTICAL,
|
|
8
|
+
JsvScrollBox,
|
|
9
|
+
ScrollStyle,
|
|
10
|
+
} from "jsview";
|
|
5
11
|
|
|
6
12
|
const props = defineProps({
|
|
7
13
|
step: Number,
|
|
@@ -16,11 +22,14 @@ const focusHub = useFocusHub();
|
|
|
16
22
|
const rootRef = ref(null);
|
|
17
23
|
const element = ref(null);
|
|
18
24
|
const scrollY = ref(0);
|
|
19
|
-
const textY = ref(0);
|
|
20
25
|
|
|
26
|
+
let textY = 0;
|
|
27
|
+
let rScrollHeight = shallowRef(0);
|
|
28
|
+
let rJsvScrollBox = shallowRef(null);
|
|
21
29
|
let textTotalHeight = 0;
|
|
22
30
|
const onTextSizeReady = (width, height) => {
|
|
23
31
|
textTotalHeight = height;
|
|
32
|
+
rScrollHeight.value = height;
|
|
24
33
|
console.log(`textSize ready width=${width} height=${height}`);
|
|
25
34
|
};
|
|
26
35
|
|
|
@@ -30,32 +39,25 @@ const onAction = {
|
|
|
30
39
|
// let keyUsed = true;
|
|
31
40
|
if (valid) {
|
|
32
41
|
// 测试用比对代码,正式场景不需要
|
|
33
|
-
if (textTotalHeight != element.value.clientHeight) {
|
|
34
|
-
|
|
35
|
-
}
|
|
42
|
+
// if (textTotalHeight != element.value.clientHeight) {
|
|
43
|
+
// console.error("Error: height miss match");
|
|
44
|
+
// }
|
|
36
45
|
|
|
37
46
|
let text_y;
|
|
38
47
|
switch (ev.keyCode) {
|
|
39
48
|
case 38:
|
|
40
|
-
if (textY
|
|
41
|
-
text_y =
|
|
42
|
-
|
|
43
|
-
(textY.value = text_y),
|
|
44
|
-
(scrollY.value =
|
|
45
|
-
(-text_y / (textTotalHeight - props.style.height)) *
|
|
46
|
-
(props.scrollStyle.height - props.scrollBlockStyle.height));
|
|
49
|
+
if (textY !== 0) {
|
|
50
|
+
text_y = textY + props.step >= 0 ? 0 : textY + props.step;
|
|
51
|
+
SlideToYByKey(text_y);
|
|
47
52
|
}
|
|
48
53
|
break;
|
|
49
54
|
case 40:
|
|
50
|
-
if (textY
|
|
55
|
+
if (textY !== props.style.height - textTotalHeight) {
|
|
51
56
|
text_y =
|
|
52
|
-
textY
|
|
57
|
+
textY - props.step <= props.style.height - textTotalHeight
|
|
53
58
|
? props.style.height - textTotalHeight
|
|
54
|
-
: textY
|
|
55
|
-
(
|
|
56
|
-
(scrollY.value =
|
|
57
|
-
(-text_y / (textTotalHeight - props.style.height)) *
|
|
58
|
-
(props.scrollStyle.height - props.scrollBlockStyle.height));
|
|
59
|
+
: textY - props.step;
|
|
60
|
+
SlideToYByKey(text_y);
|
|
59
61
|
} else {
|
|
60
62
|
focusHub.setFocus("button");
|
|
61
63
|
}
|
|
@@ -71,25 +73,66 @@ const onAction = {
|
|
|
71
73
|
},
|
|
72
74
|
};
|
|
73
75
|
|
|
76
|
+
function SlideToYByKey(newY) {
|
|
77
|
+
// 使用新的Y来调整ScrollBox的显示位置
|
|
78
|
+
rJsvScrollBox.value.updatePercent(
|
|
79
|
+
-newY / (textTotalHeight - props.style.height)
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// 记录新的Y, 并更新右边的进度条
|
|
83
|
+
UpdateRightBar(newY);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function UpdateRightBar(newY) {
|
|
87
|
+
textY = newY;
|
|
88
|
+
|
|
89
|
+
scrollY.value =
|
|
90
|
+
(-newY / (textTotalHeight - props.style.height)) *
|
|
91
|
+
(props.scrollStyle.height - props.scrollBlockStyle.height);
|
|
92
|
+
}
|
|
93
|
+
|
|
74
94
|
onMounted(() => {
|
|
75
95
|
rootRef.value.requestFocus();
|
|
96
|
+
rJsvScrollBox.value.setSensor((percent, x, y) => {
|
|
97
|
+
let newY = Math.floor(y);
|
|
98
|
+
console.log(
|
|
99
|
+
`onProgress dragged percent=${percent} \
|
|
100
|
+
x=${Math.floor(x)} \
|
|
101
|
+
y=${newY}`
|
|
102
|
+
);
|
|
103
|
+
UpdateRightBar(newY);
|
|
104
|
+
}, 15);
|
|
76
105
|
});
|
|
77
106
|
</script>
|
|
78
107
|
|
|
79
108
|
<template>
|
|
80
109
|
<jsv-focus-block ref="rootRef" name="longTextScroll" :onAction="onAction">
|
|
81
110
|
<div :style="{ overflow: 'hidden', ...style }">
|
|
82
|
-
<jsv-
|
|
83
|
-
|
|
84
|
-
:
|
|
111
|
+
<jsv-scroll-box
|
|
112
|
+
ref="rJsvScrollBox"
|
|
113
|
+
:style="{
|
|
114
|
+
width: style.width,
|
|
115
|
+
height: style.height,
|
|
116
|
+
}"
|
|
117
|
+
:direction="VERTICAL"
|
|
118
|
+
:mode="ScrollStyle.DrawerMode"
|
|
119
|
+
:enableFling="true"
|
|
120
|
+
:sliderSize="{
|
|
121
|
+
height: rScrollHeight == 0 ? style.height : rScrollHeight,
|
|
122
|
+
}"
|
|
85
123
|
>
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
124
|
+
<template #SliderBox>
|
|
125
|
+
<jsv-flex-div
|
|
126
|
+
:style="{ width: style.width }"
|
|
127
|
+
:onSized="onTextSizeReady"
|
|
128
|
+
>
|
|
129
|
+
<div
|
|
130
|
+
ref="element"
|
|
131
|
+
data-jsv-perf-loadtex="auto"
|
|
132
|
+
:style="{ width: style.width, ...textStyle }"
|
|
133
|
+
>
|
|
134
|
+
{{
|
|
135
|
+
"疾风引擎JsView用户服务协议及隐私权保护政策\n\
|
|
93
136
|
\n\
|
|
94
137
|
\n\
|
|
95
138
|
特别提示:\n\
|
|
@@ -186,9 +229,11 @@ onMounted(() => {
|
|
|
186
229
|
本协议条款的效力和解释均适用中华人民共和国的法律,如有条款与中华人民共和国法律相抵触,则该部分条款应按法律规定重新解释,部分条款的无效或重新解释不影响其他条款的法律效力。\n\
|
|
187
230
|
本协议以及疾风引擎JsView制度将统一构成您与运营方之间的完整协议,两者约定不一致的,以文本制定时间较晚者为准。\n\
|
|
188
231
|
本协议签订地为中华人民共和国上海市,若您在使用疾风引擎JsView过程中产生任何纠纷或争议,您同意将该纠纷或者争议提交本协议签订地人民法院管辖。本协议条款无论何种原因部分无效或不可执行,其他条款仍应继续有效,对双方具有约束力。"
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
232
|
+
}}
|
|
233
|
+
</div>
|
|
234
|
+
</jsv-flex-div>
|
|
235
|
+
</template>
|
|
236
|
+
</jsv-scroll-box>
|
|
192
237
|
</div>
|
|
193
238
|
<Scroll
|
|
194
239
|
:top="scrollY"
|