@shijiu/jsview-vue-samples 2.3.0 → 2.3.728-alpha.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/ABImageAlt/App.vue +114 -0
- package/ABImageAlt/Item.vue +133 -0
- package/{MetroWidgetDemos/SkeletonDiagram/assets/imageList.json → ABImageAlt/assets/imageList.js} +9 -1
- package/ABImageAlt/data.js +17 -0
- package/AI_Check_Rules.txt +5 -0
- package/AnimPicture/App.vue +20 -10
- package/ApicSwitch/App.vue +90 -0
- package/ApicSwitch/TabItem.vue +65 -0
- package/ApicSwitch/WebpShow.vue +24 -0
- package/ApicSwitch/data.js +50 -0
- package/Basic/AI_skills_update.md +1 -0
- package/Basic/components/div/ColorFormatTest.vue +93 -0
- package/Basic/components/div/DivRadius.vue +97 -15
- package/Basic/components/div/DivTag3Group.vue +30 -0
- package/Basic/components/img/ImageType.vue +65 -0
- package/Basic/components/panel/Panel2.vue +13 -1
- package/Basic/components/text/TextAlign.vue +7 -1
- package/BlobLoadTest/App.vue +201 -0
- package/BreakLinesApi/App.vue +82 -0
- package/CanvasDrawChart/App.vue +11 -0
- package/CanvasDrawChart/Graph1.vue +104 -0
- package/CanvasDrawChart/Graph2.vue +115 -0
- package/DashPath/App.vue +17 -16
- package/DashPath/AppForOperator.vue +2 -4
- package/DemoForOperator/AnimPic/AnimPic.vue +24 -2
- package/DemoForOperator/Banger/Banger/Banger.vue +73 -9
- package/DemoForOperator/Blur/Blur.vue +146 -0
- package/DemoForOperator/Blur/BlurInOut/BlurInOut.vue +184 -0
- package/DemoForOperator/Blur/BlurInOut/StaticBgSlide.vue +162 -0
- package/DemoForOperator/Blur/BlurPopup/BlurPopup.vue +249 -0
- package/DemoForOperator/BookFlip/App.vue +115 -0
- package/DemoForOperator/BookFlip/BookPage.vue +82 -0
- package/DemoForOperator/Bounce/Bounce.vue +33 -1
- package/DemoForOperator/Bounce/FreeMoveBuilder.js +1 -1
- package/DemoForOperator/ChunLian/Couplets.vue +44 -1
- package/DemoForOperator/ClickSpriteAnim/App.vue +130 -0
- package/DemoForOperator/ClickSpriteAnim/Item.vue +74 -0
- package/DemoForOperator/DominantColor/App.vue +187 -0
- package/DemoForOperator/EpisodeList/EpisodeList/Controller.vue +0 -3
- package/DemoForOperator/EpisodeList/EpisodeList/EpisodeList.vue +76 -2
- package/DemoForOperator/Firework1/App.vue +13 -2
- package/DemoForOperator/Firework1/Fireworks.vue +68 -11
- package/DemoForOperator/FlipPage/FlipPage/FlipPage.vue +30 -1
- package/DemoForOperator/Focus/Alpha/AlphaFocusBox.vue +27 -2
- package/DemoForOperator/Focus/Alpha/Item.vue +1 -0
- package/DemoForOperator/Focus/Light/Item.vue +1 -0
- package/DemoForOperator/Focus/Light/LightFocusBox.vue +42 -1
- package/DemoForOperator/Focus/Normal/Item.vue +1 -0
- package/DemoForOperator/Focus/Normal/NormalFocusBox.vue +12 -0
- package/DemoForOperator/FrameShadow/App.vue +193 -0
- package/DemoForOperator/FrameShadow/FrameShadow.vue +61 -0
- package/DemoForOperator/FullscreenIn/App.vue +1 -1
- package/DemoForOperator/FullscreenIn/FullscreenPoster.vue +18 -3
- package/DemoForOperator/Genie/App.vue +20 -6
- package/DemoForOperator/Genie/App2.vue +61 -0
- package/DemoForOperator/Genie/geniePakcer/GenieImage.vue +298 -0
- package/DemoForOperator/Genie/geniePakcer/GenieSlot.vue +292 -0
- package/DemoForOperator/Genie/geniePakcer/GenieTools.ts +463 -0
- package/DemoForOperator/GrayFilter/GrayFilter.vue +21 -0
- package/DemoForOperator/Jigsaw/JigsawFull.vue +58 -11
- package/DemoForOperator/Jigsaw/JigsawSingle.vue +47 -9
- package/DemoForOperator/LongChatBox/App.vue +36 -0
- package/DemoForOperator/LongChatBox/Bubble.vue +116 -0
- package/DemoForOperator/LongChatBox/LongChat.vue +204 -0
- package/DemoForOperator/LongChatBox/testData.js +14 -0
- package/DemoForOperator/Particle/Drop/DropParticle.vue +33 -1
- package/DemoForOperator/Particle/Explode/ExplodeParticle.vue +23 -2
- package/DemoForOperator/PosterAnim/PosterAnim.js +21 -0
- package/DemoForOperator/PosterOverflow/PosterOverflow.vue +16 -0
- package/DemoForOperator/Resize/App.vue +157 -0
- package/DemoForOperator/Resize/Resize/Item.vue +234 -0
- package/DemoForOperator/Resize/Resize/Resize.vue +96 -0
- package/DemoForOperator/Ripple/Ripple.vue +16 -1
- package/DemoForOperator/ScreenShootScale/App.vue +96 -0
- package/DemoForOperator/ScreenShootScale/Back.vue +86 -0
- package/DemoForOperator/ScreenShootScale/Front.vue +133 -0
- package/DemoForOperator/ScreenShootScale/Item.vue +62 -0
- package/DemoForOperator/ScreenShootScale/ScreenShootScale.vue +109 -0
- package/DemoForOperator/SmoothSwiper/App.vue +50 -0
- package/DemoForOperator/Sound/Bounce/App.vue +56 -0
- package/DemoForOperator/Sound/Bounce/Bounce.vue +87 -0
- package/DemoForOperator/Sound/Bounce/FreeMoveBuilder.js +146 -0
- package/DemoForOperator/Sound/Bounce/bgmusic.mp3 +0 -0
- package/DemoForOperator/Sound/Bounce/coin.mp3 +0 -0
- package/DemoForOperator/Sound/FocusMove/App.vue +134 -0
- package/DemoForOperator/Sound/FocusMove/Item.vue +43 -0
- package/DemoForOperator/Sound/FocusMove/move.mp3 +0 -0
- package/DemoForOperator/Sound/Rain/App.vue +11 -0
- package/DemoForOperator/Sound/Rain/Raining/Rain.vue +69 -0
- package/DemoForOperator/Sound/Rain/Raining/RainScene.vue +118 -0
- package/DemoForOperator/Sound/Sound/Sound.vue +24 -0
- package/DemoForOperator/Sound/Sound/index.js +4 -0
- package/DemoForOperator/Sound/Sound/useSound.js +112 -0
- package/DemoForOperator/Sprite/Sprite.vue +62 -5
- package/DemoForOperator/Stretch/Stretch/Stretch.vue +52 -2
- package/DemoForOperator/Swiper/App.vue +101 -0
- package/DemoForOperator/Swiper/Item.vue +56 -0
- package/DemoForOperator/Swiper/ParallaxSlide.vue +164 -0
- package/DemoForOperator/TabContent/TabContent/TabContent.vue +39 -1
- package/DemoForOperator/TabContentVertical/App.vue +104 -0
- package/DemoForOperator/TabContentVertical/ContentPage.vue +67 -0
- package/DemoForOperator/TabContentVertical/Item.vue +94 -0
- package/DemoForOperator/TabContentVertical/PageItem.vue +40 -0
- package/DemoForOperator/TabContentVertical/TabContent/CreepFocus.vue +160 -0
- package/DemoForOperator/TabContentVertical/TabContent/Item.vue +63 -0
- package/DemoForOperator/TabContentVertical/TabContent/TabContent.vue +184 -0
- package/DemoForOperator/TabContentVertical/TabContent/TabItem.vue +368 -0
- package/DemoForOperator/TabContentVertical/TabContent/TabWidget.vue +259 -0
- package/DemoForOperator/TabContentVertical/TabContent/Util.js +3 -0
- package/DemoForOperator/TabContentVertical/TabContent/ViewSwiper.vue +110 -0
- package/DemoForOperator/TabContentVertical/assets/children_science.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/documentary.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/free.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/game.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/home_selected.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/movie_ticket.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/my_account.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/opera.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/sports.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/tv_drama.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/variety_show.png +0 -0
- package/DemoForOperator/TabContentVertical/assets/vip.png +0 -0
- package/DemoForOperator/TabContentVertical/testData.js +76 -0
- package/DemoForOperator/Vortex/Vortex/Vortex.vue +26 -0
- package/DemoForOperator/routeList.js +125 -2
- package/DemoHomepage/App.vue +74 -1
- package/DemoHomepage/components/BodyFrame.vue +5 -0
- package/DemoHomepage/components/Item.vue +11 -0
- package/DemoHomepage/components/TabFrame.vue +1 -1
- package/DemoHomepage/router.js +798 -140
- package/DemoHomepage/views/Homepage.vue +60 -2
- package/DemoHomepage/watchTest.vue +50 -0
- package/DomRenderer/App.vue +133 -0
- package/FilterDemo/AnimatePic.vue +63 -17
- package/FilterDemo/App.vue +3 -3
- package/FlexCellDemo/AI_skills_update.md +4 -0
- package/FlexCellDemo/TestFrame1.vue +12 -2
- package/FlexCellDemo/TestFrame2.vue +10 -1
- package/FlexCellDemo/TestFrame3.vue +114 -59
- package/FpsLimit/App.vue +102 -0
- package/FreeMove/App.vue +24 -279
- package/FreeMove/TestScene1.vue +260 -0
- package/FreeMove/TestScene3.vue +431 -0
- package/FreeMoveChildAttract/App.vue +18 -8
- package/FreeMoveLink/App.vue +51 -22
- package/GiftRain/components/SpriteTranslate.vue +68 -48
- package/HashHistory/App.vue +2 -2
- package/HashHistory/router.js +1 -1
- package/Hover/App.vue +144 -0
- package/HttpRequestSSE/SSEReader.js +200 -0
- package/ImpactStop/App.vue +2 -2
- package/Input/FullKeyboard.vue +3 -3
- package/Input/InputPanel.vue +63 -3
- package/JsvLine/App.vue +53 -38
- package/LatexDemo/App.vue +3 -1
- package/LatexFormula/App.vue +196 -0
- package/LongImage/App.vue +1 -1
- package/LongImage/LongImageScroll.vue +111 -46
- package/LongImage/Scroll.vue +28 -9
- package/LongText/LongTextScroll.vue +14 -1
- package/Markdown/App.vue +36 -0
- package/Markdown/Bubble.vue +109 -0
- package/Markdown/LongChat.vue +216 -0
- package/Markdown/data.js +633 -0
- package/MetroWidgetDemos/AI_skills_update.md +2 -0
- package/MetroWidgetDemos/EpgFlowListType/App.vue +206 -0
- package/MetroWidgetDemos/EpgFlowListType/components/ContentCard.vue +105 -0
- package/MetroWidgetDemos/EpgFlowListType/components/FloorSection.vue +131 -0
- package/MetroWidgetDemos/EpgFlowListType/components/LeftTabItem.vue +41 -0
- package/MetroWidgetDemos/EpgFlowListType/data.js +78 -0
- package/MetroWidgetDemos/ListExpand/ChildItem.vue +130 -0
- package/MetroWidgetDemos/ListExpand/ExpandItem.vue +375 -0
- package/MetroWidgetDemos/ListExpand/ExpandItem1.vue +403 -0
- package/MetroWidgetDemos/ListExpand/assets/arrow-down.png +0 -0
- package/MetroWidgetDemos/ListExpand/assets/up-arrow.png +0 -0
- package/MetroWidgetDemos/ListExpand/components/WidgetListHandler.vue +150 -0
- package/MetroWidgetDemos/ListExpand/index.vue +88 -0
- package/MetroWidgetDemos/ListExpand/list.js +2421 -0
- package/MetroWidgetDemos/RefreshDemo/App.vue +14 -1
- package/MetroWidgetDemos/RenderAccelerate/App.vue +142 -0
- package/MetroWidgetDemos/RenderAccelerate/AppPage.vue +78 -0
- package/MetroWidgetDemos/RenderAccelerate/AppTab.vue +62 -0
- package/MetroWidgetDemos/RenderAccelerate/ContentItem.vue +409 -0
- package/MetroWidgetDemos/{TripleWidget → RenderAccelerate}/Item.vue +6 -3
- package/MetroWidgetDemos/RenderAccelerate/TabItem.vue +100 -0
- package/MetroWidgetDemos/RenderAccelerate/ViewSwiper.vue +215 -0
- package/MetroWidgetDemos/RenderAccelerate/WidgetItem.vue +107 -0
- package/MetroWidgetDemos/SkeletonDiagram/App.vue +35 -8
- package/MetroWidgetDemos/SkeletonDiagram/Item.vue +11 -2
- package/MetroWidgetDemos/SkeletonDiagram/assets/imageList.js +245 -0
- package/MetroWidgetDemos/SkeletonDiagram/data.js +3 -3
- package/MetroWidgetDemos/SpatialNav/App.vue +177 -0
- package/MetroWidgetDemos/SpatialNav/Buttons.vue +83 -0
- package/MetroWidgetDemos/SpatialNav/CustomFocus.vue +57 -0
- package/MetroWidgetDemos/SpatialNav/Item.vue +71 -0
- package/MetroWidgetDemos/SpatialNav/SimpleFloor.vue +86 -0
- package/MetroWidgetDemos/SpatialNav/StepMw.vue +113 -0
- package/MetroWidgetDemos/SpatialNav/TabContent/TabContent.vue +185 -0
- package/MetroWidgetDemos/SpatialNav/TripleSection/TripleSection.vue +69 -0
- package/MetroWidgetDemos/SpatialNav/TripleSection/WidgetItem.vue +100 -0
- package/MetroWidgetDemos/SpatialNav/TvSection/List.vue +75 -0
- package/MetroWidgetDemos/SpatialNav/TvSection/TvSection.vue +91 -0
- package/MetroWidgetDemos/basic2/App.vue +407 -0
- package/MetroWidgetDemos/basic2/Item.vue +68 -0
- package/MetroWidgetDemos/direction/App.vue +22 -0
- package/MetroWidgetDemos/gazeFocusDiff/App.vue +126 -0
- package/MetroWidgetDemos/gazeFocusDiff/Item.vue +87 -0
- package/MetroWidgetDemos/minimalUsage/App.vue +66 -0
- package/MetroWidgetDemos/minimalUsage/Item.vue +54 -0
- package/MetroWidgetDemos/ninePatchFocusPage/App.vue +23 -7
- package/MetroWidgetDemos/ninePatchFocusPage/Item.vue +7 -5
- package/MetroWidgetDemos/ninePatchFocusPage/focusConstants.js +2 -0
- package/MetroWidgetDemos/routeList.js +229 -8
- package/MetroWidgetDemos/slideSetting/App.vue +288 -99
- package/MetroWidgetDemos/zIndex/App.vue +117 -0
- package/MetroWidgetDemos/zIndex/Item.vue +61 -0
- package/NinePatchTester/App.vue +24 -31
- package/PosterPacker/App.vue +2 -2
- package/PreDecode/App.vue +140 -0
- package/ReactiveTest/App.vue +115 -0
- package/ReactiveTest/Item.vue +92 -0
- package/ReactiveTest/assets/imageList.js +245 -0
- package/ReactiveTest/component/TestSmartDiv.vue +50 -0
- package/ReactiveTest/component/TestSmartDivSrcList.vue +74 -0
- package/ReactiveTest/component/TestSmartImage.vue +46 -0
- package/ReactiveTest/component/TestSmartImageSrcList.vue +90 -0
- package/ReactiveTest/component/TestSmartImageStyle.vue +41 -0
- package/ReactiveTest/data.js +49 -0
- package/ScreenToBlob/App.vue +250 -0
- package/ScrollBoxTest/App.vue +52 -28
- package/ScrollBoxTest/ClipBar.vue +64 -2
- package/ScrollBoxTest/NinePatchBar.vue +64 -2
- package/ScrollBoxTest/SizeDivBar.vue +64 -2
- package/SecTorTest/App.vue +9 -3
- package/SpringFestival/SpringFestivalScene/FreeMoveBuilder.js +3 -3
- package/SyncDecode/App.vue +137 -0
- package/TextSizeLimit/App.vue +211 -0
- package/TextureAnimation/App3.vue +11 -1
- package/TouchWidget/App.vue +90 -5
- package/TouchWidget/WidgetItem.vue +1 -0
- package/TransitPage/App.vue +2 -0
- package/ViewOpacity/App.vue +19 -0
- package/assets/logo.png +0 -0
- package/package.json +1 -1
- package/DashPath/DashPath.vue +0 -118
- package/DemoForOperator/Genie/geniePakcer/Genie.vue +0 -699
- package/DemoForOperator/ScalePoster/App.vue +0 -4
- package/DemoForOperator/ScalePoster/ScalePoster.vue +0 -0
- package/DivMetroPerformance/App.vue +0 -157
- package/DivMetroPerformance/Item.vue +0 -58
- package/DivMetroPerformance/assets/bg.jpg +0 -0
- package/DivMetroPerformance/assets/coupon_content.png +0 -0
- package/DivMetroPerformance/assets/coupon_left.png +0 -0
- package/DivMetroPerformance/assets/coupon_mid.png +0 -0
- package/DivMetroPerformance/assets/coupon_right.png +0 -0
- package/DivMetroPerformance/assets/focus_border.png +0 -0
- package/DivMetroPerformance/assets/holder_logo.png +0 -0
- package/DivMetroPerformance/assets/jrbm.png +0 -0
- package/DivMetroPerformance/assets/line_left.png +0 -0
- package/DivMetroPerformance/assets/line_mid.png +0 -0
- package/DivMetroPerformance/assets/line_right.png +0 -0
- package/DivMetroPerformance/assets/loading.png +0 -0
- package/DivMetroPerformance/assets/logo.png +0 -0
- package/DivMetroPerformance/assets/mcjx.png +0 -0
- package/DivMetroPerformance/assets/tao.png +0 -0
- package/DivMetroPerformance/assets/tmall.png +0 -0
- package/DivMetroPerformance/border.png +0 -0
- package/DivMetroPerformance/components/ContentItem.vue +0 -384
- package/DivMetroPerformance/components/MyTab.vue +0 -129
- package/DivMetroPerformance/data.js +0 -124
- package/DivMetroPerformance/utils/GridItem.vue +0 -28
- package/DivMetroPerformance/utils/GridPlate.vue +0 -85
- package/MediaDemo/App.vue +0 -127
- package/MediaDemo/assets/audio-poster.png +0 -0
- package/MediaDemo/components/Button.vue +0 -69
- package/MediaDemo/components/Controllor.vue +0 -286
- package/MediaDemo/components/StatusBar.vue +0 -100
- package/MediaDemo/components/frames/AudioFrame.vue +0 -39
- package/MediaDemo/components/frames/AudioPoster.vue +0 -48
- package/MediaDemo/components/frames/MediaFrame.vue +0 -153
- package/MediaDemo/components/frames/VideoFrame.vue +0 -39
- package/MetroWidgetDemos/TripleWidget/App.vue +0 -81
- package/MetroWidgetDemos/TripleWidget/SWidgetItem.vue +0 -93
- package/MetroWidgetDemos/TripleWidget/WidgetItem.vue +0 -111
- package/Parkour/App.vue +0 -13
- package/Parkour/Common/Context.js +0 -21
- package/Parkour/Common/MatchmanInfo.js +0 -62
- package/Parkour/Common/Random.js +0 -61
- package/Parkour/Common/Sound.js +0 -50
- package/Parkour/appConfig/HOW_TO_CONFIG.md +0 -20
- package/Parkour/appConfig/app.config.mjs +0 -5
- package/Parkour/appConfig/app_sign_private_key_sample.crt +0 -28
- package/Parkour/appConfig/app_sign_public_key_sample.pem +0 -9
- package/Parkour/appConfig/jsview.config.mjs +0 -39
- package/Parkour/assets/Bgimages/bg1.png +0 -0
- package/Parkour/assets/Bgimages/bg2.png +0 -0
- package/Parkour/assets/Bgimages/bg3.png +0 -0
- package/Parkour/assets/Bgimages/bg4.png +0 -0
- package/Parkour/assets/Bgimages/bg5.png +0 -0
- package/Parkour/assets/audio/jump.mp3 +0 -0
- package/Parkour/assets/audio/lose.mp3 +0 -0
- package/Parkour/assets/role_skin1/fail.json +0 -44
- package/Parkour/assets/role_skin1/fail.png +0 -0
- package/Parkour/assets/role_skin1/jump_down.json +0 -20
- package/Parkour/assets/role_skin1/jump_down.png +0 -0
- package/Parkour/assets/role_skin1/jump_up.json +0 -44
- package/Parkour/assets/role_skin1/jump_up.png +0 -0
- package/Parkour/assets/role_skin1/roll.json +0 -44
- package/Parkour/assets/role_skin1/roll.png +0 -0
- package/Parkour/assets/role_skin1/run.json +0 -52
- package/Parkour/assets/role_skin1/run.png +0 -0
- package/Parkour/components/Backdrop.vue +0 -61
- package/Parkour/components/GameSence.vue +0 -602
- package/Parkour/components/Matchman.vue +0 -85
- package/TextureAnimation/utils/FrameCanvasStore.ts +0 -68
- package/TextureAnimation/utils/RotateFrame.vue +0 -146
- package/TextureAnimation/utils/circleHaloMask.png +0 -0
- package/ThrowMoveDemo/AccelerateDemo.vue +0 -85
- package/ThrowMoveDemo/App.vue +0 -104
- package/ThrowMoveDemo/LRParabolicDemo.vue +0 -101
- package/ThrowMoveDemo/TargetDemo.vue +0 -87
- package/ThrowMoveDemo/UDParabolicDemo.vue +0 -92
- /package/{AnimPicture/assets → assets}/animated_webp.webp +0 -0
- /package/{AnimPicture/assets → assets}/ball_3.webp +0 -0
- /package/{AnimPicture/assets → assets}/girl_run.gif +0 -0
- /package/{AnimPicture/assets → assets}/quan.webp +0 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<jsv-focus-block name="TestScene1" :onAction="onActionObj">
|
|
3
|
+
<div :style="style.sceneRoot">
|
|
4
|
+
<div :style="style.tipText">Press OK to pause/resume</div>
|
|
5
|
+
<div :style="style.horizontalBoundaryLeftMark"></div>
|
|
6
|
+
<div :style="style.horizontalBoundaryRightMark"></div>
|
|
7
|
+
<jsv-free-move-actor ref="horizontalActorRef" :top="HORIZONTAL_ACTOR_TOP" :left="0" :width="ACTOR_SIZE" :height="ACTOR_SIZE">
|
|
8
|
+
<div :style="style.horizontalBox"></div>
|
|
9
|
+
</jsv-free-move-actor>
|
|
10
|
+
<div :style="style.verticalBoundaryTopMark"></div>
|
|
11
|
+
<div :style="style.verticalBoundaryBottomMark"></div>
|
|
12
|
+
<jsv-free-move-actor ref="verticalActorRef" :top="0" :left="0" :width="ACTOR_SIZE" :height="ACTOR_SIZE">
|
|
13
|
+
<div :style="style.verticalBox"></div>
|
|
14
|
+
</jsv-free-move-actor>
|
|
15
|
+
</div>
|
|
16
|
+
</jsv-focus-block>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup>
|
|
20
|
+
import { JsvFreeMoveActor, FreeMoveApis, useFocusHub } from "jsview";
|
|
21
|
+
import { shallowRef, onMounted, nextTick } from "vue";
|
|
22
|
+
|
|
23
|
+
// 横向与纵向分别使用独立边界和速度,避免同节奏撞边
|
|
24
|
+
const HORIZONTAL_MIN_X = 100;
|
|
25
|
+
const HORIZONTAL_MAX_X = 460;
|
|
26
|
+
const FIXED_X = 620;
|
|
27
|
+
const VERTICAL_MIN_Y = 100;
|
|
28
|
+
const VERTICAL_MAX_Y = 500;
|
|
29
|
+
const HORIZONTAL_SPEED = 7;
|
|
30
|
+
const VERTICAL_SPEED = 4;
|
|
31
|
+
const HORIZONTAL_ACTOR_TOP = 220;
|
|
32
|
+
const ACTOR_SIZE = 80;
|
|
33
|
+
|
|
34
|
+
// 在script中定义style比 style scoped 执行速度更快
|
|
35
|
+
const style = {
|
|
36
|
+
sceneRoot: {
|
|
37
|
+
width: 1280,
|
|
38
|
+
height: 720,
|
|
39
|
+
backgroundColor: "#102030",
|
|
40
|
+
},
|
|
41
|
+
tipText: {
|
|
42
|
+
left: 60,
|
|
43
|
+
top: 80,
|
|
44
|
+
width: 420,
|
|
45
|
+
height: 40,
|
|
46
|
+
lineHeight: 40,
|
|
47
|
+
fontSize: 30,
|
|
48
|
+
color: "#ffffff",
|
|
49
|
+
},
|
|
50
|
+
horizontalBoundaryLeftMark: {
|
|
51
|
+
left: HORIZONTAL_MIN_X - 6,
|
|
52
|
+
top: HORIZONTAL_ACTOR_TOP - 10,
|
|
53
|
+
width: 6,
|
|
54
|
+
height: 100,
|
|
55
|
+
backgroundColor: "#ffd666",
|
|
56
|
+
},
|
|
57
|
+
horizontalBoundaryRightMark: {
|
|
58
|
+
left: HORIZONTAL_MAX_X,
|
|
59
|
+
top: HORIZONTAL_ACTOR_TOP - 10,
|
|
60
|
+
width: 6,
|
|
61
|
+
height: 100,
|
|
62
|
+
backgroundColor: "#ffd666",
|
|
63
|
+
},
|
|
64
|
+
verticalBoundaryTopMark: {
|
|
65
|
+
left: FIXED_X - 10,
|
|
66
|
+
top: VERTICAL_MIN_Y - 6,
|
|
67
|
+
width: 100,
|
|
68
|
+
height: 6,
|
|
69
|
+
backgroundColor: "#95de64",
|
|
70
|
+
},
|
|
71
|
+
verticalBoundaryBottomMark: {
|
|
72
|
+
left: FIXED_X - 10,
|
|
73
|
+
top: VERTICAL_MAX_Y,
|
|
74
|
+
width: 100,
|
|
75
|
+
height: 6,
|
|
76
|
+
backgroundColor: "#95de64",
|
|
77
|
+
},
|
|
78
|
+
horizontalBox: {
|
|
79
|
+
width: 80,
|
|
80
|
+
height: 80,
|
|
81
|
+
backgroundColor: "#ff7a45",
|
|
82
|
+
},
|
|
83
|
+
verticalBox: {
|
|
84
|
+
width: 80,
|
|
85
|
+
height: 80,
|
|
86
|
+
backgroundColor: "#36cfc9",
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const horizontalActorRef = shallowRef(null);
|
|
91
|
+
const verticalActorRef = shallowRef(null);
|
|
92
|
+
const paused = shallowRef(false);
|
|
93
|
+
const focusHub = useFocusHub();
|
|
94
|
+
let horizontalActorControl = null;
|
|
95
|
+
let verticalActorControl = null;
|
|
96
|
+
|
|
97
|
+
// 自定义事件总线:用于集中控制所有 actor 的暂停/恢复
|
|
98
|
+
// 一个事件可以同时控制两个actor, 当然也可以分开控制
|
|
99
|
+
const pauseNexus = FreeMoveApis.newNexus();
|
|
100
|
+
const resumeNexus = FreeMoveApis.newNexus();
|
|
101
|
+
|
|
102
|
+
// 预制条件名称, 用于区分不同方向的resume条件
|
|
103
|
+
const RESUME_POS_X_SPEC = "resume-pos-x";
|
|
104
|
+
const RESUME_NEG_X_SPEC = "resume-neg-x";
|
|
105
|
+
const RESUME_POS_Y_SPEC = "resume-pos-y";
|
|
106
|
+
const RESUME_NEG_Y_SPEC = "resume-neg-y";
|
|
107
|
+
|
|
108
|
+
const setupHorizontalLoopConditions = () => {
|
|
109
|
+
horizontalActorControl.run((cmds) => [
|
|
110
|
+
// 先清空旧条件,避免重复注册造成逻辑叠加
|
|
111
|
+
cmds.state().clearAllConditions(),
|
|
112
|
+
// 到达右边界后反向向左移动
|
|
113
|
+
cmds
|
|
114
|
+
.condition({ multiTimes: true })
|
|
115
|
+
.positionWall("right", HORIZONTAL_MAX_X - ACTOR_SIZE) // 边界位置指的是actor左上角, 所以减去actor尺寸避免穿模
|
|
116
|
+
.then([
|
|
117
|
+
cmds.state().alignPosition(), // 校准位置到边界, 避免穿模
|
|
118
|
+
cmds.action().setSpeed(-HORIZONTAL_SPEED, 0),
|
|
119
|
+
cmds.state().deactiveCondition(undefined, RESUME_POS_X_SPEC),
|
|
120
|
+
cmds.state().activeCondition(undefined, RESUME_NEG_X_SPEC),
|
|
121
|
+
]),
|
|
122
|
+
// 到达左边界后反向向右移动
|
|
123
|
+
cmds
|
|
124
|
+
.condition({ multiTimes: true })
|
|
125
|
+
.positionWall("left", HORIZONTAL_MIN_X)
|
|
126
|
+
.then([
|
|
127
|
+
cmds.state().alignPosition(), // 校准位置到边界, 避免穿模
|
|
128
|
+
cmds.action().setSpeed(HORIZONTAL_SPEED, 0),
|
|
129
|
+
cmds.state().deactiveCondition(undefined, RESUME_NEG_X_SPEC),
|
|
130
|
+
cmds.state().activeCondition(undefined, RESUME_POS_X_SPEC),
|
|
131
|
+
]),
|
|
132
|
+
// 监听统一暂停事件
|
|
133
|
+
cmds
|
|
134
|
+
.condition({ multiTimes: true })
|
|
135
|
+
.onCustomNexus(pauseNexus)
|
|
136
|
+
.then([
|
|
137
|
+
cmds.action().stopMoving(false),
|
|
138
|
+
]),
|
|
139
|
+
// resume 预制方案A:向右运动(默认激活)
|
|
140
|
+
cmds
|
|
141
|
+
.condition({ multiTimes: true, specName: RESUME_POS_X_SPEC })
|
|
142
|
+
.onCustomNexus(resumeNexus)
|
|
143
|
+
.then([cmds.action().setSpeed(HORIZONTAL_SPEED, 0)]),
|
|
144
|
+
// resume 预制方案B:向左运动(初始关闭)
|
|
145
|
+
cmds
|
|
146
|
+
.condition({ multiTimes: true, specName: RESUME_NEG_X_SPEC })
|
|
147
|
+
.onCustomNexus(resumeNexus)
|
|
148
|
+
.then([cmds.action().setSpeed(-HORIZONTAL_SPEED, 0)]),
|
|
149
|
+
cmds.state().deactiveCondition(undefined, RESUME_NEG_X_SPEC),
|
|
150
|
+
]);
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const setupVerticalLoopConditions = () => {
|
|
154
|
+
verticalActorControl.run((cmds) => [
|
|
155
|
+
cmds.state().clearAllConditions(),
|
|
156
|
+
// 到达下边界后反向向上移动
|
|
157
|
+
cmds
|
|
158
|
+
.condition({ multiTimes: true })
|
|
159
|
+
.positionWall("bottom", VERTICAL_MAX_Y - ACTOR_SIZE) // 边界位置指的是actor左上角, 所以减去actor尺寸避免穿模
|
|
160
|
+
.then([
|
|
161
|
+
cmds.state().alignPosition(), // 校准位置到边界, 避免穿模
|
|
162
|
+
cmds.action().setSpeed(0, -VERTICAL_SPEED),
|
|
163
|
+
cmds.state().deactiveCondition(undefined, RESUME_POS_Y_SPEC),
|
|
164
|
+
cmds.state().activeCondition(undefined, RESUME_NEG_Y_SPEC),
|
|
165
|
+
]),
|
|
166
|
+
// 到达上边界后反向向下移动
|
|
167
|
+
cmds
|
|
168
|
+
.condition({ multiTimes: true })
|
|
169
|
+
.positionWall("top", VERTICAL_MIN_Y)
|
|
170
|
+
.then([
|
|
171
|
+
cmds.state().alignPosition(), // 校准位置到边界, 避免穿模
|
|
172
|
+
cmds.action().setSpeed(0, VERTICAL_SPEED),
|
|
173
|
+
cmds.state().deactiveCondition(undefined, RESUME_NEG_Y_SPEC),
|
|
174
|
+
cmds.state().activeCondition(undefined, RESUME_POS_Y_SPEC),
|
|
175
|
+
]),
|
|
176
|
+
// 监听统一暂停事件
|
|
177
|
+
cmds
|
|
178
|
+
.condition({ multiTimes: true })
|
|
179
|
+
.onCustomNexus(pauseNexus)
|
|
180
|
+
.then([
|
|
181
|
+
cmds.action().stopMoving(false),
|
|
182
|
+
]),
|
|
183
|
+
// resume 预制方案A:向下运动(默认激活)
|
|
184
|
+
cmds
|
|
185
|
+
.condition({ multiTimes: true, specName: RESUME_POS_Y_SPEC })
|
|
186
|
+
.onCustomNexus(resumeNexus)
|
|
187
|
+
.then([cmds.action().setSpeed(0, VERTICAL_SPEED)]),
|
|
188
|
+
// resume 预制方案B:向上运动(初始关闭)
|
|
189
|
+
cmds
|
|
190
|
+
.condition({ multiTimes: true, specName: RESUME_NEG_Y_SPEC })
|
|
191
|
+
.onCustomNexus(resumeNexus)
|
|
192
|
+
.then([cmds.action().setSpeed(0, -VERTICAL_SPEED)]),
|
|
193
|
+
cmds.state().deactiveCondition(undefined, RESUME_NEG_Y_SPEC),
|
|
194
|
+
]);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const startLoopMotion = () => {
|
|
198
|
+
// 水平 actor 从左侧起点开始向右移动
|
|
199
|
+
horizontalActorControl.run((cmds) => [
|
|
200
|
+
cmds.state().setStartPos(HORIZONTAL_MIN_X, 0),
|
|
201
|
+
cmds.action().setSpeed(HORIZONTAL_SPEED, 0),
|
|
202
|
+
]);
|
|
203
|
+
// 垂直 actor 在固定 X 上从上侧起点开始向下移动
|
|
204
|
+
verticalActorControl.run((cmds) => [
|
|
205
|
+
cmds.state().setStartPos(FIXED_X, VERTICAL_MIN_Y),
|
|
206
|
+
cmds.action().setSpeed(0, VERTICAL_SPEED),
|
|
207
|
+
]);
|
|
208
|
+
paused.value = false;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const pauseMotion = () => {
|
|
212
|
+
// 广播暂停事件,让已绑定该 nexus 的 actor 一起停下
|
|
213
|
+
FreeMoveApis.fireCustomNexus(pauseNexus);
|
|
214
|
+
paused.value = true;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const resumeMotion = () => {
|
|
218
|
+
// 方向由预制 condition 的激活态决定,不依赖响应式变量
|
|
219
|
+
FreeMoveApis.fireCustomNexus(resumeNexus);
|
|
220
|
+
paused.value = false;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const togglePause = () => {
|
|
224
|
+
// 检查控制器是否存在,避免在组件挂载前调用
|
|
225
|
+
if (!horizontalActorControl || !verticalActorControl) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// 根据暂停状态决定是暂停还是恢复
|
|
230
|
+
if (paused.value) {
|
|
231
|
+
resumeMotion();
|
|
232
|
+
} else {
|
|
233
|
+
pauseMotion();
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const onKeyDown = (ev) => {
|
|
238
|
+
// 13 为 OK 键:切换暂停/恢复
|
|
239
|
+
if (ev.keyCode === 13) {
|
|
240
|
+
togglePause();
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
return false;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
const onActionObj = {
|
|
247
|
+
onKeyDown,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
onMounted(() => {
|
|
251
|
+
focusHub.setFocus("TestScene1");
|
|
252
|
+
|
|
253
|
+
// 组件挂载后获取控制器并初始化条件,再启动循环运动
|
|
254
|
+
horizontalActorControl = horizontalActorRef.value.control;
|
|
255
|
+
verticalActorControl = verticalActorRef.value.control;
|
|
256
|
+
setupHorizontalLoopConditions();
|
|
257
|
+
setupVerticalLoopConditions();
|
|
258
|
+
startLoopMotion();
|
|
259
|
+
});
|
|
260
|
+
</script>
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<jsv-focus-block name="TestScene3">
|
|
3
|
+
<div :style="style.sceneRoot">
|
|
4
|
+
<div :style="style.tipText">
|
|
5
|
+
Test updateBaseOffset: hit walls and rebuild boundary continuously
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div :style="leftBoundaryStyle"></div>
|
|
9
|
+
<div :style="rightBoundaryStyle"></div>
|
|
10
|
+
<div :style="reachMarkerStyle">
|
|
11
|
+
{{ "重合后+1" }}
|
|
12
|
+
</div>
|
|
13
|
+
<div :style="topBoundaryStyle"></div>
|
|
14
|
+
<div :style="bottomBoundaryStyle"></div>
|
|
15
|
+
<div :style="verticalReachMarkerStyle">
|
|
16
|
+
{{ "重合后+1" }}
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<jsv-free-move-div ref="freeMoveRef" :style="freeMoveContainerStyle">
|
|
20
|
+
<div :style="style.actorBody">{{ hitCounter }}</div>
|
|
21
|
+
</jsv-free-move-div>
|
|
22
|
+
<jsv-free-move-div
|
|
23
|
+
ref="verticalFreeMoveRef"
|
|
24
|
+
:style="verticalFreeMoveContainerStyle"
|
|
25
|
+
>
|
|
26
|
+
<div :style="style.verticalActorBody">{{ verticalHitCounter }}</div>
|
|
27
|
+
</jsv-free-move-div>
|
|
28
|
+
</div>
|
|
29
|
+
</jsv-focus-block>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup>
|
|
33
|
+
import { JsvFreeMoveDiv, useFocusHub, FreeMoveDef } from "jsview";
|
|
34
|
+
import { computed, onMounted, shallowRef } from "vue";
|
|
35
|
+
|
|
36
|
+
const ORIGIN_LEFT = 420;
|
|
37
|
+
const ORIGIN_TOP = 300;
|
|
38
|
+
const TRACK_SPAN = 420;
|
|
39
|
+
const ACTOR_SIZE = 80;
|
|
40
|
+
// 初始时让 actor 处于左右边界中点
|
|
41
|
+
const INITIAL_GAP = (TRACK_SPAN - ACTOR_SIZE) / 2;
|
|
42
|
+
const SPEED_X = 8;
|
|
43
|
+
const VERTICAL_ORIGIN_LEFT = 860;
|
|
44
|
+
// 720 高度下,80 尺寸 actor 的 top 居中位置是 (720 - 80) / 2 = 320
|
|
45
|
+
const VERTICAL_ORIGIN_TOP = 320;
|
|
46
|
+
const SPEED_Y = 8;
|
|
47
|
+
const LEFT_BOUNDARY_NAME = "boundary-left";
|
|
48
|
+
const RIGHT_BOUNDARY_NAME = "boundary-right";
|
|
49
|
+
const TOP_BOUNDARY_NAME = "boundary-top";
|
|
50
|
+
const BOTTOM_BOUNDARY_NAME = "boundary-bottom";
|
|
51
|
+
// 中点 reach 条件的名字,后续不参与撞边重建流程
|
|
52
|
+
const REACH_POSITION_NAME = "reach-position-middle";
|
|
53
|
+
const VERTICAL_REACH_POSITION_NAME = "reach-position-middle-vertical";
|
|
54
|
+
// FreeMove 的局部坐标中,起点就是 (0,0),这里用 x=0 作为“中点穿越”监听线
|
|
55
|
+
const REACH_X = 0;
|
|
56
|
+
const REACH_Y = 0;
|
|
57
|
+
|
|
58
|
+
const freeMoveRef = shallowRef(null);
|
|
59
|
+
const verticalFreeMoveRef = shallowRef(null);
|
|
60
|
+
const focusHub = useFocusHub();
|
|
61
|
+
let freeMoveControl = null;
|
|
62
|
+
let verticalFreeMoveControl = null;
|
|
63
|
+
|
|
64
|
+
const containerLeft = shallowRef(ORIGIN_LEFT);
|
|
65
|
+
const containerTop = shallowRef(ORIGIN_TOP);
|
|
66
|
+
const leftGap = shallowRef(INITIAL_GAP);
|
|
67
|
+
const rightGap = shallowRef(INITIAL_GAP);
|
|
68
|
+
const verticalContainerLeft = shallowRef(VERTICAL_ORIGIN_LEFT);
|
|
69
|
+
const verticalContainerTop = shallowRef(VERTICAL_ORIGIN_TOP);
|
|
70
|
+
const topGap = shallowRef(INITIAL_GAP);
|
|
71
|
+
const bottomGap = shallowRef(INITIAL_GAP);
|
|
72
|
+
// 命中中点时进行 1~10 循环计数
|
|
73
|
+
const hitCounter = shallowRef(1);
|
|
74
|
+
const verticalHitCounter = shallowRef(1);
|
|
75
|
+
|
|
76
|
+
const style = {
|
|
77
|
+
sceneRoot: {
|
|
78
|
+
width: 1280,
|
|
79
|
+
height: 720,
|
|
80
|
+
backgroundColor: "#0b1a2c",
|
|
81
|
+
},
|
|
82
|
+
tipText: {
|
|
83
|
+
left: 48,
|
|
84
|
+
top: 72,
|
|
85
|
+
width: 980,
|
|
86
|
+
height: 40,
|
|
87
|
+
lineHeight: 40,
|
|
88
|
+
fontSize: 28,
|
|
89
|
+
color: "#fefefe",
|
|
90
|
+
},
|
|
91
|
+
actorBody: {
|
|
92
|
+
width: ACTOR_SIZE,
|
|
93
|
+
height: ACTOR_SIZE,
|
|
94
|
+
backgroundColor: "#ff9c6e",
|
|
95
|
+
color: "#112244",
|
|
96
|
+
fontSize: 32,
|
|
97
|
+
fontWeight: "bold",
|
|
98
|
+
textAlign: "center",
|
|
99
|
+
lineHeight: ACTOR_SIZE,
|
|
100
|
+
},
|
|
101
|
+
verticalActorBody: {
|
|
102
|
+
width: ACTOR_SIZE,
|
|
103
|
+
height: ACTOR_SIZE,
|
|
104
|
+
backgroundColor: "#69c0ff",
|
|
105
|
+
color: "#112244",
|
|
106
|
+
fontSize: 32,
|
|
107
|
+
fontWeight: "bold",
|
|
108
|
+
textAlign: "center",
|
|
109
|
+
lineHeight: ACTOR_SIZE,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const freeMoveContainerStyle = computed(() => ({
|
|
114
|
+
left: containerLeft.value,
|
|
115
|
+
top: containerTop.value,
|
|
116
|
+
width: ACTOR_SIZE,
|
|
117
|
+
height: ACTOR_SIZE,
|
|
118
|
+
}));
|
|
119
|
+
const verticalFreeMoveContainerStyle = computed(() => ({
|
|
120
|
+
left: verticalContainerLeft.value,
|
|
121
|
+
top: verticalContainerTop.value,
|
|
122
|
+
width: ACTOR_SIZE,
|
|
123
|
+
height: ACTOR_SIZE,
|
|
124
|
+
}));
|
|
125
|
+
|
|
126
|
+
// 左右边界是固定的
|
|
127
|
+
const leftBoundaryStyle = {
|
|
128
|
+
left: containerLeft.value - leftGap.value - 6,
|
|
129
|
+
top: containerTop.value - 10,
|
|
130
|
+
width: 6,
|
|
131
|
+
height: ACTOR_SIZE + 20,
|
|
132
|
+
backgroundColor: "#ffd666",
|
|
133
|
+
};
|
|
134
|
+
const rightBoundaryStyle = {
|
|
135
|
+
left: containerLeft.value + rightGap.value + ACTOR_SIZE,
|
|
136
|
+
top: containerTop.value - 10,
|
|
137
|
+
width: 6,
|
|
138
|
+
height: ACTOR_SIZE + 20,
|
|
139
|
+
backgroundColor: "#ffd666",
|
|
140
|
+
};
|
|
141
|
+
const reachMarkerStyle = {
|
|
142
|
+
// 标记块固定绘制在初始中心位置,用于和 actor 视觉比对
|
|
143
|
+
left: ORIGIN_LEFT,
|
|
144
|
+
top: ORIGIN_TOP,
|
|
145
|
+
width: ACTOR_SIZE,
|
|
146
|
+
height: ACTOR_SIZE,
|
|
147
|
+
lineHeight: ACTOR_SIZE,
|
|
148
|
+
fontSize: 16,
|
|
149
|
+
fontWeight: "bold",
|
|
150
|
+
textAlign: "center",
|
|
151
|
+
borderWidth: 3,
|
|
152
|
+
borderStyle: "dashed",
|
|
153
|
+
borderColor: "#52c41a",
|
|
154
|
+
backgroundColor: "rgba(82, 196, 26, 0.18)",
|
|
155
|
+
};
|
|
156
|
+
const topBoundaryStyle = computed(() => ({
|
|
157
|
+
left: verticalContainerLeft.value - 10,
|
|
158
|
+
top: verticalContainerTop.value - topGap.value - 6,
|
|
159
|
+
width: ACTOR_SIZE + 20,
|
|
160
|
+
height: 6,
|
|
161
|
+
backgroundColor: "#73d13d",
|
|
162
|
+
}));
|
|
163
|
+
const bottomBoundaryStyle = computed(() => ({
|
|
164
|
+
left: verticalContainerLeft.value - 10,
|
|
165
|
+
top: verticalContainerTop.value + bottomGap.value + ACTOR_SIZE,
|
|
166
|
+
width: ACTOR_SIZE + 20,
|
|
167
|
+
height: 6,
|
|
168
|
+
backgroundColor: "#73d13d",
|
|
169
|
+
}));
|
|
170
|
+
const verticalReachMarkerStyle = {
|
|
171
|
+
// 标记块固定绘制在竖直运动的初始中心位置,用于和 actor 视觉比对
|
|
172
|
+
left: VERTICAL_ORIGIN_LEFT,
|
|
173
|
+
top: VERTICAL_ORIGIN_TOP,
|
|
174
|
+
width: ACTOR_SIZE,
|
|
175
|
+
height: ACTOR_SIZE,
|
|
176
|
+
lineHeight: ACTOR_SIZE,
|
|
177
|
+
fontSize: 16,
|
|
178
|
+
fontWeight: "bold",
|
|
179
|
+
textAlign: "center",
|
|
180
|
+
borderWidth: 3,
|
|
181
|
+
borderStyle: "dashed",
|
|
182
|
+
borderColor: "#13c2c2",
|
|
183
|
+
backgroundColor: "rgba(19, 194, 194, 0.18)",
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const increaseCounter = () => {
|
|
187
|
+
// 计数器始终保持在 1~10 区间
|
|
188
|
+
hitCounter.value = hitCounter.value >= 10 ? 1 : hitCounter.value + 1;
|
|
189
|
+
};
|
|
190
|
+
const increaseVerticalCounter = () => {
|
|
191
|
+
// 计数器始终保持在 1~10 区间
|
|
192
|
+
verticalHitCounter.value =
|
|
193
|
+
verticalHitCounter.value >= 10 ? 1 : verticalHitCounter.value + 1;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const getStateXY = (stateInfo) => {
|
|
197
|
+
const x = stateInfo.xPos;
|
|
198
|
+
const y = stateInfo.yPos;
|
|
199
|
+
return { x, y };
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const getLocalWallPos = () => {
|
|
203
|
+
return {
|
|
204
|
+
left: -leftGap.value,
|
|
205
|
+
right: rightGap.value,
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
const getLocalVerticalWallPos = () => {
|
|
209
|
+
return {
|
|
210
|
+
top: -topGap.value,
|
|
211
|
+
bottom: bottomGap.value,
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// 撞边后的统一处理:
|
|
216
|
+
// 1) 响应式更新容器left/top
|
|
217
|
+
// 2) 用 updateBaseOffset 同步新基准
|
|
218
|
+
// 3) 只清理并重建“对边”condition,本边保留到到达对面再清理
|
|
219
|
+
// 注意:速度反转不在这里做,而是在 condition.then 内同步执行 scaleSpeed
|
|
220
|
+
const applyBaseOffsetAndRebuild = (nextDirection, stateInfo) => {
|
|
221
|
+
if (!freeMoveControl) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// 获取当前actor的坐标(相对于当前div的top,left的相对坐标)
|
|
226
|
+
const { x: stateX, y: stateY } = getStateXY(stateInfo);
|
|
227
|
+
|
|
228
|
+
// 命中墙后,按当前x位移重建左右gap:向左时x为负,向右时x为正
|
|
229
|
+
leftGap.value += stateX;
|
|
230
|
+
rightGap.value -= stateX;
|
|
231
|
+
|
|
232
|
+
// 更新container的left坐标
|
|
233
|
+
containerLeft.value += stateX;
|
|
234
|
+
|
|
235
|
+
// offset 以 condition.then 回调里的 state.x/state.y 为准
|
|
236
|
+
const offsetX = stateX;
|
|
237
|
+
const localWalls = getLocalWallPos();
|
|
238
|
+
|
|
239
|
+
freeMoveControl.run((cmds) => [
|
|
240
|
+
// 关键校验点:style坐标变化后(通过containerLeft.value更新),
|
|
241
|
+
// 必须同步到FreeMove内部基准系
|
|
242
|
+
cmds.state().updateBaseOffset(offsetX, 0),
|
|
243
|
+
// 单次只删除对边,本边保留(直到抵达对面再删除)
|
|
244
|
+
...(nextDirection > 0
|
|
245
|
+
? [
|
|
246
|
+
// 下次往右移动,只重建右墙;中点 reach 条件保持不变
|
|
247
|
+
cmds.state().removeConditionByName(RIGHT_BOUNDARY_NAME),
|
|
248
|
+
buildRightWallCondition(cmds, localWalls.right),
|
|
249
|
+
]
|
|
250
|
+
: [
|
|
251
|
+
// 下次往左移动,只重建左墙;中点 reach 条件保持不变
|
|
252
|
+
cmds.state().removeConditionByName(LEFT_BOUNDARY_NAME),
|
|
253
|
+
buildLeftWallCondition(cmds, localWalls.left),
|
|
254
|
+
]),
|
|
255
|
+
]);
|
|
256
|
+
};
|
|
257
|
+
const applyVerticalBaseOffsetAndRebuild = (nextDirection, stateInfo) => {
|
|
258
|
+
if (!verticalFreeMoveControl) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 获取当前actor的坐标(相对于当前div的top,left的相对坐标)
|
|
263
|
+
const { y: stateY } = getStateXY(stateInfo);
|
|
264
|
+
|
|
265
|
+
// 命中墙后,按当前y位移重建上下gap:向上时y为负,向下时y为正
|
|
266
|
+
topGap.value += stateY;
|
|
267
|
+
bottomGap.value -= stateY;
|
|
268
|
+
|
|
269
|
+
// 更新container的top坐标
|
|
270
|
+
verticalContainerTop.value += stateY;
|
|
271
|
+
|
|
272
|
+
// offset 以 condition.then 回调里的 state.x/state.y 为准
|
|
273
|
+
const offsetY = stateY;
|
|
274
|
+
const localWalls = getLocalVerticalWallPos();
|
|
275
|
+
|
|
276
|
+
verticalFreeMoveControl.run((cmds) => [
|
|
277
|
+
// 关键校验点:style坐标变化后(通过verticalContainerTop.value更新),
|
|
278
|
+
// 必须同步到FreeMove内部基准系
|
|
279
|
+
cmds.state().updateBaseOffset(0, offsetY),
|
|
280
|
+
// 单次只删除对边,本边保留(直到抵达对面再删除)
|
|
281
|
+
...(nextDirection > 0
|
|
282
|
+
? [
|
|
283
|
+
// 下次往下移动,只重建下墙;中点 reach 条件保持不变
|
|
284
|
+
cmds.state().removeConditionByName(BOTTOM_BOUNDARY_NAME),
|
|
285
|
+
buildBottomWallCondition(cmds, localWalls.bottom),
|
|
286
|
+
]
|
|
287
|
+
: [
|
|
288
|
+
// 下次往上移动,只重建上墙;中点 reach 条件保持不变
|
|
289
|
+
cmds.state().removeConditionByName(TOP_BOUNDARY_NAME),
|
|
290
|
+
buildTopWallCondition(cmds, localWalls.top),
|
|
291
|
+
]),
|
|
292
|
+
]);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const buildLeftWallCondition = (cmds, wallPos) => {
|
|
296
|
+
return cmds
|
|
297
|
+
.condition({ multiTimes: true, specName: LEFT_BOUNDARY_NAME })
|
|
298
|
+
.positionWall("left", wallPos)
|
|
299
|
+
.then([
|
|
300
|
+
cmds.state().alignPosition(),
|
|
301
|
+
// 反转速度放在then命令里同步执行,避免JS回调异步导致延迟
|
|
302
|
+
cmds.action(FreeMoveDef.KeepFlags.XY).scaleSpeed(-1, undefined),
|
|
303
|
+
(stateInfo) => {
|
|
304
|
+
// 命中左墙后重建基准和边界
|
|
305
|
+
applyBaseOffsetAndRebuild(1, stateInfo);
|
|
306
|
+
},
|
|
307
|
+
]);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const buildRightWallCondition = (cmds, wallPos) => {
|
|
311
|
+
return cmds
|
|
312
|
+
.condition({ multiTimes: true, specName: RIGHT_BOUNDARY_NAME })
|
|
313
|
+
.positionWall("right", wallPos)
|
|
314
|
+
.then([
|
|
315
|
+
cmds.state().alignPosition(),
|
|
316
|
+
// 反转速度放在then命令里同步执行,避免JS回调异步导致延迟
|
|
317
|
+
cmds.action(FreeMoveDef.KeepFlags.XY).scaleSpeed(-1, undefined),
|
|
318
|
+
(stateInfo) => {
|
|
319
|
+
// 命中右墙后重建基准和边界
|
|
320
|
+
applyBaseOffsetAndRebuild(-1, stateInfo);
|
|
321
|
+
},
|
|
322
|
+
]);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const buildReachCondition = (cmds) => {
|
|
326
|
+
return cmds
|
|
327
|
+
.condition({ multiTimes: true, specName: REACH_POSITION_NAME })
|
|
328
|
+
// 仅监听 x=0 的穿越,y 不限制
|
|
329
|
+
.reachPosition(REACH_X, undefined)
|
|
330
|
+
.then([
|
|
331
|
+
() => {
|
|
332
|
+
// 触达中点后回调 JS,测试 updateBaseOffset 对既有 condition 的影响
|
|
333
|
+
increaseCounter();
|
|
334
|
+
},
|
|
335
|
+
]);
|
|
336
|
+
};
|
|
337
|
+
const buildTopWallCondition = (cmds, wallPos) => {
|
|
338
|
+
return cmds
|
|
339
|
+
.condition({ multiTimes: true, specName: TOP_BOUNDARY_NAME })
|
|
340
|
+
.positionWall("top", wallPos)
|
|
341
|
+
.then([
|
|
342
|
+
cmds.state().alignPosition(),
|
|
343
|
+
// 反转速度放在then命令里同步执行,避免JS回调异步导致延迟
|
|
344
|
+
cmds.action(FreeMoveDef.KeepFlags.XY).scaleSpeed(undefined, -1),
|
|
345
|
+
(stateInfo) => {
|
|
346
|
+
// 命中上墙后重建基准和边界
|
|
347
|
+
applyVerticalBaseOffsetAndRebuild(1, stateInfo);
|
|
348
|
+
},
|
|
349
|
+
]);
|
|
350
|
+
};
|
|
351
|
+
const buildBottomWallCondition = (cmds, wallPos) => {
|
|
352
|
+
return cmds
|
|
353
|
+
.condition({ multiTimes: true, specName: BOTTOM_BOUNDARY_NAME })
|
|
354
|
+
.positionWall("bottom", wallPos)
|
|
355
|
+
.then([
|
|
356
|
+
cmds.state().alignPosition(),
|
|
357
|
+
// 反转速度放在then命令里同步执行,避免JS回调异步导致延迟
|
|
358
|
+
cmds.action(FreeMoveDef.KeepFlags.XY).scaleSpeed(undefined, -1),
|
|
359
|
+
(stateInfo) => {
|
|
360
|
+
// 命中下墙后重建基准和边界
|
|
361
|
+
applyVerticalBaseOffsetAndRebuild(-1, stateInfo);
|
|
362
|
+
},
|
|
363
|
+
]);
|
|
364
|
+
};
|
|
365
|
+
const buildVerticalReachCondition = (cmds) => {
|
|
366
|
+
return cmds
|
|
367
|
+
.condition({ multiTimes: true, specName: VERTICAL_REACH_POSITION_NAME })
|
|
368
|
+
// 仅监听 y=0 的穿越,x 不限制
|
|
369
|
+
.reachPosition(undefined, REACH_Y)
|
|
370
|
+
.then([
|
|
371
|
+
() => {
|
|
372
|
+
// 触达中点后回调 JS,测试 updateBaseOffset 对既有 condition 的影响
|
|
373
|
+
increaseVerticalCounter();
|
|
374
|
+
},
|
|
375
|
+
]);
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// 初始只注册一套左右墙条件;后续由撞边回调动态重建
|
|
379
|
+
const setupConditions = () => {
|
|
380
|
+
const localWalls = getLocalWallPos();
|
|
381
|
+
freeMoveControl.run((cmds) => [
|
|
382
|
+
// 场景重启时统一清理一次,再按“中点 + 左右墙”完整初始化
|
|
383
|
+
cmds.state().clearAllConditions(),
|
|
384
|
+
// 中点 reach 条件只在这里创建一次,后续撞边流程不删除/不重建
|
|
385
|
+
buildReachCondition(cmds),
|
|
386
|
+
buildLeftWallCondition(cmds, localWalls.left),
|
|
387
|
+
buildRightWallCondition(cmds, localWalls.right),
|
|
388
|
+
]);
|
|
389
|
+
};
|
|
390
|
+
const setupVerticalConditions = () => {
|
|
391
|
+
const localWalls = getLocalVerticalWallPos();
|
|
392
|
+
verticalFreeMoveControl.run((cmds) => [
|
|
393
|
+
// 场景重启时统一清理一次,再按“中点 + 上下墙”完整初始化
|
|
394
|
+
cmds.state().clearAllConditions(),
|
|
395
|
+
// 中点 reach 条件只在这里创建一次,后续撞边流程不删除/不重建
|
|
396
|
+
buildVerticalReachCondition(cmds),
|
|
397
|
+
buildTopWallCondition(cmds, localWalls.top),
|
|
398
|
+
buildBottomWallCondition(cmds, localWalls.bottom),
|
|
399
|
+
]);
|
|
400
|
+
};
|
|
401
|
+
|
|
402
|
+
const startMotion = () => {
|
|
403
|
+
freeMoveControl.run((cmds) => [
|
|
404
|
+
// 起始时左右gap相等,从中点出发
|
|
405
|
+
cmds.state().setStartPos(leftGap.value, 0),
|
|
406
|
+
cmds.action().setSpeed(-SPEED_X, 0),
|
|
407
|
+
]);
|
|
408
|
+
};
|
|
409
|
+
const startVerticalMotion = () => {
|
|
410
|
+
verticalFreeMoveControl.run((cmds) => [
|
|
411
|
+
// 起始时上下gap相等,从中点出发
|
|
412
|
+
cmds.state().setStartPos(0, topGap.value),
|
|
413
|
+
cmds.action().setSpeed(0, -SPEED_Y),
|
|
414
|
+
]);
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
onMounted(() => {
|
|
418
|
+
// 保证当前 scene 拿到焦点,便于直接测试键控/运动行为
|
|
419
|
+
focusHub.setFocus("TestScene3");
|
|
420
|
+
freeMoveControl = freeMoveRef.value?.control;
|
|
421
|
+
verticalFreeMoveControl = verticalFreeMoveRef.value?.control;
|
|
422
|
+
if (!freeMoveControl || !verticalFreeMoveControl) {
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
setupConditions();
|
|
427
|
+
setupVerticalConditions();
|
|
428
|
+
startMotion();
|
|
429
|
+
startVerticalMotion();
|
|
430
|
+
});
|
|
431
|
+
</script>
|