feat(components): 实现侧边栏拖动功能

- 在 SideButton 组件中添加拖动功能,支持鼠标和触摸操作
-优化 artDetail 页面中的拖动逻辑,限制拖动范围
-修复 liveRoom 组件中的拖动相关问题
This commit is contained in:
xingyy 2025-02-14 17:00:34 +08:00
parent aad429be0a
commit 2f8eb36a52
2 changed files with 130 additions and 29 deletions

View File

@ -14,7 +14,7 @@ const initData = async () => {
detail.value = res.data detail.value = res.data
} }
} }
const position = ref({x: window?.innerWidth - 120 || 0, y: 240}) // const position = ref({x: window?.innerWidth - 120 || 0, y: 240})
const startPosition = ref({x: 0, y: 0}) const startPosition = ref({x: 0, y: 0})
const isDragging = ref(false) const isDragging = ref(false)
@ -33,38 +33,30 @@ const onDrag = (e) => {
const clientX = e.touches ? e.touches[0].clientX : e.clientX const clientX = e.touches ? e.touches[0].clientX : e.clientX
const clientY = e.touches ? e.touches[0].clientY : e.clientY const clientY = e.touches ? e.touches[0].clientY : e.clientY
// const maxX = window.innerWidth - 108
const maxX = window.innerWidth - 108 // const maxY = window.innerHeight - 137
const maxY = window.innerHeight - 137 //
//
const x = Math.min(Math.max(0, clientX - startPosition.value.x), maxX) const x = Math.min(Math.max(0, clientX - startPosition.value.x), maxX)
const y = Math.min(Math.max(0, clientY - startPosition.value.y), maxY) const y = Math.min(Math.max(0, clientY - startPosition.value.y), maxY)
position.value = {x, y} position.value = {x, y}
} }
} }
const stopDrag = () => { const stopDrag = () => {
isDragging.value = false isDragging.value = false
} }
onMounted(() => { onMounted(() => {
//
document.addEventListener('mousemove', onDrag) document.addEventListener('mousemove', onDrag)
document.addEventListener('mouseup', stopDrag) document.addEventListener('mouseup', stopDrag)
//
document.addEventListener('touchmove', onDrag) document.addEventListener('touchmove', onDrag)
document.addEventListener('touchend', stopDrag) document.addEventListener('touchend', stopDrag)
}) })
onUnmounted(() => { onUnmounted(() => {
document.removeEventListener('mousemove', onDrag) document.removeEventListener('mousemove', onDrag)
document.removeEventListener('mouseup', stopDrag) document.removeEventListener('mouseup', stopDrag)
document.removeEventListener('touchmove', onDrag) document.removeEventListener('touchmove', onDrag)
document.removeEventListener('touchend', stopDrag) document.removeEventListener('touchend', stopDrag)
}) })
initData() initData()
</script> </script>

View File

@ -1,17 +1,93 @@
<script setup> <script setup>
import {ref} from "vue"; import { ref, computed, onMounted, onBeforeUnmount } from "vue"
import lockClosed from "@/static/images/lockdfd@2x.png"; import lockClosed from "@/static/images/lockdfd@2x.png"
import lockOpen from "@/static/images/lock4@2x.png"; import lockOpen from "@/static/images/lock4@2x.png"
import {liveStore} from "@/stores/live/index.js"; import { liveStore } from "@/stores/live/index.js"
import xButton from '@/components/x-button/index.vue' import xButton from '@/components/x-button/index.vue'
import tangPopup from './tangPopup.vue' import tangPopup from './tangPopup.vue'
import {goodStore} from "@/stores/goods/index.js"; import { goodStore } from "@/stores/goods/index.js"
import {authStore} from "~/stores/auth/index.js"; import { authStore } from "~/stores/auth/index.js"
const {quoteStatus, changeStatus, show, auctionData, getSocketData} = liveStore(); const { quoteStatus, changeStatus, show, auctionData, getSocketData } = liveStore()
const {pageRef} = goodStore(); const { pageRef } = goodStore()
const {userInfo} = authStore() const { userInfo } = authStore()
const showTang = ref(false) const showTang = ref(false)
//
const isDragging = ref(false)
const startY = ref(0)
const currentTop = ref(196) // top
const sidebarRef = ref(null)
//
const minTop = 0 // top
const maxTop = window.innerHeight - 180 // top
//
const handleMouseDown = (e) => {
isDragging.value = true
startY.value = e.clientY - currentTop.value
document.addEventListener('mousemove', handleMouseMove)
document.addEventListener('mouseup', handleMouseUp)
}
//
const handleMouseMove = (e) => {
if (!isDragging.value) return
let newTop = e.clientY - startY.value
//
newTop = Math.max(minTop, Math.min(newTop, maxTop))
currentTop.value = newTop
//
if (sidebarRef.value) {
sidebarRef.value.style.top = `${newTop}px`
}
}
//
const handleMouseUp = () => {
isDragging.value = false
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
}
//
const handleTouchStart = (e) => {
isDragging.value = true
startY.value = e.touches[0].clientY - currentTop.value
}
const handleTouchMove = (e) => {
if (!isDragging.value) return
let newTop = e.touches[0].clientY - startY.value
newTop = Math.max(minTop, Math.min(newTop, maxTop))
currentTop.value = newTop
if (sidebarRef.value) {
sidebarRef.value.style.top = `${newTop}px`
}
}
const handleTouchEnd = () => {
isDragging.value = false
}
//
onMounted(() => {
if (sidebarRef.value) {
sidebarRef.value.style.top = `${currentTop.value}px`
}
})
//
onBeforeUnmount(() => {
document.removeEventListener('mousemove', handleMouseMove)
document.removeEventListener('mouseup', handleMouseUp)
})
const openOne = () => { const openOne = () => {
showTang.value = true showTang.value = true
} }
@ -24,25 +100,42 @@ const paySide = computed(() => {
return false return false
} }
}) })
const goPay = () => { const goPay = () => {
show.value = true show.value = true
} }
</script> </script>
<template> <template>
<div class="bg-white w-60px rounded-l-4px overflow-hidden"> <div
ref="sidebarRef"
class="bg-white w-60px rounded-l-4px overflow-hidden absolute right-0 z-999 cursor-move"
@mousedown="handleMouseDown"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
<!-- 拍品信息 --> <!-- 拍品信息 -->
<van-button class="w-60px !h-60px" @click="openOne" style="border: none;border-radius: 0"> <van-button
class="w-60px !h-60px"
@click="openOne"
style="border: none;border-radius: 0"
>
<div class="text-center flex flex-col justify-center items-center text-#7D7D7F text-12px"> <div class="text-center flex flex-col justify-center items-center text-#7D7D7F text-12px">
<div>{{ $t('live_room.lots') }}</div> <div>{{ $t('live_room.lots') }}</div>
<div>({{ auctionData?.artwork?.index }}/{{ pageRef.itemCount ?? 0 }})</div> <div>({{ auctionData?.artwork?.index }}/{{ pageRef.itemCount ?? 0 }})</div>
</div> </div>
</van-button> </van-button>
<tangPopup v-model:show="showTang"></tangPopup> <tangPopup v-model:show="showTang"></tangPopup>
<!-- 出价开关 --> <!-- 出价开关 -->
<van-button class="w-60px !h-60px" @click="changeStatus" <van-button
style="border-right: none;border-left: none;border-radius: 0;padding: 0"> class="w-60px !h-60px"
<div class="text-center flex flex-col justify-center items-center"> @click="changeStatus"
style="border-right: none;border-left: none;border-radius: 0;padding: 0"
>
<div class="text-center flex flex-col justify-center items-center">
<div class="mb-4px"> <div class="mb-4px">
<img <img
:src="quoteStatus ? lockClosed : lockOpen" :src="quoteStatus ? lockClosed : lockOpen"
@ -50,19 +143,35 @@ const goPay = () => {
alt="锁图标" alt="锁图标"
/> />
</div> </div>
<div :class="quoteStatus ? 'text-gray-500' : 'text-blue-600'" class="text-10px transition-colors duration-200"> <div
:class="quoteStatus ? 'text-gray-500' : 'text-blue-600'"
class="text-10px transition-colors duration-200"
>
{{ quoteStatus ? $t('live_room.colse_bid') : $t('live_room.start_bid') }} {{ quoteStatus ? $t('live_room.colse_bid') : $t('live_room.start_bid') }}
</div> </div>
</div> </div>
</van-button> </van-button>
<!-- 支付 --> <!-- 支付 -->
<van-button v-if="paySide" class="w-60px !h-60px" style="border: none;border-radius: 0" @click="goPay"> <van-button
<div class="text-center flex flex-col justify-center items-center text-yellow-600"> v-if="paySide"
class="w-60px !h-60px"
style="border: none;border-radius: 0"
@click="goPay"
>
<div class="text-center flex flex-col justify-center items-center text-yellow-600">
<div class="text-10px">RMB</div> <div class="text-10px">RMB</div>
<div class="text-12px">5,000</div> <div class="text-12px">5,000</div>
<div class="text-10px">{{ $t('art_detail_page.button') }}</div> <div class="text-10px">{{ $t('art_detail_page.button') }}</div>
</div> </div>
</van-button> </van-button>
</div> </div>
</template> </template>
<style scoped>
.cursor-move {
cursor: move;
user-select: none;
touch-action: none;
}
</style>