FloorSwitch.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <template>
  2. <div
  3. class="floor-switch"
  4. :class="{ disable: flying, showTours: showTours }"
  5. v-if="floors.length > 1 && mode != 'panorama'"
  6. >
  7. <ul>
  8. <li
  9. v-if="mode != 'floorplan'"
  10. :class="{ active: 'all' == floorId }"
  11. @click.stop="onGotoFloor('all')"
  12. >
  13. <b></b><span>全部</span>
  14. </li>
  15. <li
  16. v-for="item in floors"
  17. :key="item.id"
  18. :class="{ active: item.id == floorId }"
  19. @click.stop="onGotoFloor(item.id)"
  20. >
  21. <b></b><span>{{ item.name }}</span>
  22. </li>
  23. </ul>
  24. </div>
  25. </template>
  26. <script setup lang="ts">
  27. import { computed, unref, watch } from 'vue';
  28. import { useApp } from '/@/hooks/userApp';
  29. import { useSocket } from '/@/hooks/userSocket';
  30. import { useAppStore } from '/@/store/modules/app';
  31. import { useRtcStore } from '/@/store/modules/rtc';
  32. import { useSceneStore } from '/@/store/modules/scene';
  33. import { useTourStore } from '/@/store/modules/tour';
  34. const appStore = useAppStore();
  35. const sceneStore = useSceneStore();
  36. const tourStore = useTourStore();
  37. const mode = computed(() => appStore.mode);
  38. const flying = computed(() => appStore.flying);
  39. // eslint-disable-next-line vue/no-side-effects-in-computed-properties
  40. const floors = computed(() => sceneStore.floors.reverse());
  41. const floorId = computed(() => appStore.floorId);
  42. const showTours = computed(() => tourStore.showTours);
  43. const rtcStore = useRtcStore();
  44. const onGotoFloor = (id) => {
  45. // store.commit("setFloor", id);
  46. if (rtcStore.isLeader || appStore.isTourMode) {
  47. const { socket } = useSocket();
  48. appStore.setFloor(id);
  49. if (rtcStore.isLeader) {
  50. socket &&
  51. socket.emit('action', {
  52. type: 'sync-floor',
  53. data: {
  54. floorId: id,
  55. },
  56. });
  57. }
  58. }
  59. };
  60. useApp().then((sdk) =>
  61. sdk.Camera.on('mode.beforeChange', ({ toMode, floorIndex }) => {
  62. // store.commit("mode", toMode);
  63. appStore.setMode(toMode);
  64. if (toMode != 'dollhouse') {
  65. // store.commit("setFloorId", floorIndex);
  66. appStore.setFloorId(floorIndex);
  67. }
  68. }),
  69. );
  70. watch(
  71. () => [flying, mode],
  72. (val) => {
  73. if (!unref(val)[0].value && unref(val)[1].value === 'dollhouse') {
  74. console.log('dollhouse-all');
  75. setTimeout(() => {
  76. onGotoFloor('all');
  77. }, 50);
  78. }
  79. // if (!unref(val[0]) && unref(val[1]) === 'dollhouse') {
  80. // }
  81. },
  82. { deep: true, immediate: true },
  83. );
  84. </script>
  85. <style lang="scss" scoped>
  86. .floor-switch {
  87. pointer-events: all;
  88. position: absolute;
  89. bottom: calc(100% + 5px);
  90. left: 20px;
  91. z-index: 10;
  92. transition: bottom 0.1s;
  93. ul,
  94. li {
  95. padding: 0;
  96. margin: 0;
  97. }
  98. ul {
  99. position: relative;
  100. z-index: 2;
  101. }
  102. li {
  103. cursor: pointer;
  104. display: flex;
  105. align-items: center;
  106. position: relative;
  107. height: 50px;
  108. &:first-child {
  109. b {
  110. &::before {
  111. display: none;
  112. }
  113. }
  114. &.active {
  115. b {
  116. &::after {
  117. bottom: -10px;
  118. }
  119. }
  120. }
  121. }
  122. &:last-child {
  123. b {
  124. &::after {
  125. display: none;
  126. }
  127. }
  128. &.active {
  129. b {
  130. &::before {
  131. top: -10px;
  132. }
  133. }
  134. }
  135. }
  136. b {
  137. position: relative;
  138. width: 16px;
  139. height: 16px;
  140. background-color: #1c1c1c;
  141. border-radius: 50%;
  142. box-shadow: 0px 0px 2px 1px #404040;
  143. cursor: pointer;
  144. &::before {
  145. content: '';
  146. position: absolute;
  147. top: -5px;
  148. left: 50%;
  149. margin-left: -3px;
  150. background: #1c1c1c;
  151. width: 6px;
  152. height: 6px;
  153. }
  154. &::after {
  155. content: '';
  156. position: absolute;
  157. bottom: -5px;
  158. left: 50%;
  159. margin-left: -3px;
  160. background: #1c1c1c;
  161. width: 6px;
  162. height: 6px;
  163. }
  164. }
  165. span {
  166. margin-left: 10px;
  167. font-size: 14px;
  168. //color: #939393;
  169. cursor: pointer;
  170. color: #eeeeee;
  171. text-shadow: 0px 0px 4px rgba(0, 0, 0, 0.5);
  172. }
  173. &.active {
  174. b {
  175. left: -6px;
  176. width: 28px;
  177. height: 28px;
  178. border: solid 6px #1c1c1c;
  179. background-color: #404040;
  180. box-shadow: 0px 0px 2px 1px #404040;
  181. &::before {
  182. top: -10px;
  183. }
  184. &::after {
  185. bottom: -10px;
  186. }
  187. }
  188. span {
  189. margin-left: 0;
  190. position: relative;
  191. display: flex;
  192. align-items: center;
  193. justify-content: center;
  194. height: 32px;
  195. color: rgba(255, 255, 255, 0.88);
  196. border: solid 4px #1c1c1c;
  197. background-color: #404040;
  198. border-radius: 32px;
  199. box-shadow: 0px 0px 2px 1px #404040;
  200. padding: 0px 10px;
  201. text-shadow: none;
  202. &::before {
  203. content: '';
  204. position: absolute;
  205. left: -10px;
  206. background: #1c1c1c;
  207. width: 7px;
  208. height: 4px;
  209. box-shadow: -2px 0px 2px 1px #404040;
  210. }
  211. &::after {
  212. content: '';
  213. position: absolute;
  214. left: -16px;
  215. background: #1c1c1c;
  216. width: 6px;
  217. height: 11px;
  218. border-radius: 50%;
  219. }
  220. }
  221. }
  222. }
  223. &::after {
  224. content: '';
  225. position: absolute;
  226. left: 5px;
  227. top: 20px;
  228. bottom: 20px;
  229. width: 6px;
  230. background: #1c1c1c;
  231. box-shadow: 0px 0px 2px 1px #404040;
  232. z-index: 1;
  233. }
  234. }
  235. [is-mobile] {
  236. .floor-switch {
  237. bottom: 2.5rem;
  238. &.showTours {
  239. bottom: 5rem;
  240. }
  241. li {
  242. height: 45px;
  243. &:first-child {
  244. &.active {
  245. b {
  246. &::after {
  247. bottom: -6px;
  248. }
  249. }
  250. }
  251. }
  252. &:last-child {
  253. &.active {
  254. b {
  255. &::before {
  256. top: -6px;
  257. }
  258. }
  259. }
  260. }
  261. b {
  262. width: 14px;
  263. height: 14px;
  264. &::before {
  265. top: -3px;
  266. left: 50%;
  267. margin-left: -2px;
  268. width: 4px;
  269. height: 4px;
  270. }
  271. &::after {
  272. bottom: -3px;
  273. left: 50%;
  274. margin-left: -2px;
  275. width: 4px;
  276. height: 4px;
  277. }
  278. }
  279. span {
  280. font-size: 0.36842rem;
  281. }
  282. &.active {
  283. b {
  284. left: -3px;
  285. width: 20px;
  286. height: 20px;
  287. border: solid 4px #1c1c1c;
  288. &::before {
  289. top: -6px;
  290. }
  291. &::after {
  292. bottom: -6px;
  293. }
  294. }
  295. span {
  296. height: 30px;
  297. border: solid 3px #1c1c1c;
  298. border-radius: 30px;
  299. padding: 0px 10px;
  300. margin-left: 5px;
  301. &::before {
  302. left: -11px;
  303. width: 10px;
  304. height: 4px;
  305. box-shadow: -2px 0px 1px 1px #404040;
  306. }
  307. &::after {
  308. left: -14px;
  309. width: 3px;
  310. height: 6px;
  311. border-radius: 40%;
  312. }
  313. }
  314. }
  315. }
  316. &::after {
  317. left: 5px;
  318. top: 20px;
  319. bottom: 20px;
  320. width: 4px;
  321. }
  322. }
  323. @media (orientation: landscape) {
  324. .floor-switch {
  325. bottom: 1rem;
  326. li {
  327. span {
  328. font-size: 0.25rem;
  329. }
  330. }
  331. }
  332. }
  333. }
  334. </style>