Panel.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <template>
  2. <div class="panel" @mousemove.prevent @touchmove.prevent :style="{ top: panelNewTop == null ? null : `${panelNewTop}px` }">
  3. <slot></slot>
  4. </div>
  5. </template>
  6. <script setup>
  7. import { ref, onMounted, computed, watch, nextTick, defineProps } from "vue";
  8. import { useStore } from "vuex";
  9. const props = defineProps({
  10. isOpen: {
  11. default: false,
  12. },
  13. });
  14. watch(
  15. () => props.isOpen,
  16. () => {
  17. const $panel = document.querySelector(".panel");
  18. let orgTop = $panel.offsetTop;
  19. let newTop = window.innerHeight - $panel.clientHeight;
  20. let value = orgTop - newTop;
  21. if (value > 0) {
  22. openPanel($panel, orgTop, value);
  23. } else {
  24. resetPanel();
  25. }
  26. }
  27. );
  28. const panelNewTop = ref(null);
  29. const panelOrgTop = ref(0);
  30. const store = useStore();
  31. const resetPanel = () => {
  32. if (panelOrgTop.value > 0) {
  33. KanKan.Animate.transitions.start((progress) => {
  34. const $panel = document.querySelector(".panel");
  35. if (!$panel) {
  36. return
  37. }
  38. let orgTop = $panel.offsetTop;
  39. let newTop = panelOrgTop.value;
  40. let value = orgTop - newTop;
  41. panelNewTop.value = orgTop - value * progress;
  42. const $color = $panel.querySelectorAll(".color");
  43. $color.forEach((item) => {
  44. item.style.backgroundColor = `rgba(0, 0, 0, ${0.2})`;
  45. });
  46. }, 200);
  47. }
  48. };
  49. const openPanel = ($panel, orgTop, value) => {
  50. KanKan.Animate.transitions.start((progress) => {
  51. panelNewTop.value = orgTop - value * progress;
  52. let opc = progress;
  53. if (opc < 0.2) {
  54. opc = 0.2;
  55. } else if (opc > 0.5) {
  56. opc = 0.5;
  57. }
  58. const $color = $panel.querySelectorAll(".color");
  59. $color.forEach((item) => {
  60. item.style.backgroundColor = `rgba(0, 0, 0, ${opc})`;
  61. });
  62. }, 200);
  63. };
  64. onMounted(() => {
  65. nextTick(() => {
  66. document.querySelector(".player").addEventListener("touchstart", () => {
  67. resetPanel();
  68. // openPanel();
  69. });
  70. });
  71. const $panel = document.querySelector(".panel");
  72. const $color = $panel.querySelectorAll(".color");
  73. $panel.addEventListener("touchstart", down, false);
  74. $panel.addEventListener("mousedown", down, false);
  75. panelOrgTop.value = $panel.offsetTop;
  76. let pos = {
  77. top: panelOrgTop.value,
  78. };
  79. let timing = null;
  80. function down(e) {
  81. e.stopPropagation();
  82. pos.new = ((e.touches && e.touches[0]) || e).clientY;
  83. pos.org = $panel.offsetTop;
  84. pos.eHeight = $panel.clientHeight;
  85. pos.wHeight = window.innerHeight;
  86. $panel.addEventListener("touchmove", move, false);
  87. $panel.addEventListener("mousemove", move, false);
  88. $panel.addEventListener("touchend", up, false);
  89. $panel.addEventListener("mouseup", up, false);
  90. store.commit("SetPlayerOptions", {
  91. showMap: true,
  92. showToolbar: true,
  93. showDescription: false,
  94. });
  95. }
  96. function move(e) {
  97. e.stopPropagation();
  98. let top = ((e.touches && e.touches[0]) || e).clientY + pos.org - pos.new;
  99. let opc = (pos.wHeight - top) / pos.eHeight;
  100. if (opc < 0.2) {
  101. opc = 0.2;
  102. } else if (opc > 0.5) {
  103. opc = 0.5;
  104. }
  105. // if (top > pos.top) {
  106. // top = pos.top;
  107. // }
  108. if (top + pos.eHeight < pos.wHeight) {
  109. top = pos.wHeight - pos.eHeight;
  110. } else if (top > panelOrgTop.value) {
  111. top = panelOrgTop.value;
  112. }
  113. $color.forEach((item) => {
  114. item.style.backgroundColor = `rgba(0, 0, 0, ${opc})`;
  115. });
  116. panelNewTop.value = top;
  117. if (timing == null) {
  118. timing = Date.now();
  119. }
  120. }
  121. function up(e) {
  122. $panel.removeEventListener("touchmove", move, false);
  123. $panel.removeEventListener("mousemove", move, false);
  124. $panel.removeEventListener("touchend", up, false);
  125. $panel.removeEventListener("mouseup", up, false);
  126. pos.end = ((e.changedTouches && e.changedTouches[0]) || e).clientY;
  127. if (Date.now() - timing < 500) {
  128. let diff = pos.end - pos.new;
  129. let orgTop = 0;
  130. let newTop = 0;
  131. if (Math.abs(diff) > 5) {
  132. let value = 0;
  133. if (diff > 0) {
  134. orgTop = $panel.offsetTop;
  135. newTop = panelOrgTop.value;
  136. value = orgTop - newTop;
  137. } else {
  138. orgTop = $panel.offsetTop;
  139. newTop = pos.wHeight - pos.eHeight;
  140. value = orgTop - newTop;
  141. }
  142. KanKan.Animate.transitions.start((progress) => {
  143. panelNewTop.value = orgTop - value * progress;
  144. let opc = (pos.wHeight - panelNewTop.value) / pos.eHeight;
  145. if (opc < 0.2) {
  146. opc = 0.2;
  147. } else if (opc > 0.5) {
  148. opc = 0.5;
  149. }
  150. $color.forEach((item) => {
  151. item.style.backgroundColor = `rgba(0, 0, 0, ${opc})`;
  152. });
  153. }, 200);
  154. }
  155. }
  156. timing = null;
  157. }
  158. });
  159. </script>
  160. <style lang="scss" scoped>
  161. .panel {
  162. position: fixed;
  163. top: calc(100% - 90px);
  164. left: 0.4rem;
  165. right: 0.4rem;
  166. z-index: 22;
  167. }
  168. </style>