index.tsx 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import {
  2. toolOpen,
  3. whitePenShow,
  4. penShow,
  5. isPlay,
  6. isHidden
  7. } from './globalTools';
  8. import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue';
  9. import { useRoute } from 'vue-router';
  10. import styles from './index.module.less';
  11. import iconTool from './images/icon-tool.png';
  12. import iconNote from './images/icon-note.png';
  13. import iconWhiteboard from './images/icon-whiteboard.png';
  14. import gArrowRight from './images/g-arrow-right.png';
  15. import Pen from '@/views/coursewarePlay/component/tools/pen';
  16. import { nextTick } from 'process';
  17. export default defineComponent({
  18. name: 'globalTools',
  19. setup() {
  20. const isMask = ref(false); // 是否显示遮罩层,为了处理云教练里面拖动不了的问题
  21. const route = useRoute();
  22. // watch(
  23. // () => route.path,
  24. // () => {
  25. // handleStatus();
  26. // }
  27. // );
  28. const iconToolsDom = ref<HTMLDivElement>();
  29. const expendToolsDom = ref<HTMLDivElement>();
  30. function openTool() {
  31. if (isLock) return;
  32. isPlay.value = false
  33. toolOpen.value = !toolOpen.value;
  34. }
  35. function openType(type: 'note' | 'whiteboard') {
  36. if (isLock) return;
  37. if (type === 'note') {
  38. penShow.value = true;
  39. isHidden.value = true;
  40. } else if (type === 'whiteboard') {
  41. whitePenShow.value = true;
  42. isHidden.value = true;
  43. }
  44. }
  45. function handleStatus() {
  46. isHidden.value = route.path === '/login' ? true : false;
  47. }
  48. function computePos(type: 'width' | 'height', value: number) {
  49. const clientNum =
  50. type == 'width'
  51. ? document.documentElement.clientWidth
  52. : document.documentElement.clientHeight;
  53. console.log(value, clientNum)
  54. return {
  55. pos: ((clientNum - value) / 2).toFixed(5)
  56. };
  57. }
  58. /* 拖拽还没有兼容rem */
  59. let isLock = false;
  60. let toolMoveY = 0; // 移动的距离
  61. function drag(el: HTMLElement) {
  62. function mousedown(e: MouseEvent | TouchEvent) {
  63. const isTouchEv = isTouchEvent(e);
  64. const event = isTouchEv ? e.touches[0] : e;
  65. isLock = false;
  66. isMask.value = true;
  67. const parentElement = el;
  68. const parentElementRect = parentElement.getBoundingClientRect();
  69. const downX = event.clientX;
  70. const downY = event.clientY;
  71. // const clientWidth = document.documentElement.clientWidth
  72. const clientHeight = document.documentElement.clientHeight;
  73. // const minLeft = 0
  74. const minTop = 0;
  75. // const maxLeft = clientWidth - parentElementRect.width
  76. const maxTop = clientHeight - parentElementRect.height;
  77. function onMousemove(e: MouseEvent | TouchEvent) {
  78. const event = isTouchEvent(e) ? e.touches[0] : e;
  79. // let moveX = parentElementRect.left + (e.clientX - downX)
  80. let moveY = parentElementRect.top + (event.clientY - downY);
  81. // let moveY = e.clientY - downY
  82. // moveX = moveX < minLeft ? minLeft : moveX > maxLeft ? maxLeft : moveX
  83. moveY = moveY < minTop ? minTop : moveY > maxTop ? maxTop : moveY;
  84. toolMoveY = moveY;
  85. document.documentElement.style.setProperty(
  86. '--toolTranslateY',
  87. `${moveY}px`
  88. );
  89. // 计算移动的距离
  90. const cX = event.clientX - downX;
  91. const cY = event.clientY - downY;
  92. // 如果移动距离超过一定阈值,则认为是拖动
  93. if (Math.abs(cX) > 3 || Math.abs(cY) > 3) {
  94. isLock = true; // 设置为拖动状态
  95. }
  96. }
  97. function onMouseup() {
  98. document.removeEventListener(
  99. isTouchEv ? 'touchmove' : 'mousemove',
  100. onMousemove
  101. );
  102. document.removeEventListener(
  103. isTouchEv ? 'touchend' : 'mouseup',
  104. onMouseup
  105. );
  106. isMask.value = false;
  107. }
  108. document.addEventListener(
  109. isTouchEv ? 'touchmove' : 'mousemove',
  110. onMousemove
  111. );
  112. document.addEventListener(
  113. isTouchEv ? 'touchend' : 'mouseup',
  114. onMouseup
  115. );
  116. }
  117. el.addEventListener('mousedown', mousedown);
  118. el.addEventListener('touchstart', mousedown);
  119. }
  120. function isTouchEvent(e: MouseEvent | TouchEvent): e is TouchEvent {
  121. return window.TouchEvent && e instanceof window.TouchEvent;
  122. }
  123. //重新计算位置 居中
  124. function refreshPos() {
  125. // computePos("height", iconToolsDom.value?.clientHeight ||
  126. console.log(iconToolsDom.value?.clientHeight);
  127. const posHeight = computePos(
  128. 'height',
  129. iconToolsDom.value?.clientHeight || 0
  130. );
  131. if (iconToolsDom.value) {
  132. document.documentElement.style.setProperty(
  133. '--toolTranslateY',
  134. `${posHeight.pos}px`
  135. );
  136. }
  137. }
  138. let rect: any;
  139. function onResize() {
  140. rect = rect ? rect : iconToolsDom.value?.getBoundingClientRect();
  141. const clientHeight = document.documentElement.clientHeight;
  142. const maxTop = clientHeight - rect.height;
  143. if (toolMoveY >= maxTop) {
  144. document.documentElement.style.setProperty(
  145. '--toolTranslateY',
  146. `${maxTop}px`
  147. );
  148. }
  149. }
  150. onMounted(() => {
  151. handleStatus();
  152. drag(iconToolsDom.value!);
  153. drag(expendToolsDom.value!);
  154. nextTick(() => {
  155. refreshPos();
  156. })
  157. window.addEventListener('resize', onResize);
  158. });
  159. onUnmounted(() => {
  160. window.removeEventListener('resize', onResize);
  161. });
  162. return () => (
  163. <div>
  164. <div
  165. class={[
  166. styles.globalTools,
  167. isPlay.value ? styles.isPlay : '',
  168. isHidden.value ? styles.isHidden : ''
  169. ]}>
  170. {isMask.value && <div class={styles.mask}></div>}
  171. <div
  172. class={[[styles.iconTools, toolOpen.value ? styles.hideTools : '']]}
  173. ref={iconToolsDom}>
  174. <img onClick={openTool} src={iconTool} />
  175. </div>
  176. <div
  177. class={[styles.expendTools, toolOpen.value ? styles.showTools : '']}
  178. ref={expendToolsDom}>
  179. <img onClick={() => openType('note')} src={iconNote} />
  180. <img
  181. onClick={() => openType('whiteboard')}
  182. class={styles.iconWhiteboard}
  183. src={iconWhiteboard}
  184. />
  185. <img
  186. onClick={openTool}
  187. class={styles.iconArrow}
  188. src={gArrowRight}
  189. />
  190. </div>
  191. </div>
  192. <Pen
  193. show={penShow.value}
  194. tip="请确认是否退出批注?"
  195. close={() => {
  196. penShow.value = false;
  197. isHidden.value = false;
  198. }}
  199. />
  200. <Pen
  201. show={whitePenShow.value}
  202. isWhite
  203. tip="请确认是否退出白板?"
  204. close={() => {
  205. whitePenShow.value = false;
  206. isHidden.value = false;
  207. }}
  208. />
  209. </div>
  210. );
  211. }
  212. });