cover.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. <template>
  2. <div
  3. class="cover-layout"
  4. @click="clickHandler"
  5. @mousedown.stop.prevent="downHandler"
  6. @touchstart.stop.prevent="downHandler"
  7. :class="{ move: move }"
  8. :style="style"
  9. ref="dom"
  10. >
  11. <slot />
  12. </div>
  13. </template>
  14. <script setup lang="ts">
  15. import {computed, onMounted, onUnmounted, ref, watch} from 'vue'
  16. import {Pos, Pos3D} from '@/sdk'
  17. import {useSDK} from '@/hook'
  18. import { getPostionByTarget} from '@/components/base/utils'
  19. const props = defineProps<{
  20. pos: Pos3D
  21. }>()
  22. const emit = defineEmits<{
  23. (m: 'changePos', pos: Pos3D): void
  24. (m: 'focus'): void
  25. (m: 'blur'): void
  26. }>()
  27. const sdk = useSDK()
  28. const dom = ref<HTMLElement>()
  29. const screen = ref<Pos>(null)
  30. const style = computed(
  31. () =>
  32. screen.value && {
  33. left: screen.value.x + 'px',
  34. top: screen.value.y + 'px'
  35. }
  36. )
  37. const updatePos = () => {
  38. if (props.pos) {
  39. const data = sdk.scene.getScreenByPoint(props.pos)
  40. screen.value = data.trueSide ? data.pos : null
  41. }
  42. }
  43. sdk.scene.on('posChange', updatePos)
  44. watch(props, updatePos)
  45. updatePos()
  46. const move = ref(false)
  47. const downHandler = (sev: MouseEvent | TouchEvent) => {
  48. const el = sev.target as HTMLElement
  49. const mountEl = document.documentElement
  50. const preset = {
  51. x: el.offsetWidth / 2,
  52. y: el.offsetHeight
  53. }
  54. if (sev instanceof TouchEvent) {
  55. const pos = getPostionByTarget(el, document.querySelector("#app") as HTMLElement);
  56. preset.x = preset.x - (sev.touches[0].pageX - (pos.x - preset.x))
  57. preset.y = preset.y - (sev.touches[0].pageY - (pos.y - preset.y))
  58. console.log(
  59. pos,
  60. sev.touches[0].clientX,
  61. sev.touches[0].clientY,
  62. preset
  63. )
  64. } else {
  65. preset.x -= sev.offsetX
  66. preset.y -= sev.offsetY
  67. }
  68. const moveHandler = (ev: MouseEvent | TouchEvent) => {
  69. move.value = true
  70. const pos = sdk.scene.getPointByScreen({
  71. x: (ev instanceof TouchEvent ? ev.touches[0].pageX : ev.pageX) + preset.x,
  72. y: (ev instanceof TouchEvent ? ev.touches[0].pageY : ev.pageY) + preset.y,
  73. inDrag: true
  74. })
  75. if (pos.position) {
  76. emit('changePos', pos.position);
  77. }
  78. }
  79. const upHandler = (ev: MouseEvent) => {
  80. mountEl.removeEventListener('mousemove', moveHandler)
  81. mountEl.removeEventListener('mouseup', upHandler)
  82. mountEl.removeEventListener('touchmove', moveHandler)
  83. mountEl.removeEventListener('touchend', upHandler)
  84. move.value = false
  85. }
  86. mountEl.addEventListener('mousemove', moveHandler)
  87. mountEl.addEventListener('mouseup', upHandler)
  88. mountEl.addEventListener('touchmove', moveHandler)
  89. mountEl.addEventListener('touchend', upHandler)
  90. }
  91. const clickHandler = ev => {
  92. emit("focus")
  93. const handler = (ev: MouseEvent) => {
  94. if (!dom.value.contains(ev.target as HTMLElement) && ev.target !== dom.value) {
  95. emit("blur")
  96. document.documentElement.removeEventListener("click", handler)
  97. }
  98. }
  99. document.documentElement.addEventListener("click", handler, { passive: true })
  100. }
  101. onUnmounted(() => {
  102. emit("blur")
  103. })
  104. </script>
  105. <style scoped lang="scss">
  106. .cover-layout {
  107. position: absolute;
  108. z-index: 1;
  109. transform: translate(-50%, -100%);
  110. cursor: move;
  111. }
  112. .move {
  113. pointer-events: none;
  114. }
  115. </style>