123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- <template>
- <div ref="dragBoxRef" class="tvb-drag-box" :class="{ disabled: disabled }" :style="disabled ? '' : `right: ${dragBoxPos.x}px; bottom: ${dragBoxPos.y}px;`
- " @touchstart="onTouchStart" @touchend="onTouchEnd" @touchmove="onTouchMove">
- <slot></slot>
- </div>
- </template>
- <script setup>
- import { ref } from "vue";
- const props = defineProps({
- disabled: { type: Boolean, default: false }
- });
- const dragPos = {
- hasMoved: false, // 排除click事件
- x: 20, // right
- y: 100, // bottom
- startX: 0,
- startY: 0,
- endX: 0,
- endY: 0
- };
- const dragBoxPos = ref({ x: null, y: null });
- const dragBoxRef = ref();
- const setPosition = (dragX, dragY) => {
- [dragX, dragY] = _getSafeAreaXY(dragX, dragY);
- dragPos.x = dragX;
- dragPos.y = dragY;
- dragBoxPos.value.x = dragX;
- dragBoxPos.value.y = dragY;
- };
- const _getSafeAreaXY = (x, y) => {
- const docWidth = Math.max(
- document.documentElement.offsetWidth,
- window.innerWidth
- );
- const docHeight = Math.max(
- document.documentElement.offsetHeight,
- window.innerHeight
- );
- // 检查屏幕边缘
- if (x + dragBoxRef.value.offsetWidth > docWidth) {
- x = docWidth - dragBoxRef.value.offsetWidth;
- }
- if (y + dragBoxRef.value.offsetHeight > docHeight) {
- y = docHeight - dragBoxRef.value.offsetHeight;
- }
- if (x < 0) {
- x = 0;
- }
- // iOS底部的安全区域
- if (y < 20) {
- y = 20;
- }
- return [x, y];
- };
- const onTouchStart = (e) => {
- if (props.disabled) return;
- dragPos.startX = e.touches[0].pageX;
- dragPos.startY = e.touches[0].pageY;
- dragPos.hasMoved = false;
- };
- const onTouchEnd = (e) => {
- if (props.disabled) return;
- if (!dragPos.hasMoved) return;
- dragPos.startX = 0;
- dragPos.startY = 0;
- dragPos.hasMoved = false;
- setPosition(dragPos.endX, dragPos.endY);
- };
- const onTouchMove = (e) => {
- if (props.disabled) return;
- if (e.touches.length <= 0) return;
- const offsetX = e.touches[0].pageX - dragPos.startX,
- offsetY = e.touches[0].pageY - dragPos.startY;
- let x = Math.floor(dragPos.x - offsetX),
- y = Math.floor(dragPos.y - offsetY);
- [x, y] = _getSafeAreaXY(x, y);
- dragBoxPos.value.x = x;
- dragBoxPos.value.y = y;
- dragPos.endX = x;
- dragPos.endY = y;
- dragPos.hasMoved = true;
- e.preventDefault();
- };
- </script>
- <style lang='scss' scoped>
- .tvb-drag-box {
- &:not(.disabled) {
- position: fixed;
- bottom: 100px;
- right: 20px;
- overflow: hidden;
- z-index: 99;
- }
- }
- </style>
|