看了网上的不少关于拖拽的文章,自己尝试着用es6 的class写了一个拖拽方法,记录一下
配置项
配置项 | 描述 | 默认值 |
---|
autoAdsord | 是否开启自动吸边 | true |
adsordConfig | 吸边的相关配置,接收一个对象, 可以配置等待时间和持续时间 | {waitTime: 2,durationTime: 1.3} |
dragShadow | 是否开启拖影 | true |
triggerTime | 启动拖拽的触发时间(长按时长),接收一个number类型,单位是秒 | 2 |
responseTime | 拖拽触发后,如果放开的鼠标,在该时间内,可以继续拖拽,接收一个number类型,单位是秒 | 2 |
class Drag 代码
interface config {
autoAdsord?: boolean
adsordConfig?: adsordConfig
triggerTime?: number
responseTime?: number
dragShadow: boolean
}
interface adsordConfig {
waitTime: number,
durationTime: number
}
const defaultConfig: config = {
autoAdsord: true,
adsordConfig: {
waitTime: 2,
durationTime: 1.3
},
triggerTime: 2,
responseTime: 2,
dragShadow: true
}
class Drag {
el: HTMLElement
config: config = defaultConfig
offsetX: number = 0
offsetY: number = 0
maxW: number = 0
maxH: number = 0
equipment: string = 'pc'
eventDown: string = 'mousedown'
eventMove: string = 'mousemove'
eventUp: string = 'mouseup'
isDrag: boolean = false
isDragTimeId: number | undefined = undefined
clearDragTimeId: number | undefined = undefined
adsordTimeId: number | undefined = undefined
adsordTimeIdInner: number | undefined = undefined
constructor(el: HTMLElement, config: config = defaultConfig) {
this.el = el
this.config = {
...config,
...defaultConfig
}
this.equipment = this.iswap()
this.el.style.position = 'fixed';
this.el.style.zIndex = '999'
switch (this.equipment) {
case 'pc':
this.eventDown = 'mousedown'
this.eventMove = 'mousemove'
this.eventUp = 'mouseup'
break
case 'mobile':
this.eventDown = 'touchstart'
this.eventMove = 'touchmove'
this.eventUp = 'touchend'
break
}
this.onDown()
}
onDown() {
this.el.addEventListener(this.eventDown, this.start)
}
onMove() {
document.addEventListener(this.eventMove, this.move);
}
onUp() {
document.addEventListener(this.eventUp, this.stop);
}
start = (event: any) => {
if ((event as MouseEvent).button == 0 || this.equipment === 'mobile') {
clearTimeout(this.clearDragTimeId)
this.config.autoAdsord && this.clearAdsord()
this.maxW = document.documentElement.clientWidth - this.el.offsetWidth
this.maxH = document.documentElement.clientHeight - this.el.offsetHeight
const lexObj: any = getComputedStyle(this.el);
let { pointX, pointY } = this.getPoint(event)
this.offsetX = pointX - this.el.offsetLeft + parseInt(lexObj['margin-left']);
this.offsetY = pointY - this.el.offsetTop + parseInt(lexObj['margin-top']);
this.onMove()
this.onUp()
this.setIsDarg()
}
}
move = (event: any) => {
clearTimeout(this.isDragTimeId)
if (!this.isDrag) return
this.config.autoAdsord && this.clearAdsord()
this.el.style.pointerEvents = 'none'
this.el.style.userSelect = 'none'
let { pointX, pointY } = this.getPoint(event)
let x = pointX - this.offsetX;
let y = pointY - this.offsetY;
if (x < 0) {
x = 0;
} else if (x > this.maxW) {
x = this.maxW
}
if (y < 0) {
y = 0;
} else if (y > this.maxH) {
y = this.maxH
}
this.el.style.left = x + 'px';
this.el.style.top = y + 'px';
if (this.config.dragShadow) {
this.setDragShadow()
}
}
stop = () => {
clearTimeout(this.isDragTimeId)
this.el.style.pointerEvents = ''
this.el.style.userSelect = 'text'
document.removeEventListener(this.eventMove, this.move);
document.removeEventListener(this.eventUp, this.stop);
this.config.autoAdsord && this.setAdsord()
this.clearDragTimeId = setTimeout(() => {
this.resetIsDarg()
}, (this.config.responseTime ?? 0) * 1000)
}
getPoint(event: MouseEvent | TouchEvent) {
let pointX = 0
let pointY = 0
switch (this.equipment) {
case 'pc':
pointX = (event as MouseEvent).pageX
pointY = (event as MouseEvent).pageY
break
case 'mobile':
var touch = (event as TouchEvent).targetTouches[0];
pointX = touch.clientX
pointY = touch.clientY
break
}
return {
pointX,
pointY
}
}
setAdsord() {
this.adsordTimeId = setTimeout(() => {
let domCenterX = this.el.offsetWidth / 2 + this.el.offsetLeft
let screenCenterX = window.innerWidth / 2
let animationTime = this.config.adsordConfig?.durationTime ?? 0
this.el.style.transition = animationTime + 's'
if (domCenterX > screenCenterX) {
this.el.style.left = this.maxW + 'px'
} else {
this.el.style.left = '0'
}
this.adsordTimeIdInner = setTimeout(() => {
this.el.style.transition = ''
if (domCenterX > screenCenterX) {
this.el.style.left = ''
this.el.style.right = '0'
}
}, animationTime * 1000)
}, (this.config.adsordConfig?.waitTime ?? 0) * 1000)
}
clearAdsord() {
clearTimeout(this.adsordTimeIdInner)
clearTimeout(this.adsordTimeId)
this.el.style.transition = ''
}
setIsDarg() {
this.isDragTimeId = setTimeout(() => {
this.isDrag = true
this.el.style.cursor = 'pointer'
this.el.style.transform = 'scale(1.1)'
}, (this.config.triggerTime ?? 0) * 1000)
}
resetIsDarg() {
clearTimeout(this.isDragTimeId)
this.isDrag = false
this.el.style.cursor = 'auto'
this.el.style.transform = 'scale(1)'
}
iswap(): string {
let uA: string = navigator.userAgent.toLowerCase();
let ipad: boolean = uA.match(/ipad/i) !== null;
let iphone: boolean = uA.match(/iphone os/i) !== null;
let midp: boolean = uA.match(/midp/i) !== null;
let uc7: boolean = uA.match(/rv:1.2.3.4/i) !== null;
let uc: boolean = uA.match(/ucweb/i) !== null
let android: boolean = uA.match(/android/i) !== null;
let windowsce: boolean = uA.match(/windows ce/i) !== null;
let windowsmd: boolean = uA.match(/windows mobile/i) !== null;
if (!(ipad || iphone || midp || uc7 || uc || android || windowsce || windowsmd)) {
return 'pc'
} else {
return 'mobile'
}
}
setDragShadow() {
let newEle = document.createElement("div")
newEle.style.width = this.el.offsetWidth + 'px'
newEle.style.height = this.el.offsetWidth + 'px'
newEle.style.background = 'rgba(0,0,0,0.05)'
newEle.style.position = 'fixed';
newEle.style.left = String(parseInt(this.el.style.left)) + 'px';
newEle.style.top = String(parseInt(this.el.style.top)) + 'px';
newEle.style.opacity = '1'
newEle.style.zIndex = '0'
newEle.style.transition = 1 + 's'
newEle.style.filter = 'blur(2px)'
let opacity = 1
document.body.appendChild(newEle)
let opacityTimeId = setInterval(() => {
if (newEle.style.opacity <= '0') {
clearInterval(opacityTimeId)
newEle.remove()
} else {
newEle.style.opacity = String(Number(newEle.style.opacity) - 0.4)
}
}, 100)
}
destory() {
this.el.removeEventListener(this.eventDown, this.start)
}
}
export default Drag
js
const defaultConfig = {
autoAdsord: true,
adsordConfig: {
waitTime: 1,
durationTime: 0.5
},
triggerTime: 0,
responseTime: 0,
dragShadow: false
}
class Drag {
el
config = defaultConfig
offsetX = 0
offsetY = 0
maxW = 0
maxH = 0
equipment = 'pc'
eventDown = 'mousedown'
eventMove = 'mousemove'
eventUp = 'mouseup'
isDrag = false
isDragTimeId = undefined
clearDragTimeId = undefined
adsordTimeId = undefined
adsordTimeIdInner = undefined
constructor(el, config = defaultConfig) {
this.el = el
this.config = {
...defaultConfig,
...config
}
this.equipment = this.iswap()
this.el.style.position = 'fixed';
this.el.style.zIndex = '999'
switch (this.equipment) {
case 'pc':
this.eventDown = 'mousedown'
this.eventMove = 'mousemove'
this.eventUp = 'mouseup'
break
case 'mobile':
this.eventDown = 'touchstart'
this.eventMove = 'touchmove'
this.eventUp = 'touchend'
break
}
this.onDown()
}
onDown() {
this.el.addEventListener(this.eventDown, this.start)
}
onMove() {
document.addEventListener(this.eventMove, this.move, { passive: true });
}
onUp() {
document.addEventListener(this.eventUp, this.stop);
}
start = (event) => {
document.body.addEventListener('touchmove', this.bodyScroll, { passive: false });
if ((event).button == 0 || this.equipment === 'mobile') {
clearTimeout(this.clearDragTimeId)
this.config.autoAdsord && this.clearAdsord()
this.maxW = document.documentElement.clientWidth - this.el.offsetWidth
this.maxH = document.documentElement.clientHeight - this.el.offsetHeight
const lexObj = getComputedStyle(this.el);
let { pointX, pointY } = this.getPoint(event)
this.offsetX = pointX - this.el.offsetLeft + parseInt(lexObj['margin-left']);
this.offsetY = pointY - this.el.offsetTop + parseInt(lexObj['margin-top']);
this.onMove()
this.onUp()
this.setIsDarg()
}
}
move = (event) => {
clearTimeout(this.isDragTimeId)
if (!this.isDrag) return
this.config.autoAdsord && this.clearAdsord()
this.el.style.pointerEvents = 'none'
this.el.style.userSelect = 'none'
let { pointX, pointY } = this.getPoint(event)
let x = pointX - this.offsetX;
let y = pointY - this.offsetY;
if (x < 0) {
x = 0;
} else if (x > this.maxW) {
x = this.maxW
}
if (y < 0) {
y = 0;
} else if (y > this.maxH) {
y = this.maxH
}
this.el.style.left = x + 'px';
this.el.style.top = y + 'px';
}
stop = () => {
clearTimeout(this.isDragTimeId)
this.el.style.pointerEvents = ''
this.el.style.userSelect = 'text'
document.removeEventListener(this.eventMove, this.move);
document.removeEventListener(this.eventUp, this.stop);
this.config.autoAdsord && this.setAdsord()
this.clearDragTimeId = setTimeout(() => {
this.resetIsDarg()
}, (this.config.responseTime ?? 0) * 1000)
document.body.removeEventListener('touchmove', this.bodyScroll, { passive: false });
}
getPoint(event) {
let pointX = 0
let pointY = 0
switch (this.equipment) {
case 'pc':
pointX = (event).pageX
pointY = (event).pageY
break
case 'mobile':
var touch = (event).targetTouches[0];
pointX = touch.clientX
pointY = touch.clientY
break
}
return {
pointX,
pointY
}
}
setAdsord() {
this.adsordTimeId = setTimeout(() => {
let domCenterX = this.el.offsetWidth / 2 + this.el.offsetLeft
let screenCenterX = window.innerWidth / 2
let animationTime = this.config.adsordConfig?.durationTime ?? 0
this.el.style.transition = animationTime + 's'
if (domCenterX > screenCenterX) {
this.el.style.left = this.maxW + 'px'
} else {
this.el.style.left = '0'
}
this.adsordTimeIdInner = setTimeout(() => {
this.el.style.transition = ''
if (domCenterX > screenCenterX) {
this.el.style.left = ''
this.el.style.right = '0'
}
}, animationTime * 1000)
}, (this.config.adsordConfig?.waitTime ?? 0) * 1000)
}
clearAdsord() {
clearTimeout(this.adsordTimeIdInner)
clearTimeout(this.adsordTimeId)
this.el.style.transition = ''
}
setIsDarg() {
this.isDragTimeId = setTimeout(() => {
this.isDrag = true
this.el.style.cursor = 'pointer'
this.el.style.transform = 'scale(1.1)'
}, (this.config.triggerTime ?? 0) * 1000)
}
resetIsDarg() {
clearTimeout(this.isDragTimeId)
this.isDrag = false
this.el.style.cursor = 'auto'
this.el.style.transform = 'scale(1)'
}
iswap() {
let uA = navigator.userAgent.toLowerCase();
let ipad = uA.match(/ipad/i) !== null;
let iphone = uA.match(/iphone os/i) !== null;
let midp = uA.match(/midp/i) !== null;
let uc7 = uA.match(/rv:1.2.3.4/i) !== null;
let uc = uA.match(/ucweb/i) !== null
let android = uA.match(/android/i) !== null;
let windowsce = uA.match(/windows ce/i) !== null;
let windowsmd = uA.match(/windows mobile/i) !== null;
if (!(ipad || iphone || midp || uc7 || uc || android || windowsce || windowsmd)) {
return 'pc'
} else {
return 'mobile'
}
}
setDragShadow() {
let newEle = document.createElement("div")
newEle.style.width = this.el.offsetWidth + 'px'
newEle.style.height = this.el.offsetWidth + 'px'
newEle.style.background = 'rgba(0,0,0,0.05)'
newEle.style.position = 'fixed';
newEle.style.left = String(parseInt(this.el.style.left)) + 'px';
newEle.style.top = String(parseInt(this.el.style.top)) + 'px';
newEle.style.opacity = '1'
newEle.style.zIndex = '0'
newEle.style.transition = 1 + 's'
newEle.style.filter = 'blur(2px)'
let opacity = 1
document.body.appendChild(newEle)
let opacityTimeId = setInterval(() => {
if (newEle.style.opacity <= '0') {
clearInterval(opacityTimeId)
newEle.remove()
} else {
newEle.style.opacity = String(Number(newEle.style.opacity) - 0.4)
}
}, 100)
}
bodyScroll(event) {
event.preventDefault();
}
destory() {
this.el.removeEventListener(this.eventDown, this.start)
}
}