基于纯原生js封装模态框拖拽效果插件

928 阅读4分钟

简易模态框拖拽插件

模态框拖拽插件简易参数配置分析

//-> 后期引入 drag-plugin.js 通过 new Drag([selector],[options])  

简易参数配置分析

/*
* 简易的拖拽插件
*    new Drag([selector],[options]); 
* SELECTOR
*    是按住谁来实现拖拽
* OPTIONS = {}
*    element:拖拽中要移动的元素(默认值:当前按住的元素)
*    boundary:是否进行边界校验 (默认值:true,不能超过要移动元素所在容器的范围,需要开发者保证:当前移动的元素是相对于它所在容器定位的)   
* 
*    声明周期函数(钩子函数) ->callback 回调函数
*    dragstart: 拖拽 开始
*    dragmove:  拖拽中
*    dragend: 拖拽结束
*/

代码如下:

~ function () {
	/*
	 * 拖拽插件封装 
	 */
	class Drag {
		constructor(selector, options) {
			this.initParams(selector, options);
			this._selector.addEventListener('mousedown', this.down.bind(this));
		}
		//=>参数初始化(尽可能把一切信息都挂载到实例上,这样在其它方法中,只要能获取到实例,这些信息都可以调用 =>我们尽可能保证每个方法中的THIS都是实例)
		initParams(selector, options = {}) {
			this._selector = document.querySelector(selector);

			//=>配置项的默认值信息
			let defaultParams = {
				element: this._selector,
				boundary: true,
				dragstart: null,
				dragmove: null,
				dragend: null
			};
			defaultParams = Object.assign(defaultParams, options);

			//=>把配置项信息都挂载到实例上  后期只要是 能够拿到实例,那么实例上所有的信息都能用
			Drag.each(defaultParams, (value, key) => {
				this['_' + key] = value;
			});
		}
		//=>实现拖拽的效果
		down(ev) {
			let {
				_element
			} = this;
			this.startX = ev.pageX;
			this.startY = ev.pageY;
			this.startL = Drag.queryCss(_element, 'left');
			this.startT = Drag.queryCss(_element, 'top');
			this._move = this.move.bind(this);
			this._up = this.up.bind(this);
               /*
                  为防止焦点丢失,我们把move 和 up 都绑定给document
                  但是这样做会里面的this指向改变, 不是我们想要的结果
                  基于 bind 方法 柯里化函数预处理机制 将this 重新指向实例
               */ 
               
			document.addEventListener('mousemove', this._move);
			document.addEventListener('mouseup', this._up);
			//=>钩子函数处理
			this._dragstart && this._dragstart(this, ev); //-> this 为 实例  ev 事件对象 
		}
		move(ev) {
			let {
				_element,
				_boundary,
				startX,
				startY,
				startL,
				startT
			} = this;
			let curL = ev.pageX - startX + startL,
				curT = ev.pageY - startY + startT;
			if (_boundary) {
				//=>处理边界
				let parent = _element.parentNode,
					minL = 0,
					minT = 0,
					maxL = parent.offsetWidth - _element.offsetWidth,
					maxT = parent.offsetHeight - _element.offsetHeight;
				curL = curL < minL ? minL : (curL > maxL ? maxL : curL);
				curT = curT < minT ? minT : (curT > maxT ? maxT : curT);
			}
			_element.style.left = curL + 'px';
			_element.style.top = curT + 'px';

			//=>钩子函数处理
			this._dragmove && this._dragmove(this, curL, curT, ev); //-> this 为 实例  ev 事件对象
		}
		up(ev) {
               /*
                移除时和绑定时 也是如此 基于bind 的机制 
               */
			document.removeEventListener('mousemove', this._move);
			document.removeEventListener('mouseup', this._up);
			
			//=>钩子函数处理
			this._dragend && this._dragend(this, ev); //-> this 为 实例  ev 事件对象
		}
		//=>设置工具类的方法(把它当做类[普通对象]的私有属性)
		static each(arr, callback) {
			if ('length' in arr) {
				//=>数组||类数组
				for (let i = 0; i < arr.length; i++) {
					callback && callback(arr[i], i);
				}
				return;
			}
			//=>普通对象
			for (let key in arr) {
				if (!arr.hasOwnProperty(key)) break;
				callback && callback(arr[key], key);
			}
		}
		static queryCss(curEle, attr) {
               //-> 将获取到值 parseFloat  防止后期 数学计算时出现字符串拼接
			return parseFloat(window.getComputedStyle(curEle)[attr]);
		}
	}
	window.Drag = Drag;
}();

例子引用 下面可看实现效果

[[http://localhost:63342/Java Script JS/就业正式课/week6/0902/drag1.html?_ijt=p3nhitvi4dr1895a68f7ab6olb](http://localhost:63342/Java Script JS/就业正式课/week6/0902/drag1.html?_ijt=p3nhitvi4dr1895a68f7ab6olb)

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>珠峰培训</title>
	<link rel="stylesheet" href="css/reset.min.css">
	<style>
		html,
		body {
			height: 100%;
			overflow: hidden;
		}

		#box {
			position: absolute;
			top: 0;
			left: 0;
			width: 100px;
			height: 100px;
			background: red;
		}

		#box h2 {
			height: 30px;
			background: green;
			cursor: move;
		}
	</style>
</head>

<body>
	<div id="box">
		<h2></h2>
	</div>
      /* 引入我们的插件 drag-plugin.js  */
	<script src="js/drag-plugin.js"></script>
	<script>
		new Drag('#box h2', {
			element: box,
			boundary: false
		});
	</script>

</body>

</html>

例子二 下面可看实现效果

[http://localhost:63342/Java Script JS/就业正式课/week6/0902/drag2.html?_ijt=p3nhitvi4dr1895a68f7ab6olb](http://localhost:63342/Java Script JS/就业正式课/week6/0902/drag2.html?_ijt=p3nhitvi4dr1895a68f7ab6olb)

<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>珠峰培训</title>
	<link rel="stylesheet" href="css/reset.min.css">
	<style>
		html,
		body {
			height: 100%;
			overflow: hidden;
		}

		#box {
			position: absolute;
			top: 0;
			left: 0;
			z-index: 10;
			width: 100px;
			height: 100px;
			background: red;
			cursor: move;
		}

		#container {
			position: relative;
			box-sizing: border-box;
			margin: 30px auto;
			width: 300px;
			height: 200px;
			border: 2px solid lightseagreen;
		}
	</style>
</head>

<body>
	<div id="box"></div>
	<div id="container"></div>

	<script src="js/drag-plugin.js"></script>
	<script>
		new Drag('#box', {
			dragend: function (examp, ev) {
				//=>this:Drag example
				let _element = this._element;
				let minL = container.offsetLeft,
					minT = container.offsetTop,
					maxL = minL + container.offsetWidth - _element.offsetWidth,
					maxT = minT + container.offsetHeight - _element.offsetHeight,
					curL = Drag.queryCss(_element, 'left'),
					curT = Drag.queryCss(_element, 'top');
				if ((curL >= minL && curL <= maxL) && (curT >= minT && curT <= maxT)) {
					//=>在指定的范围内
					container.appendChild(_element);
					_element.style.left = 0;
					_element.style.top = 0;
					return;
				}
				//=>没有拖动到指定的范围内
				_element.style.left = this.startL + 'px';
				_element.style.top = this.startT + 'px';
			}
		});
	</script>

</body>

</html>