mainLand.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758
  1. <template>
  2. <view class="main-land-container">
  3. <!-- <view class="scroll-container" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" >
  4. <view class="background" :style="{ transform: `translateX(${translateX}px)` }">
  5. <image class="island-image" src="/static/island/island.png" mode="heightFix"></image>
  6. </view>
  7. </view> -->
  8. <!-- 第三层:背景 -->
  9. <view class="background-layer"></view>
  10. <!-- 第二层:地图 -->
  11. <view class="map-layer" id="mapLayer" :style="{ transform: `translateX(${translateX}px)` }"
  12. @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @mousedown="onmousedown"
  13. @mousemove="onmousemove" @mouseup="onmouseup">
  14. <!-- 这里可以放置地图元素(示例:一个方块) -->
  15. <!-- <view style="position: absolute; top: 30%; left: 30%; width: 100px; height: 100px; background: green;"></view> -->
  16. <image class="island-image" src="/static/island/mainLand.png" mode="widthFix"
  17. style="width:2048rpx; bottom: 0rpx;left: 0rpx; position: absolute;"></image>
  18. <!-- <view style="position: absolute;width: 300rpx;left: 280rpx; bottom:230rpx;align-items: center;">
  19. <image class="house-image" src="/static/island/building/4.png" mode="widthFix" style="width:300rpx; position: static;" @click="onHouseClick" :animation="houseAnimationData"> </image>
  20. </view> -->
  21. <view style="position: absolute;width: 360rpx;left:782rpx; bottom:385rpx;align-items: center;">
  22. <view style="position: relative;">
  23. <image class="farm-image" src="/static/island/building/3.png" mode="widthFix"
  24. style="width:360rpx; position: static;" @click="onFarmClick" :animation="farmAnimationData">
  25. </image>
  26. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx;display: flex; align-items: center; justify-content: center; font-weight: bold;">花 田</view>
  27. </view>
  28. </view>
  29. <view style="position: absolute;width: 360rpx;left: 335rpx; bottom:835rpx;align-items: center;">
  30. <view style="position: relative;">
  31. <image class="mine-image" src="/static/island/building/4.png" mode="widthFix"
  32. style="width:360rpx; position: static;"> </image>
  33. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">矿 场</view>
  34. </view>
  35. </view>
  36. <view style="position: absolute;width: 360rpx;left: 782rpx; bottom:720rpx;align-items: center;">
  37. <view style="position: relative;">
  38. <image class="hall-image" src="/static/island/building/5.png" mode="widthFix"
  39. style="width:360rpx; position: static;"> </image>
  40. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">市政厅</view>
  41. </view>
  42. </view>
  43. <view style="position: absolute;width: 360rpx;left: 248rpx; bottom:488rpx;align-items: center;">
  44. <view style="position: relative;">
  45. <image class="wood-image" src="/static/island/building/6.png" mode="widthFix"
  46. style="width:360rpx; position: static;"> </image>
  47. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">伐木场</view>
  48. </view>
  49. </view>
  50. <view style="position: absolute;width: 360rpx;left: 910rpx; bottom:108rpx;align-items: center;">
  51. <view style="position: relative;">
  52. <image class="shop-image" src="/static/island/building/2.png" mode="widthFix"
  53. style="width:360rpx; position: static;" @click="onShopClick" :animation="shopAnimationData">
  54. </image>
  55. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">花 店</view>
  56. </view>
  57. </view>
  58. <view style="position: absolute;width: 360rpx;left: 1498rpx; bottom:75rpx;align-items: center;">
  59. <view style="position: relative;">
  60. <image class="airport-image" src="/static/island/building/7.png" mode="widthFix"
  61. style="width:360rpx; position: static;"> </image>
  62. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">机 场</view>
  63. </view>
  64. </view>
  65. <view style="position: absolute;width: 360rpx;left: 1400rpx; bottom:380rpx;align-items: center;">
  66. <view style="position: relative;">
  67. <image class="house-image" src="/static/island/building/1.png" mode="widthFix"
  68. style="width:360rpx; position: static;" @click="onHouseClick" :animation="houseAnimationData">
  69. </image>
  70. <view style="position: absolute; left: 35rpx; bottom: 135rpx; width: 45rpx; height: 130rpx; background: rgba(255,236,219,0.95); box-shadow: 1rpx -1rpx 2rpx 0rpx rgba(0,0,0,0.2); border-radius: 32rpx 32rpx 32rpx 32rpx; border: 2rpx solid #DEB691; writing-mode: vertical-lr; color: #683830; font-size: 28rpx; display: flex; align-items: center; justify-content: center; font-weight: bold;">材料店</view>
  71. </view>
  72. </view>
  73. <!-- 引导箭头 -->
  74. <view class="guide-arrow" v-if="showGuideArrow" :style="{ left: guideArrowPosition.x + 'rpx', bottom: guideArrowPosition.y + 'rpx', transform: `rotate(${guideArrowPosition.r}deg)` }">
  75. <image src="/static/island/arrow.png" mode="aspectFit"></image>
  76. </view>
  77. <!-- 回家箭头 -->
  78. <view class="home-arrow" @click="goHome" :animation="homeArrowAnimation"
  79. :style="{ opacity: homeArrowVisible ? 1 : 0 }">
  80. <!-- <image src="/static/island/home_arrow.png" mode="widthFix" style="width: 100rpx;"></image> -->
  81. <view class="arrow"></view>
  82. <text class="home-text">回家</text>
  83. </view>
  84. </view>
  85. <!-- 第一层:UI -->
  86. <view class="ui-layer">
  87. <view class="ui-content">
  88. <!-- 添加货币计数器 -->
  89. <view class="currency-display">
  90. <view class="currency-item">
  91. <image src="/static/island/UI/wd_icon_coin.png" mode="widthFix" class="currency-icon"></image>
  92. <text class="currency-value">{{userInfo.num_gmd}}</text>
  93. </view>
  94. <view class="currency-item">
  95. <image src="/static/island/UI/wd_icon_xingyuan.png" mode="widthFix" class="currency-icon">
  96. </image>
  97. <text class="currency-value">{{userInfo.num_gmg}}</text>
  98. </view>
  99. </view>
  100. <view class="ui-buttons">
  101. <image src="/static/island/icon_backpack.png" mode="widthFix" style="width:100rpx"
  102. @click="showInventory" class="ui-icon-button"></image>
  103. <!-- <button class="ui-button" @click="showCharacter">角色</button>
  104. <button class="ui-button" @click="showShop">商店</button> -->
  105. </view>
  106. </view>
  107. </view>
  108. <!-- 对话框组件 -->
  109. <backpack-dialog :visible.sync="inventoryVisible" @close="onInventoryClose"></backpack-dialog>
  110. <character-dialog :visible.sync="characterVisible" @close="onCharacterClose"></character-dialog>
  111. <shop-dialog :visible.sync="shopVisible" :shopName="currentShopName" @close="onShopClose" @buy="onShopBuy"></shop-dialog>
  112. <hua-tian :visible.sync="huaTianVisible" @close="onHuaTianClose" ref="huaTian"></hua-tian>
  113. <task-dialog :visible.sync="taskDialogVisible" @close="onTaskDialogClose" type="huatian"></task-dialog>
  114. <!-- 引导对话组件 -->
  115. <talk-guide
  116. v-if="showTalkGuide"
  117. :guide-data="currentTalkData"
  118. :player-name="playerName"
  119. :visible="showTalkGuide"
  120. @talk-complete="onTalkComplete"
  121. ></talk-guide>
  122. <!-- 引导管理器 -->
  123. <guide-manager ref="guideManager"></guide-manager>
  124. </view>
  125. </template>
  126. <script>
  127. import BackpackDialog from '@/components/dialogs/BackpackDialog.vue'
  128. import CharacterDialog from '@/components/dialogs/CharacterDialog.vue'
  129. import ShopDialog from '@/components/dialogs/ShopDialog.vue'
  130. import HuaTian from './HuaTian.vue'
  131. import TaskDialog from './TaskDialog.vue'
  132. import TalkGuide from './talkGuide.vue'
  133. import GuideManager from '@/components/guide/GuideManager.vue'
  134. export default {
  135. components: {
  136. BackpackDialog,
  137. CharacterDialog,
  138. ShopDialog,
  139. HuaTian,
  140. TaskDialog,
  141. TalkGuide,
  142. GuideManager
  143. },
  144. data() {
  145. return {
  146. // // 背景位置控制
  147. translateX: -200,
  148. startX: 0,
  149. currentX: 0,
  150. isDragging: false,
  151. // maxTranslate: 0,
  152. userInfo: {
  153. num_gmd: 0,
  154. num_gmg: 0,
  155. },
  156. moneyTimer: null, // 添加定时器变量
  157. // // 获取屏幕宽度和背景宽度
  158. screenWidth: 0,
  159. backgroundWidth: 0,
  160. islandHeight: 0,
  161. houseAnimationData: {},
  162. farmAnimationData: {},
  163. shopAnimationData: {},
  164. houseAnimating: false,
  165. farmAnimating: false,
  166. shopAnimating: false,
  167. baseTranslate: {
  168. x: -50,
  169. y: 50
  170. },
  171. inventoryVisible: false,
  172. characterVisible: false,
  173. shopVisible: false,
  174. huaTianVisible: false,
  175. taskDialogVisible: false,
  176. homeArrowAnimation: {},
  177. homeArrowAnimating: false,
  178. homeArrowVisible: false,
  179. currentShopName: '商店',
  180. // 引导相关数据
  181. showTalkGuide: false,
  182. currentTalkData: [],
  183. playerName: '梦幻',
  184. // 引导箭头相关
  185. showGuideArrow: false,
  186. guideArrowPosition: { x: 0, y: 0, r: 0 }
  187. }
  188. },
  189. onLoad() {
  190. let self = this;
  191. // 获取屏幕宽度
  192. uni.getSystemInfo({
  193. success: (res) => {
  194. self.screenWidth = res.windowWidth;
  195. console.log('屏幕宽度:', self.screenWidth);
  196. }
  197. });
  198. this.getUserMoney();
  199. // 启动定时器,每2秒更新一次铃钱
  200. this.moneyTimer = setInterval(() => {
  201. this.getUserMoney();
  202. }, 2000);
  203. },
  204. onShow() {
  205. // 检查是否需要显示引导
  206. this.checkAndShowGuide('mainLand');
  207. },
  208. onReady() {
  209. // 在组件渲染完成后获取图片尺寸
  210. setTimeout(() => {
  211. this.getImageSize();
  212. // 延迟1秒后显示箭头并开始动画
  213. setTimeout(() => {
  214. this.homeArrowVisible = true;
  215. this.startHomeArrowAnimation();
  216. }, 1000);
  217. }, 300);
  218. },
  219. onUnload() {
  220. // 清除定时器
  221. if (this.moneyTimer) {
  222. clearInterval(this.moneyTimer);
  223. this.moneyTimer = null;
  224. }
  225. },
  226. methods: {
  227. loadData() {
  228. // 可以在这里加载其他数据
  229. },
  230. getImageSize() {
  231. const query = uni.createSelectorQuery().in(this);
  232. query.select('.island-image').boundingClientRect(data => {
  233. if (data) {
  234. // 获取岛屿图片的宽度和高度
  235. this.backgroundWidth = data.width;
  236. this.islandHeight = data.height;
  237. // this.backgroundWidth = 1536;
  238. // this.islandHeight = 1024;
  239. // 设置背景高度为岛屿高度的两倍(在CSS中实现)
  240. // 计算最大可移动距离
  241. this.maxTranslate = this.backgroundWidth - this.screenWidth;
  242. // 初始位置居中
  243. // this.translateX = -this.maxTranslate / 2;
  244. // 打印调试信息
  245. // console.log('屏幕宽度:', this.screenWidth);
  246. // console.log('背景宽度:', this.backgroundWidth);
  247. // console.log('岛屿高度:', this.islandHeight);
  248. // console.log('屏幕宽度:',this.screenWidth);
  249. // console.log('最大可移动距离:',this.maxTranslate);
  250. // console.log('岛屿data:', data);
  251. } else {
  252. console.error('未能获取岛屿图片的尺寸');
  253. }
  254. }).exec();
  255. },
  256. // 触摸开始
  257. touchStart(e) {
  258. // console.log('----------- touchStart');
  259. this.startX = e.touches[0].clientX;
  260. this.currentX = this.translateX;
  261. console.log('this.startX =', this.startX);
  262. console.log('this.currentX =', this.currentX);
  263. },
  264. // 触摸移动
  265. touchMove(e) {
  266. console.log('----------- touchMove');
  267. const moveX = e.touches[0].clientX - this.startX;
  268. let newTranslateX = this.currentX + moveX;
  269. // 限制移动范围,不让背景两侧露出
  270. if (newTranslateX > 0) {
  271. newTranslateX = 0;
  272. } else if (newTranslateX < -this.maxTranslate) {
  273. newTranslateX = -this.maxTranslate;
  274. }
  275. this.translateX = newTranslateX;
  276. console.log('moveX =', moveX);
  277. console.log('this.translateX =', this.translateX);
  278. },
  279. // 触摸结束
  280. touchEnd() {
  281. console.log('----------- touchEnd');
  282. this.currentX = this.translateX;
  283. console.log('this.currentX =', this.currentX);
  284. },
  285. onmousedown(e) {
  286. console.log('----------- onmousedown');
  287. console.log('----------- e', e);
  288. this.isDragging = true;
  289. this.startX = e.clientX;
  290. this.currentX = this.translateX;
  291. mapLayer.style.cursor = 'grabbing';
  292. },
  293. onmousemove(e) {
  294. if (this.isDragging) {
  295. console.log('----------- onmousemove');
  296. const moveX = e.clientX - this.startX;
  297. let newTranslateX = this.currentX + moveX;
  298. //限制移动范围,不让背景两侧露出
  299. if (newTranslateX > 0) {
  300. newTranslateX = 0;
  301. } else if (newTranslateX < -this.maxTranslate) {
  302. newTranslateX = -this.maxTranslate;
  303. }
  304. this.translateX = newTranslateX;
  305. console.log('moveX =', moveX);
  306. console.log('this.translateX =', this.translateX);
  307. }
  308. },
  309. onmouseup(e) {
  310. console.log('----------- onmouseup');
  311. this.isDragging = false;
  312. mapLayer.style.cursor = 'grab';
  313. },
  314. onHouseClick(event) {
  315. if (this.houseAnimating) return;
  316. // 处理点击事件
  317. console.log('house clicked!');
  318. // 播放房屋的点击动画
  319. this.playAnimation('house');
  320. // 设置商店名称为"房屋商店"
  321. this.currentShopName = '材料商店';
  322. this.shopVisible = true;
  323. },
  324. onFarmClick(event) {
  325. if (this.farmAnimating) return;
  326. // 处理点击事件
  327. console.log('farm clicked!111');
  328. // 播放大厅的点击动画
  329. this.playAnimation('farm');
  330. // 打开花田对话框
  331. this.huaTianVisible = true;
  332. // 将mainLand传递给HuaTian组件
  333. this.$refs.huaTian && this.$refs.huaTian.setMainLand(this);
  334. // 检查是否需要显示引导
  335. this.checkAndShowGuide('mainLand_farm');
  336. },
  337. onShopClick(event) {
  338. if (this.shopAnimating) return;
  339. // 处理点击事件
  340. console.log('shop clicked!');
  341. // 播放商店的点击动画
  342. this.playAnimation('shop');
  343. // 设置商店名称为"花店"
  344. this.currentShopName = '花店';
  345. // 打开商店对话框
  346. this.shopVisible = true;
  347. },
  348. playAnimation(type) {
  349. let self = this;
  350. // 根据类型设置对应的动画状态
  351. if (type === 'house') {
  352. this.houseAnimating = true;
  353. } else if (type === 'farm') {
  354. this.farmAnimating = true;
  355. } else if (type === 'shop') {
  356. this.shopAnimating = true;
  357. }
  358. // 创建动画实例
  359. const animation = uni.createAnimation({
  360. duration: 400,
  361. timingFunction: 'ease',
  362. });
  363. // 定义果冻动画序列
  364. animation.scale(0.95).step({
  365. duration: 100
  366. })
  367. .scale(1.05).step({
  368. duration: 100
  369. })
  370. .scale(0.98).step({
  371. duration: 100
  372. })
  373. .scale(1).step({
  374. duration: 100
  375. });
  376. // 根据类型应用动画到对应的元素
  377. if (type === 'house') {
  378. this.houseAnimationData = animation.export();
  379. } else if (type === 'farm') {
  380. this.farmAnimationData = animation.export();
  381. } else if (type === 'shop') {
  382. this.shopAnimationData = animation.export();
  383. }
  384. // 动画结束后重置状态
  385. setTimeout(() => {
  386. if (type === 'house') {
  387. self.houseAnimating = false;
  388. } else if (type === 'farm') {
  389. self.farmAnimating = false;
  390. } else if (type === 'shop') {
  391. self.shopAnimating = false;
  392. }
  393. }, 800);
  394. },
  395. showInventory() {
  396. console.log('Opening inventory...')
  397. this.inventoryVisible = true
  398. },
  399. onInventoryClose() {
  400. console.log('Closing inventory...')
  401. this.inventoryVisible = false
  402. },
  403. showCharacter() {
  404. console.log('Opening character...')
  405. this.characterVisible = true
  406. },
  407. onCharacterClose() {
  408. console.log('Closing character...')
  409. this.characterVisible = false
  410. },
  411. showShop() {
  412. console.log('Opening shop...')
  413. this.shopVisible = true
  414. },
  415. onShopClose() {
  416. console.log('Closing shop...')
  417. this.shopVisible = false
  418. },
  419. onShopBuy(item) {
  420. console.log('Buying item:', item)
  421. },
  422. onHuaTianClose() {
  423. console.log('Closing hua tian dialog...')
  424. this.huaTianVisible = false
  425. },
  426. startHomeArrowAnimation() {
  427. if (this.homeArrowAnimating) return;
  428. this.homeArrowAnimating = true;
  429. const animation = uni.createAnimation({
  430. duration: 1000,
  431. timingFunction: 'ease-in-out',
  432. });
  433. const animate = () => {
  434. if (!this.homeArrowAnimating) return;
  435. animation.translateY(-20).step({
  436. duration: 1000
  437. });
  438. this.homeArrowAnimation = animation.export();
  439. setTimeout(() => {
  440. animation.translateY(0).step({
  441. duration: 1000
  442. });
  443. this.homeArrowAnimation = animation.export();
  444. setTimeout(() => {
  445. if (this.homeArrowAnimating) {
  446. animate();
  447. }
  448. }, 1000);
  449. }, 1000);
  450. };
  451. animate();
  452. },
  453. goHome() {
  454. uni.navigateTo({
  455. url: '/pages/isLand/homeLand'
  456. });
  457. },
  458. // 打开任务对话框
  459. onTaskClick() {
  460. console.log('Opening task dialog...')
  461. this.taskDialogVisible = true
  462. },
  463. // 关闭任务对话框
  464. onTaskDialogClose() {
  465. console.log('Closing task dialog...')
  466. this.taskDialogVisible = false
  467. },
  468. // 获取用户铃钱
  469. getUserMoney() {
  470. uni.request({
  471. url: this.$apiHost + '/User/getinfo',
  472. method: 'GET',
  473. data: {
  474. uuid: getApp().globalData.uuid
  475. },
  476. header: {
  477. 'Content-Type': 'application/x-www-form-urlencoded',
  478. 'sign': getApp().globalData.headerSign,
  479. },
  480. success: (res) => {
  481. if (res.data) {
  482. console.log("res.getUserMoney", res.data)
  483. this.userInfo = res.data;
  484. }
  485. }
  486. })
  487. },
  488. // 检查并显示引导
  489. checkAndShowGuide(stageId) {
  490. console.log('checkAndShowGuide stageId :', stageId);
  491. // 延迟执行以确保DOM已经渲染
  492. setTimeout(() => {
  493. if (this.$refs.guideManager) {
  494. const hasGuide = this.$refs.guideManager.startGuide(stageId);
  495. console.log('checkAndShowGuide hasGuide :', hasGuide);
  496. if (hasGuide) {
  497. this.currentTalkData = this.$refs.guideManager.getCurrentTalkData();
  498. console.log('checkAndShowGuide currentTalkData :', this.currentTalkData);
  499. if (this.currentTalkData) {
  500. this.showTalkGuide = true;
  501. // 检查是否需要显示引导箭头
  502. this.checkAndShowGuideArrow();
  503. }else{
  504. console.log('currentTalkData err:', this.currentTalkData);
  505. }
  506. }
  507. }
  508. }, 200);
  509. },
  510. // 对话完成回调
  511. onTalkComplete() {
  512. // 调用引导管理器的下一步
  513. console.log('----------- onTalkComplete');
  514. this.$refs.guideManager && this.$refs.guideManager.nextStep();
  515. // 获取新的对话数据
  516. const newTalkData = this.$refs.guideManager.getCurrentTalkData();
  517. console.log('----------- onTalkComplete newTalkData:', newTalkData);
  518. if (newTalkData) {
  519. // 先隐藏对话组件
  520. this.showTalkGuide = false;
  521. // 更新对话数据
  522. this.currentTalkData = newTalkData;
  523. // 使用 nextTick 确保数据更新后再显示对话组件
  524. this.$nextTick(() => {
  525. this.showTalkGuide = true;
  526. // 检查是否需要显示引导箭头
  527. this.checkAndShowGuideArrow();
  528. });
  529. } else {
  530. // 如果没有新的对话数据,隐藏对话组件
  531. this.showTalkGuide = false;
  532. }
  533. },
  534. // 检查并显示引导箭头
  535. checkAndShowGuideArrow() {
  536. if (this.$refs.guideManager) {
  537. const arrowPosition = this.$refs.guideManager.getCurrentArrowPosition();
  538. console.log('----------- checkAndShowGuideArrow arrowPosition:', arrowPosition);
  539. if (arrowPosition) {
  540. // 显示引导箭头
  541. this.showGuideArrow = true;
  542. // 设置箭头位置
  543. this.guideArrowPosition = {
  544. x: arrowPosition.x,
  545. y: arrowPosition.y,
  546. r: arrowPosition.r || 0
  547. };
  548. console.log('----------- guideArrowPosition:', this.guideArrowPosition);
  549. console.log('----------- showGuideArrow:', this.showGuideArrow);
  550. } else {
  551. // 隐藏引导箭头
  552. this.showGuideArrow = false;
  553. }
  554. }
  555. }
  556. }
  557. }
  558. </script>
  559. <style lang="scss" scoped>
  560. @import './mainLand.scss';
  561. .ui-layer {
  562. position: fixed;
  563. top: 0;
  564. left: 0;
  565. right: 0;
  566. bottom: 0;
  567. pointer-events: none;
  568. z-index: 100;
  569. .ui-content {
  570. position: absolute;
  571. top: 20rpx;
  572. right: 20rpx;
  573. pointer-events: auto;
  574. z-index: 101;
  575. }
  576. .ui-buttons {
  577. display: flex;
  578. flex-direction: column;
  579. gap: 20rpx;
  580. .ui-icon-button {
  581. transition: transform 0.2s ease;
  582. &:active {
  583. transform: scale(0.9);
  584. opacity: 0.8;
  585. }
  586. }
  587. .ui-button {
  588. // background: rgba(255, 255, 255, 0.9);
  589. // border: none;
  590. width: 120rpx;
  591. padding: 16rpx 32rpx;
  592. border-radius: 8rpx;
  593. font-size: 28rpx;
  594. color: #333;
  595. // box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  596. min-width: 120rpx;
  597. &:active {
  598. opacity: 0.8;
  599. transform: scale(0.95);
  600. }
  601. }
  602. .backpack-button {
  603. background-image: url('/static/island/icon_backpack.png');
  604. background-size: cover;
  605. background-position: center;
  606. background-repeat: no-repeat;
  607. }
  608. }
  609. }
  610. .map-layer {
  611. position: relative;
  612. z-index: 1;
  613. cursor: grab;
  614. &:active {
  615. cursor: grabbing;
  616. }
  617. }
  618. .guide-arrow {
  619. position: absolute;
  620. z-index: 10;
  621. width: 100rpx;
  622. height: 100rpx;
  623. display: flex;
  624. justify-content: center;
  625. align-items: center;
  626. pointer-events: none; /* 防止箭头阻挡点击事件 */
  627. image {
  628. width: 100rpx;
  629. height: 100rpx;
  630. animation: pulse 1.5s infinite; /* 添加脉冲动画 */
  631. }
  632. }
  633. @keyframes pulse {
  634. 0% {
  635. transform: scale(1);
  636. opacity: 1;
  637. }
  638. 50% {
  639. transform: scale(1.2);
  640. opacity: 0.8;
  641. }
  642. 100% {
  643. transform: scale(1);
  644. opacity: 1;
  645. }
  646. }
  647. .home-arrow {
  648. // background: rgba(255, 255, 255, 0.9);
  649. position: absolute;
  650. left: 40rpx; // 调整到左边位置
  651. bottom: 460rpx;
  652. display: flex;
  653. flex-direction: column;
  654. align-items: center;
  655. cursor: pointer;
  656. z-index: 10;
  657. transition: opacity 0.5s ease-in-out; // 添加淡入效果
  658. .arrow {
  659. content: '';
  660. display: block;
  661. width: 60rpx;
  662. height: 60rpx;
  663. background: url('/static/island/arrow.png') no-repeat center center;
  664. background-size: contain;
  665. transform: rotate(90deg);
  666. }
  667. .home-text {
  668. color: #ffffff;
  669. font-size: 32rpx;
  670. text-shadow: 2rpx 2rpx 4rpx rgba(0, 0, 0, 0.5);
  671. margin-top: 10rpx;
  672. }
  673. }
  674. </style>