好久没更新了,最近写了一个小的拖拽组件,分享一下
场景:h5项目上要有一个联系客服或查看相关问题的模块,一般定位在页面的左侧或右侧,可当页面滑动时,可能会遮罩页面内容,所有就做成可拖拽的。
写起来很简单,使用 touchstart touchmove touchend 三个时间
- touchstart: 主要做一些例如 禁止滚动,防止滚动冲突
- touchmove: 当手指滚动时,使目标元素(也就是组件)跟随手指的滚动进行移动
- touchend: 用于手指移开,判断组件是回到左边还是右边。
我里的组件 props isOnlyLeft 意思是:只能在屏幕的左半边移动,isOnlyRight 只在屏幕右半边移动
<template>
<div ref="drawable"
:style="{left: left, top: top}"
class="draggable-box"
@touchstart="touchstart"
@touchend="touchend"
@touchmove="mousemove">
<slot />
</div>
</template>
<script>
export default {
name: 'DrawableBox',
props: {
top: String,
left: String,
isOnlyLeft: Boolean,
isOnlyRight: Boolean
},
data () {
return {
flag: false
}
},
methods: {
touchstart () {
this.flag = true
// 禁用页面滚动条
document.getElementById('app').style = 'overflow: hidden;'
this.$refs.drawable.style.transition = 'none'
},
touchend () {
this.flag = false
this.$refs.drawable.style.transition = 'all 0.2s'
document.getElementById('app').style = 'overflow: auto;'
let left = this.$refs.drawable.offsetLeft
let screenWidth = window.screen.width
let oWidth = this.$refs.drawable.offsetWidth
// 判断是回到左边还是右边
if (left + oWidth / 2 <= screenWidth / 2) {
this.$refs.drawable.style.left = '0px'
} else {
this.$refs.drawable.style.left = screenWidth - oWidth + 'px'
}
},
mousemove (e) {
// 禁止默认行为,防止在微信上打开和下拉冲突
e.preventDefault()
if (this.flag) {
let clientY = e.targetTouches[0].clientY
let clientX = e.targetTouches[0].clientX
let offsetHeight = this.$refs.drawable.offsetHeight
let offsetWidth = this.$refs.drawable.offsetWidth
let top = clientY - offsetHeight / 2
let left = clientX - offsetWidth / 2
// 屏幕得宽度
let screenWidth = window.screen.width
let screenHeight = window.screen.height
let maxTop = screenHeight - offsetHeight
let maxLeft = 0
const halfWidth = screenWidth / 2
if (this.isOnlyLeft) {
maxLeft = halfWidth - offsetWidth / 2
} else {
maxLeft = screenWidth - offsetWidth
}
if (top <= 0) {
top = 0
}
if (top > maxTop) {
top = maxTop
}
if (this.isOnlyRight) {
if (left <= halfWidth) {
left = halfWidth
}
} else {
if (left <= 0) {
left = 0
}
}
left = left > maxLeft ? maxLeft : left
this.$refs.drawable.style.top = top + 'px'
this.$refs.drawable.style.left = left + 'px'
}
}
}
}
</script>
<style lang="stylus" scoped>
.draggable-box
position: fixed
z-index: 100
</style>