Toggle navigation
我的博客
首页
文章列表
留言板
登录
注册
首页
技术分享
文章
全局拖拽
作者:
gaohan
•
2023年08月17日
阅读 (296)
:::align-left
```
/**
* @Name: 拖动插件
* @Descripttion: body区域内拖动,支持传染Dom对象或者css选择器
* @Author: gaohan
* @Date: 2023/8/17 16:36
* @LastEditors: gaohan
* @LastEditTime: 2023/8/17
*/
declare namespace DragDrop {
// 拖动配置项
export interface dropOptions {
// 是否锁定,锁定状态下不可拖动
locked: boolean,
// 拖动目标元素
target: string|HTMLElement,
// 拖动目标元素父级
parent: string|HTMLElement
}
// 默认配置项
export interface defaultOptions{
// 拖动
drop: dropOptions,
// 默认顶部top值
top: number
}
}
class DragDrop{
options:DragDrop.defaultOptions
root:HTMLElement|null
parent:HTMLElement|null
lock:()=>void;
constructor(options:object,top:number=100){
const drop = Object.assign({
locked: false,
target: '',
parent: document.body
},options)
this.options = {
drop,
top
}
this.root = null
this.parent = null
this.lock = ()=>{
this.options.drop.locked = true
}
this.reset()
}
protected reset(){
const {drop} = this.options
const {locked,target,parent} = drop
if( locked || !target ){
return
}
if( typeof target === 'string'){
this.root = document.querySelector(target)
}else{
this.root = this.isDom(target) ? target : null
}
if( typeof parent === 'string'){
this.parent = document.querySelector(parent)
}else{
this.parent = this.isDom(parent) ? parent : null
}
if( this.parent === null && this.root === null ){
return
}
this.setStyle()
this.bindEvent()
}
protected setStyle(){
// 设置弹窗宽高,默认位置
const {top} = this.options
const winWidth = window.innerWidth
const rootWidth = parseFloat(this.parent?.clientWidth+'')
const maxWidth = winWidth*0.4
const width = rootWidth <= maxWidth ? rootWidth : maxWidth
const left = (winWidth - width) / 2
const style:any = {
'position': 'fixed',
'z-index': 99999,
'top': top + 'px',
'left': left + 'px',
'width': maxWidth + 'px',
'max-height': 600 + 'px'
}
Object.keys(style).map((key:any)=>{
(this.parent as HTMLElement).style[key] = style[key]
});
(this.root as HTMLElement).style.cursor = 'move'
}
protected bindEvent(){
// 绑定拖动事件
this.root?.addEventListener('pointerdown', (event:PointerEvent)=>{
event.stopPropagation()
event.cancelBubble=true;
if( this.parent && this.root ){
const xDown:number = event.clientX
const yDown:number = event.clientY
const leftDown:number = this.parent.offsetLeft
const topDown:number = this.parent.offsetTop
const move = (e:PointerEvent)=>{
e.stopPropagation()
e.cancelBubble=true;
const xMove:number = e.clientX;
const yMove:number = e.clientY;
const x:number = leftDown + xMove - xDown;
const y:number = topDown + yMove - yDown;
(this.parent as HTMLElement).style.left = this.getPos(x,false) + 'px';
(this.parent as HTMLElement).style.top = this.getPos(y,true) + 'px';
}
document.addEventListener('pointermove', move)
this.root.addEventListener('pointerup', ()=>{
this.root?.removeEventListener('pointerdown',()=>{})
document.removeEventListener('pointermove',move)
})
}
})
}
protected getPos(value: number, isTop: boolean){
const winWidth = window.innerWidth
const winHeight = window.innerHeight
const rootWidth = parseFloat(this.parent?.clientWidth+'')
const rootHeight = parseFloat(this.parent?.clientHeight+'')
const limitLeft = -(rootWidth/2)
const limitTop = 0
const limitRight = (winWidth - rootWidth) + (rootWidth/2)
const limitBottom = (winHeight - rootHeight) + (rootHeight/2)
if( isTop ){
value = value <= limitTop ? limitTop : value
value = value >= limitBottom ? limitBottom : value
}else{
value = value <= limitLeft ? limitLeft : value
value = value >= limitRight ? limitRight : value
}
return value
}
private isDom(obj: any){
const d = document.createElement("div");
try{
d.appendChild(obj.cloneNode(true));
return obj.nodeType==1
}catch(e){
return obj === window || obj === document;
}
}
}
export default DragDrop
/**
*
* 知识点解析:
* 面向对象编程
* 命名空间
* 指针,触屏,鼠标事件
* 方法作用域
* 方法关键词 public private protected
* 界值处理
* 报错处理
* ts
* es6语法
*
*
* 插件的常见形式:
* 实例化一个对象,初始化时构建基础数据,抛出部分方法提供别人使用
*
* 初始化方法构建:
* 1) 默认参数和传参
* 2) 基础数据构建
* 3) 有Dom操作的确定Dom元素
* 4) 绑定必要的事件
*
* */
```
© 著作权归作者所有
分类
技术分享
标签
javascript