index.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <template>
  2. <div class="AEROSPACE2023" @touchmove="touchmove">
  3. <playBtn url="https://cxzx.smcic.net/topic/tool/media/bgmaerospace2023.mp3" />
  4. <div ref="main" class="page" @touchstart="touchstart" @touchend="touchend">
  5. <page0
  6. :class="{
  7. animate__animated: page === 0,
  8. animate__fadeInUp: isUp && page === 0,
  9. animate__fadeInDown: !isUp && page === 0,
  10. }"
  11. v-if="page === 0"
  12. />
  13. <page1
  14. :class="{
  15. animate__animated: page === 1,
  16. animate__fadeInUp: isUp && page === 1,
  17. animate__fadeInDown: !isUp && page === 1,
  18. }"
  19. v-if="page === 1"
  20. />
  21. <page3
  22. :class="{
  23. animate__animated: page === 2,
  24. animate__fadeInUp: isUp && page === 2,
  25. animate__fadeInDown: !isUp && page === 2,
  26. }"
  27. v-if="page === 2"
  28. />
  29. <page4
  30. :class="{
  31. animate__animated: page === 3,
  32. animate__fadeInUp: isUp && page === 3,
  33. animate__fadeInDown: !isUp && page === 3,
  34. }"
  35. v-if="page === 3"
  36. />
  37. <page5
  38. :class="{
  39. animate__animated: page === 4,
  40. animate__fadeInUp: isUp && page === 4,
  41. animate__fadeInDown: !isUp && page === 4,
  42. }"
  43. v-if="page === 4"
  44. />
  45. <page6
  46. :class="{
  47. animate__animated: page === 5,
  48. animate__fadeInUp: isUp && page === 5,
  49. animate__fadeInDown: !isUp && page === 5,
  50. }"
  51. v-if="page === 5"
  52. />
  53. </div>
  54. </div>
  55. </template>
  56. <script setup>
  57. import { ref } from 'vue';
  58. import page0 from './page0.vue';
  59. import page1 from './page1.vue';
  60. import page3 from './page3.vue';
  61. import page4 from './page4.vue';
  62. import page5 from './page5.vue';
  63. import page6 from './page6.vue';
  64. import playBtn from '../../components/playBtn.vue';
  65. import 'animate.css';
  66. // import { onMounted, reactive } from "vue";
  67. // import { isIpad, isIpod, isIphone } from "../../utils/isTerminal";
  68. /**
  69. * window.$originData.orginParames.title 页面标题
  70. * window.$originData.orginParames.parameters 固定参数值
  71. * window.$originData.urlParames url参数
  72. */
  73. // console.log(window.$originData);
  74. // const play_stats = ref(false);
  75. const main = ref(null);
  76. const page = ref(0);
  77. const isUp = ref(true);
  78. let startStats = 0;
  79. let time = Date.now();
  80. let startY = 0;
  81. const isChangePage = cha => {
  82. let out = false; // false 不能翻页 true 能翻页
  83. let sondiv = getinnerele();
  84. // 视口高度 main.value.offsetHeight
  85. // 内容高度 sondiv.offsetHeight
  86. // 视口基本大于内容 则可以翻页
  87. /**
  88. * 初始化y值或结束y值不在翻页区间,则不能翻页
  89. * 翻页区间是scrolltop 10 以内 和 底部剩余空间10 以内
  90. */
  91. let h = main.value.offsetHeight + main.value.scrollTop;
  92. // if (Math.pow(cha, 2) < 6400) out = true;
  93. let timeRange = Date.now() - time > 50;
  94. if (cha < -80 && startStats < 10 && timeRange) {
  95. // 下滑
  96. /**
  97. * 下滑初始滚动小于10 -翻页
  98. */
  99. out = true;
  100. } else {
  101. // 上滑
  102. /**
  103. * 下滑剩余小于10 -翻页
  104. */
  105. if (sondiv.offsetHeight - h < 10 && cha > 80 && timeRange) out = true;
  106. }
  107. return out;
  108. };
  109. const touchstart = e => {
  110. time = Date.now();
  111. startStats = main.value.scrollTop;
  112. startY = e.changedTouches[0].clientY;
  113. };
  114. const touchend = e => {
  115. const cha = startY - e.changedTouches[0].clientY;
  116. if (!isChangePage(cha)) return;
  117. // cha > 0 向上滑动手指
  118. // cha < 0 向下滑动手指
  119. // 初始位置滚动为0的,则判断距离25即可
  120. // 距离足够则滑动到下一页;
  121. let n = cha > 0 ? 1 : -1;
  122. let dn = n + page.value;
  123. let len = 5;
  124. // if (dn < 0) dn = len;
  125. // if (dn > len) dn = 0;
  126. if (dn < 0) return;
  127. if (dn > len) return;
  128. isUp.value = n === 1;
  129. page.value = dn;
  130. main.value.scrollTop = 0;
  131. };
  132. const touchmove = e => {
  133. const cha = startY - e.changedTouches[0].clientY;
  134. if (main.value.scrollTop <= 1 && cha < 0) e.preventDefault();
  135. const ele = getinnerele();
  136. if (
  137. cha > 0 &&
  138. main.value.offsetHeight + main.value.scrollTop >= ele.offsetHeight
  139. )
  140. e.preventDefault();
  141. };
  142. const getinnerele = () => {
  143. let nodes = main.value.childNodes || [];
  144. return nodes[page.value];
  145. };
  146. </script>
  147. <style lang="scss">
  148. // 动画库
  149. @import url(./sass/animation.scss);
  150. // 字体库
  151. @import url(./sass/base.scss);
  152. // @import url(https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css);
  153. .AEROSPACE2023 {
  154. width: 100%;
  155. height: 100vh;
  156. overflow: hidden;
  157. background-image: url(./img/background.jpg);
  158. background-size: 100% 100%;
  159. max-width: 750px;
  160. min-width: 330px;
  161. margin: 0 auto;
  162. display: block;
  163. position: relative;
  164. .imgbtn {
  165. position: absolute;
  166. top: 16px;
  167. right: 16px;
  168. z-index: 10;
  169. }
  170. .page {
  171. width: 100%;
  172. height: 100vh;
  173. margin: 0 auto;
  174. overflow-y: auto;
  175. & > div {
  176. width: 100%;
  177. }
  178. }
  179. .excess-enter-active,
  180. .excess-leave-active {
  181. transition: opacity 0.1s ease;
  182. }
  183. .excess-enter-from,
  184. .excess-leave-to {
  185. opacity: 0;
  186. }
  187. }
  188. </style>