自己写一个jqery的拖拽插件

说实话,jQuery比原生的js好用多了,本来想用原生写的,也写出来的,只是,感觉不像插件,所以用jQuery实现了一版。

实现的功能:可以指定拖拽的边界,在拖拽过程中,可以触发几个自定义事件

先说明一下我写的插件的原则:

1.常量分离出来,放在$.zUI.插件中

2.插件的主体执行函数命名为$.zUI.插件.fn

3.销毁函数命名为$.zUI.插件.unfn

这些规范,主要是为了以后写其他插件时,放在一起,精简代码用的,以后可能还会增加其他规则,以写出一个骨架来。

拖拽的原理其实比较简单,就是在鼠标落下后,添加一个mousemove事件,让元素跟随鼠标移动,鼠标抬起后,移除刚才的事件。别看下面的代码那么多,其实多数是控制元素拖拽的范围的,把这些代码忽略后,其余的东西,很少。

主要的两段代码如下:

		$.zUI = $.zUI || {}
		/*
		 * draggable
		 * 参数:obj{
		 * bOffsetParentBoundary:是否以定位父亲元素为边界,
		 * oBoundary:指定元素left和top的边界值,形如{iMinLeft:...,iMaxLeft:...,iMinTop:...,iMaxTop:...},与上一个参数互斥
		 * fnComputePosition:扩展函数,返回形如{left:...,top:...}的对象
		 * }
		 * 支持的自定义事件:
		 * "draggable.start":drag起始,就是鼠标down后触发
		 * "draggable.move":drag过程中多次触发
		 * "draggable.stop":drag结束触发,就是鼠标up后触发
		 */
		//draggable常量
		$.zUI.draggable = {
			defaults :{
				bOffsetParentBoundary:false,//是否以定位父亲元素为边界
				oBoundary:null,//边界
				fnComputePosition:null//计算位置的函数
			},
			sFlagName:"zUIdraggable",
			sEventName:"zUIdraggableEvent",
			sOptsName:"draggableOpts"
		}
		$.zUI.draggable.fn = function(ele,opts){

			var jqEle = $(ele);
			jqEle.data($.zUI.draggable.sOptsName,$.extend({},$.zUI.draggable.defaults,opts));
			//如果该参数已经执行过draggable了,直接返回,仅相当于修改了配置参数
			if(jqEle.data($.zUI.draggable.sFlagName)){
				return;
			}
			jqEle.data($.zUI.draggable.sFlagName,true);
			jqEle.data($.zUI.draggable.sEventName,{
				mousedown:function(ev){
				var opts = jqEle.data($.zUI.draggable.sOptsName);
				var jqThis = $(this);
				jqThis.trigger("draggable.start");
				var iOffsetX = ev.pageX - this.offsetLeft;
				var iOffsetY = ev.pageY - this.offsetTop;

				function fnMouseMove (ev) {
					var oPos = {};
					if(opts.fnComputePosition){
						oPos = opts.fnComputePosition(ev,iOffsetX,iOffsetY);
					}else{
						oPos.iLeft = ev.pageX - iOffsetX;
						oPos.iTop = ev.pageY - iOffsetY;
					}

					var oBoundary = opts.oBoundary;
					if(opts.bOffsetParentBoundary){//如果以offsetParent作为边界
						var eParent = jqThis.offsetParent()[0];
						oBoundary = {};
						oBoundary.iMinLeft = 0;
						oBoundary.iMinTop = 0;
						oBoundary.iMaxLeft = eParent.clientWidth - jqThis.outerWidth();
						oBoundary.iMaxTop = eParent.clientHeight - jqThis.outerHeight();
					}

					if(oBoundary){//如果存在oBoundary,将oBoundary作为边界
						oPos.iLeft = oPos.iLeft < oBoundary.iMinLeft ? oBoundary.iMinLeft : oPos.iLeft;
						oPos.iLeft = oPos.iLeft > oBoundary.iMaxLeft ? oBoundary.iMaxLeft : oPos.iLeft;
						oPos.iTop = oPos.iTop < oBoundary.iMinTop ? oBoundary.iMinTop : oPos.iTop;
						oPos.iTop = oPos.iTop > oBoundary.iMaxTop ? oBoundary.iMaxTop : oPos.iTop;
					}

					jqThis.css({left:oPos.iLeft,top:oPos.iTop});
					ev.preventDefault();
					jqThis.trigger("draggable.move");
				}

				var oEvent = {
					mousemove:fnMouseMove,
					mouseup:function(){
						$(document).off(oEvent);
						jqThis.trigger("draggable.stop");
					}
				};

				$(document).on(oEvent);
			}});

			jqEle.on(jqEle.data($.zUI.draggable.sEventName));
		}

		$.zUI.draggable.unfn = function(e){
			var jqEle = $(ele);
			if(jqEle.data($.zUI.draggable.sFlagName)){
				jqEle.off(jqEle.data($.zUI.draggable.sEventName));
				jqEle.data($.zUI.draggable.sFlagName,false);
			}
		}

需要说明的有几点:

1.鼠标落下后,要记录鼠标相对元素的位置,mousemove的过程中,要把这段距离减去;

2.jQuery的data方法,这个方法非常方便,可以讲数据和对应的元素绑定,jq.data(key,value)就出存储,jq.data(key)就是读取,jq.data(obj)也是存储。

3.undraggable就是把事件函数去掉了

4.jQuery的on方法非常强大,添加后还可以使用trigger方法来触发,有兴趣的同学可以到官方看看API,on方法非常暴躁,这里的自定义函数,就是用这两个方法实现的。

5.这里是把方法放在了$函数上,最后要把这个方法放在$.fn上,如下:

$.each(["draggable"],function(i,widget){
			unWidget = "un"+widget;
			var w = {};
			w[widget] = function(args){
					this.each(function(){
					$.zUI[widget].fn(this,args);
				});
				return this;
			};
			w[unWidget] = function(){
					this.each(function(){
					$.zUI[unWidget].unfn(this);
				});
				return this;
			}
			$.fn.extend(w);
		});

这里是不是有点乱,其实这么写主要是为了以后写方便;

each除了在jq对象上用之外,还可以使用$.each(Array,fnCallBack);之后添加新的插件后,按照我之前的标准写,只需要在第一个参数上添加其他字符串就可以了。

仔细看看,就是添加了两个方法:draggable和undraggable;这两函数都调用this.each方法,让dragable和undraggable可以再每个元素上都执行。

最后,用一个匿名函数自执行把他们都包起来,为了防止$符号被其他的插件使用,传一个jQuery过去:

(function($){
          .......
})(jQuery);
	

到此为止,这个插件就写完啦。下面是demo的链接地址。

拖拽demo

时间: 2024-10-24 10:50:45

自己写一个jqery的拖拽插件的相关文章

jquery拖拽插件Easydrag

在一些有弹出框的页面,会经常用到拖拽效果来增加用户体验,避免因弹出框遮挡一些元素.如果用原生的js来写的话,js兼容性很不好控制,经常由于浏览器事件的不统一而影响效果,今天给大家介绍一个拖拽插件easydrag,EasyDrag可以指定可拖动的区域,一个setHandler搞定,不错开源是个好东西,只需要一行代码便可轻松在主流浏览器上 使用方法示例: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &q

一步一步实现JS拖拽插件

js拖拽是常见的网页效果,本文将从零开始实现一个简单的js插件. 一.js拖拽插件的原理 常见的拖拽操作是什么样的呢?整过过程大概有下面几个步骤: 1.用鼠标点击被拖拽的元素 2.按住鼠标不放,移动鼠标 3.拖拽元素到一定位置,放开鼠标 这里的过程涉及到三个dom事件:onmousedown,onmousemove,onmouseup.所以拖拽的基本思路就是: 1.用鼠标点击被拖拽的元素触发onmousedown (1)设置当前元素的可拖拽为true,表示可以拖拽 (2)记录当前鼠标的坐标x,y

JQuery之拖拽插件

一直以来,都对JS获取元素的位置感到非常的困惑:一会client.一会offset.一会scroll. 再加上各大浏览器之间的不兼容,唉,搞得哥晕晕乎乎的. 而很多页面效果都要用到这些位置.不得已,得练练,得记记. 下面就来说说这个基于 JQuery的简易拖拽插件吧. 按惯例,先说说拖拽的原理,以及搞这么一个东东的步骤: 那什么是拖拽呢? 看名字就知道了:就是把一个东东拖来拽去的. 放到我们的DOM上,就是改变它的位置. 它只有两个难点:1.如何知道是在拖? 2.如何知道从哪拖,拖到哪? 其实,

Android高级控件(六)——自定义ListView高仿一个QQ可拖拽列表的实现

Android高级控件(六)--自定义ListView高仿一个QQ可拖拽列表的实现 我们做一些好友列表或者商品列表的时候,居多的需求可能就是需要列表拖拽了,而我们选择了ListView,也是因为使用ListView太久远了,导致对他已经有浓厚的感情了,我们之前也是写过几篇关于ListView的博文 Android实训案例(三)--实现时间轴效果的ListView,加入本地存储,实现恋爱日记的效果! Android高级控件(一)--ListView绑定CheckBox实现全选,增加和删除等功能 A

jQuery拖拽插件制作拖拽排序特效

基于jQuery拖拽插件制作拖拽排序特效是一款非常实用的鼠标拖拽布局插件.效果图如下: 在线预览   源码下载 实现的代码. html代码: <h1>水平拖拽</h1> <div class="demo"> <div class="item item1"><span>1</span></div> <div class="item item2"><

vue拖拽插件(弹框拖拽)

// =======拖拽 插件 cnpm install vuedraggableimport draggable from 'vuedraggable' <draggable v-model="tags" :move="getdata" @update="datadragEnd"> <transition-group> <div class="testdiv" v-for="eleme

【原创】js实现一个可随意拖拽排序的菜单导航栏

1.想做这个效果的原因主要是用在UC上看新闻发现他们的导航菜单很有趣.无聊的时候在哪划着玩了很久.所以就干脆自己写一个.原效果如下 2.整体效果如下,在已推荐和未添加里面每个小方块可以触摸移动位置互换.未添加和已添加里面的小方块位置可以拖放. 3.结构分析.整体结构用红线框标出.可以分为三个部分.关注底部拖拽部分.一个div里面嵌套两个div.定位关系如图.本次教程之作一个拖拽框 1.好了,基本情况已经分析清楚先实现页面样式. <div class="wrap"> <

103 extend 插件入口 jquery eq 和get的封装 拖拽插件

//demo.js window.onload = function () { //个人中心 $().getClass("member").hover(function(){ $(this).css("background","url(images/arrow2.png) no-repeat 55px center"); $().getClass("member_ul").show(); },function(){ $().g

拖拽插件SortableJS

在项目中,经常会遇到一些涉及到拖拽的需求,github上面有一个开源的SortableJS的插件,支持Vue,React,Angular等多种框架,实现效果很好,基本可以满足大部分的需求,下面就第一次在jquery中的使用做个简单的demo记录. 引入文件Sortable.min.js 指定包裹容器的id 根据api开始创建使用即可 <!DOCTYPE html> <html> <head> <meta charset="utf-8" />