587 lines
23 KiB
JavaScript
587 lines
23 KiB
JavaScript
/*! Tdrag 0.0.1 */
|
||
/**
|
||
* Created by Tezml on 2016/5/26
|
||
* You can modify my source code, if you have a good idea or a problem can be encountered by e-mail: tezml@tezml.com to find me.
|
||
* 如果你想在项目中使用该插件,请不要删除该注释。
|
||
*/
|
||
;(function($,window,document,undefined){
|
||
jQuery(function() {
|
||
//插件制作
|
||
|
||
|
||
$.fn.Tdrag = function (opt) {
|
||
var call = {
|
||
scope: null,//父级
|
||
grid: null,//网格
|
||
axis:"all",//上下或者左右
|
||
pos:false,//是否记住位置
|
||
handle:null,//手柄
|
||
moveClass:"tezml",//移动时不换位加的class
|
||
dragChange:false,//是否开启拖拽换位
|
||
changeMode:"point",//point & sort
|
||
cbStart:function(){},//移动前的回调函数
|
||
cbMove:function(){},//移动中的回调函数
|
||
cbEnd:function(){},//移动结束时候的回调函数
|
||
random:false,//是否自动随机排序
|
||
randomInput:null,//点击随机排序的按钮
|
||
animation_options:{//运动时的参数
|
||
duration:800,//每次运动的时间
|
||
easing:"ease-out"//移动时的特效,ease-out、ease-in、linear
|
||
},
|
||
disable:false,//禁止拖拽
|
||
disableInput:null//禁止拖拽的按钮
|
||
};
|
||
var dragfn = new Dragfn(this, opt);
|
||
if (opt && $.isEmptyObject(opt) == false) {
|
||
dragfn.options = $.extend(call, opt);
|
||
} else {
|
||
dragfn.options = call;
|
||
}
|
||
dragfn.firstRandom=true;
|
||
var ele = dragfn.$element;
|
||
dragfn.pack(ele,false);
|
||
if(dragfn.options.randomInput!=null){
|
||
$(dragfn.options.randomInput).bind("click",function(){
|
||
dragfn.pack(ele,true);
|
||
})
|
||
}
|
||
//加载拓展jquery的函数
|
||
dragfn.loadJqueryfn()
|
||
};
|
||
|
||
//依赖构造函数
|
||
var Dragfn = function (ele, opt) {
|
||
this.$element = ele;
|
||
this.options = opt;
|
||
};
|
||
//构造函数方法
|
||
Dragfn.prototype = {
|
||
init: function (obj) {
|
||
var self = this;
|
||
self.ele=self.$element;
|
||
self.handle=$(obj);//手柄
|
||
self.options = self.options;
|
||
self.disable = self.options.disable;
|
||
self._start = false;
|
||
self._move = false;
|
||
self._end = false;
|
||
self.disX = 0;
|
||
self.disY = 0;
|
||
self.zIndex=1000;
|
||
self.moving=false;
|
||
self.moves="";
|
||
|
||
|
||
//父级
|
||
self.box = $.type(self.options.scope)==="string" ? self.options.scope : null;
|
||
//手柄
|
||
if(self.options.handle!=null){
|
||
self.handle=$(obj).find(self.options.handle);
|
||
}
|
||
|
||
//三个事件
|
||
self.handle.on("mousedown", function (ev) {
|
||
self.start(ev, obj);
|
||
obj.setCapture && obj.setCapture();
|
||
return false;
|
||
});
|
||
if(self.options.dragChange) {
|
||
$(obj).on("mousemove", function (ev) {
|
||
self.move(ev, obj);
|
||
});
|
||
$(obj).on("mouseup", function (ev) {
|
||
self.end(ev, obj);
|
||
});
|
||
}else{
|
||
$(document).on("mousemove", function (ev) {
|
||
self.move(ev, obj);
|
||
});
|
||
$(document).on("mouseup", function (ev) {
|
||
self.end(ev, obj);
|
||
});
|
||
}
|
||
},
|
||
//jquery调取函数时候用
|
||
loadJqueryfn: function(){
|
||
var self=this;
|
||
$.extend({
|
||
//返回按照index排序的回调函数
|
||
sortBox:function(obj){
|
||
var arr=[];
|
||
for (var s = 0; s < $(obj).length; s++) {
|
||
arr.push($(obj).eq(s));
|
||
}
|
||
for ( var i = 0; i < arr.length; i++) {
|
||
for ( var j = i + 1; j < arr.length; j++) {
|
||
if(Number(arr[i].attr("index")) > Number(arr[j].attr("index"))){
|
||
var temp = arr[i];
|
||
arr[i] = arr[j];
|
||
arr[j] = temp;
|
||
}
|
||
}
|
||
}
|
||
return arr
|
||
},
|
||
//随机排序函数
|
||
randomfn:function(obj){
|
||
self.pack($(obj),true);
|
||
},
|
||
//开启拖拽
|
||
disable_open:function(){
|
||
self.disable=false;
|
||
},
|
||
//禁止拖拽
|
||
disable_cloose:function(){
|
||
self.disable=true;
|
||
}
|
||
});
|
||
},
|
||
toDisable: function(){
|
||
var self=this;
|
||
if(self.options.disableInput!=null){
|
||
$(self.options.disableInput).bind("click",function(){
|
||
if(self.disable==true){
|
||
self.disable=false
|
||
}else{
|
||
self.disable=true
|
||
}
|
||
})
|
||
}
|
||
},
|
||
start: function (ev, obj) {
|
||
var self = this;
|
||
self.moved=obj;
|
||
if (self.disable == true) {
|
||
return false
|
||
}
|
||
self._start = true;
|
||
var oEvent = ev || event;
|
||
self.disX = oEvent.clientX - obj.offsetLeft;
|
||
self.disY = oEvent.clientY - obj.offsetTop;
|
||
$(obj).css("zIndex",self.zIndex++);
|
||
self.options.cbStart();
|
||
},
|
||
move: function (ev, obj) {
|
||
var self = this;
|
||
if (self._start != true) {
|
||
return false
|
||
}
|
||
if(obj!=self.moved){
|
||
return false
|
||
}
|
||
self._move = true;
|
||
var oEvent = ev || event;
|
||
var l = oEvent.clientX - self.disX;
|
||
var t = oEvent.clientY - self.disY;
|
||
//有父级限制
|
||
if (self.box != null) {
|
||
var rule = self.collTestBox(obj,self.box);
|
||
if (l > rule.lmax) {
|
||
l = rule.lmax;
|
||
} else if (l < rule.lmin) {
|
||
l = rule.lmin;
|
||
}
|
||
if (t > rule.tmax) {
|
||
t = rule.tmax;
|
||
} else if (t < rule.tmin) {
|
||
t = rule.tmin;
|
||
}
|
||
}
|
||
if(self.options.axis=="all"){
|
||
obj.style.left = self.grid(obj, l, t).left + 'px';
|
||
obj.style.top = self.grid(obj, l, t).top + 'px';
|
||
}else if(self.options.axis=="y"){
|
||
obj.style.top = self.grid(obj, l, t).top + 'px';
|
||
}else if(self.options.axis=="x"){
|
||
obj.style.left = self.grid(obj, l, t).left + 'px';
|
||
}
|
||
/* if(self.options.changeWhen=="move") {
|
||
if (self.options.changeMode == "sort") {
|
||
self.sortDrag(obj);
|
||
} else if (self.options.changeMode == "point") {
|
||
self.pointmoveDrag(obj);
|
||
}
|
||
}else{
|
||
self.moveAddClass(obj);
|
||
}*/
|
||
if(self.options.pos==true){
|
||
self.moveAddClass(obj);
|
||
}
|
||
self.options.cbMove(obj,self);
|
||
|
||
},
|
||
end: function (ev, obj) {
|
||
var self = this;
|
||
if (self._start != true) {
|
||
return false
|
||
}
|
||
if(self.options.changeMode=="sort"&&self.options.pos==true){
|
||
self.sortDrag(obj);
|
||
}else if(self.options.changeMode=="point"&&self.options.pos==true){
|
||
self.pointDrag(obj);
|
||
}
|
||
if(self.options.pos==true){
|
||
self.animation(obj, self.aPos[$(obj).attr("index")]);
|
||
}
|
||
self.options.cbEnd();
|
||
if(self.options.handle!=null){
|
||
$(obj).find(self.options.handle).unbind("onmousemove");
|
||
$(obj).find(self.options.handle).unbind("onmouseup");
|
||
}else{
|
||
$(obj).unbind("onmousemove");
|
||
$(obj).unbind("onmouseup");
|
||
}
|
||
obj.releaseCapture && obj.releaseCapture();
|
||
self._start = false;
|
||
|
||
},
|
||
//算父级的宽高
|
||
collTestBox: function (obj, obj2) {
|
||
var self = this;
|
||
var l1 = 0;
|
||
var t1 = 0;
|
||
var l2 = $(obj2).innerWidth() - $(obj).outerWidth();
|
||
var t2 = $(obj2).innerHeight() - $(obj).outerHeight();
|
||
return {
|
||
lmin: l1,//取的l最小值
|
||
tmin: t1,//取的t最小值
|
||
lmax: l2,//取的l最大值
|
||
tmax: t2//取的t最大值
|
||
}
|
||
|
||
},
|
||
//算父级宽高时候干掉margin
|
||
grid: function (obj, l, t) {//cur:[width,height]
|
||
var self = this;
|
||
var json = {
|
||
left: l,
|
||
top: t
|
||
};
|
||
if ($.isArray(self.options.grid) && self.options.grid.length == 2) {
|
||
var gx = self.options.grid[0];
|
||
var gy = self.options.grid[1];
|
||
json.left = Math.floor((l + gx / 2) / gx) * gx;
|
||
json.top = Math.floor((t + gy / 2) / gy) * gy;
|
||
return json
|
||
} else if (self.options.grid == null) {
|
||
return json
|
||
} else {
|
||
console.log("grid参数传递格式错误");
|
||
return false
|
||
}
|
||
},
|
||
findNearest: function(obj){
|
||
var self=this;
|
||
var iMin=new Date().getTime();
|
||
var iMinIndex=-1;
|
||
var ele=self.ele;
|
||
for(var i=0;i<ele.length;i++){
|
||
if(obj==ele[i]){
|
||
continue;
|
||
}
|
||
if(self.collTest(obj,ele[i])){
|
||
var dis=self.getDis(obj,ele[i]);
|
||
if(dis<iMin){
|
||
iMin=dis;
|
||
iMinIndex=i;
|
||
}
|
||
}
|
||
}
|
||
if(iMinIndex==-1){
|
||
return null;
|
||
}else{
|
||
return ele[iMinIndex];
|
||
}
|
||
},
|
||
getDis: function(obj,obj2){
|
||
var self=this;
|
||
var l1=obj.offsetLeft+obj.offsetWidth/2;
|
||
var l2=obj2.offsetLeft+obj2.offsetWidth/2;
|
||
|
||
var t1=obj.offsetTop+obj.offsetHeight/2;
|
||
var t2=obj2.offsetTop+obj2.offsetHeight/2;
|
||
|
||
var a=l2-l1;
|
||
var b=t1-t2;
|
||
|
||
return Math.sqrt(a*a+b*b);
|
||
},
|
||
collTest: function(obj,obj2){
|
||
var self=this;
|
||
var l1=obj.offsetLeft;
|
||
var r1=obj.offsetLeft+obj.offsetWidth;
|
||
var t1=obj.offsetTop;
|
||
var b1=obj.offsetTop+obj.offsetHeight;
|
||
|
||
var l2=obj2.offsetLeft;
|
||
var r2=obj2.offsetLeft+obj2.offsetWidth;
|
||
var t2=obj2.offsetTop;
|
||
var b2=obj2.offsetTop+obj2.offsetHeight;
|
||
|
||
if(r1<l2 || r2<l1 || t2>b1 || b2<t1){
|
||
return false;
|
||
}else{
|
||
return true;
|
||
}
|
||
},
|
||
//初始布局转换
|
||
pack: function(ele,click){
|
||
var self=this;
|
||
self.toDisable();
|
||
if(self.options.pos==false){
|
||
for (var i = 0; i < ele.length; i++) {
|
||
$(ele[i]).css("position", "absolute");
|
||
$(ele[i]).css("margin", "0");
|
||
self.init(ele[i]);
|
||
}
|
||
}else if(self.options.pos==true) {
|
||
var arr = [];
|
||
if (self.options.random || click) {
|
||
while (arr.length < ele.length) {
|
||
var n = self.rnd(0, ele.length);
|
||
if (!self.finInArr(arr, n)) {//没找到
|
||
arr.push(n);
|
||
}
|
||
}
|
||
}
|
||
if (self.options.random == false || click != true) {
|
||
var n = 0;
|
||
while (arr.length < ele.length) {
|
||
arr.push(n);
|
||
n++
|
||
}
|
||
}
|
||
|
||
//如果是第二次以后随机列表,那就重新排序后再随机,因为我智商不够使,不会排了
|
||
if (self.firstRandom == false) {
|
||
var sortarr = [];
|
||
var n = 0;
|
||
while (sortarr.length < ele.length) {
|
||
sortarr.push(n);
|
||
n++
|
||
}
|
||
for (var i = 0; i < ele.length; i++) {
|
||
$(ele[i]).attr("index", sortarr[i]);
|
||
$(ele[i]).css("left", self.aPos[sortarr[i]].left);
|
||
$(ele[i]).css("top", self.aPos[sortarr[i]].top);
|
||
}
|
||
}
|
||
|
||
//布局转化
|
||
self.aPos = [];
|
||
if (self.firstRandom == false) {
|
||
//不是第一次
|
||
for (var j = 0; j < ele.length; j++) {
|
||
self.aPos[j] = {
|
||
left: ele[$(ele).eq(j).attr("index")].offsetLeft,
|
||
top: ele[$(ele).eq(j).attr("index")].offsetTop
|
||
};
|
||
}
|
||
} else {
|
||
//第一次
|
||
for (var j = 0; j < ele.length; j++) {
|
||
self.aPos[j] = {left: ele[j].offsetLeft, top: ele[j].offsetTop};
|
||
}
|
||
}
|
||
//第二个循环布局转化
|
||
for (var i = 0; i < ele.length; i++) {
|
||
$(ele[i]).attr("index", arr[i]);
|
||
$(ele[i]).css("left", self.aPos[arr[i]].left);
|
||
$(ele[i]).css("top", self.aPos[arr[i]].top);
|
||
$(ele[i]).css("position", "absolute");
|
||
$(ele[i]).css("margin", "0");
|
||
self.init(ele[i]);
|
||
}
|
||
self.firstRandom = false;
|
||
}
|
||
},
|
||
//移动时候加class
|
||
moveAddClass: function(obj){
|
||
var self=this;
|
||
var oNear=self.findNearest(obj);
|
||
$(self.$element).removeClass(self.options.moveClass);
|
||
if(oNear && $(oNear).hasClass(self.options.moveClass)==false){
|
||
$(oNear).addClass(self.options.moveClass);
|
||
}
|
||
|
||
},
|
||
//给li排序
|
||
sort: function(){
|
||
var self=this;
|
||
var arr_li=[];
|
||
for (var s = 0; s < self.$element.length; s++) {
|
||
arr_li.push(self.$element[s]);
|
||
}
|
||
for ( var i = 0; i < arr_li.length; i++) {
|
||
for ( var j = i + 1; j < arr_li.length; j++) {
|
||
if(Number($(arr_li[i]).attr("index")) > Number($(arr_li[j]).attr("index"))){
|
||
var temp = arr_li[i];
|
||
arr_li[i] = arr_li[j];
|
||
arr_li[j] = temp;
|
||
}
|
||
}
|
||
}
|
||
return arr_li;
|
||
},
|
||
//点对点的方式换位
|
||
pointDrag: function(obj){
|
||
var self=this;
|
||
//先拍序
|
||
var oNear=self.findNearest(obj);
|
||
if (oNear) {
|
||
self.animation(obj,self.aPos[$(oNear).attr("index")]);
|
||
self.animation(oNear, self.aPos[$(obj).attr("index")]);
|
||
var tmp;
|
||
tmp = $(obj).attr("index");
|
||
$(obj).attr("index", $(oNear).attr("index"));
|
||
$(oNear).attr("index", tmp);
|
||
$(oNear).removeClass(self.options.moveClass);
|
||
} else if (self.options.changeWhen == "end") {
|
||
self.animation(obj, self.aPos[$(obj).attr("index")]);
|
||
}
|
||
|
||
},
|
||
//排序的方式换位
|
||
sortDrag: function(obj){
|
||
var self=this;
|
||
//先拍序
|
||
var arr_li=self.sort();
|
||
//换位置
|
||
var oNear=self.findNearest(obj);
|
||
if(oNear){
|
||
if(Number($(oNear).attr("index"))>Number($(obj).attr("index"))){
|
||
//前换后
|
||
var obj_tmp=Number($(obj).attr("index"));
|
||
$(obj).attr("index",Number($(oNear).attr("index"))+1);
|
||
for (var i = obj_tmp; i < Number($(oNear).attr("index"))+1; i++) {
|
||
self.animation(arr_li[i],self.aPos[i-1]);
|
||
self.animation(obj,self.aPos[$(oNear).attr("index")]);
|
||
$(arr_li[i]).removeClass(self.options.moveClass);
|
||
$(arr_li[i]).attr("index",Number($(arr_li[i]).attr("index"))-1);
|
||
}
|
||
|
||
}else if(Number($(obj).attr("index"))>Number($(oNear).attr("index"))){
|
||
//后换前
|
||
var obj_tmp=Number($(obj).attr("index"));
|
||
$(obj).attr("index",$(oNear).attr("index"));
|
||
for (var i = Number($(oNear).attr("index")); i < obj_tmp; i++) {
|
||
self.animation(arr_li[i],self.aPos[i+1]);
|
||
self.animation(obj,self.aPos[Number($(obj).attr("index"))]);
|
||
$(arr_li[i]).removeClass(self.options.moveClass);
|
||
$(arr_li[i]).attr("index",Number($(arr_li[i]).attr("index"))+1);
|
||
}
|
||
}
|
||
}else{
|
||
self.animation(obj,self.aPos[$(obj).attr("index")]);
|
||
}
|
||
|
||
},
|
||
//运动函数(后期再加参数)
|
||
animation: function(obj,json){
|
||
var self=this;
|
||
//考虑默认值
|
||
var options=self.options.animation_options; /*|| {};
|
||
options.duration=self.options.animation_options.duration || 800;
|
||
options.easing=options.easing.duration.easing || 'ease-out';*/
|
||
var self=this;
|
||
var count=Math.round(options.duration/30);
|
||
var start={};
|
||
var dis={};
|
||
for(var name in json){
|
||
start[name]=parseFloat(self.getStyle(obj,name));
|
||
if(isNaN(start[name])){
|
||
switch(name){
|
||
case 'left':
|
||
start[name]=obj.offsetLeft;
|
||
break;
|
||
case 'top':
|
||
start[name]=obj.offsetTop;
|
||
break;
|
||
case 'width':
|
||
start[name]=obj.offsetWidth;
|
||
break;
|
||
case 'height':
|
||
start[name]=obj.offsetHeight;
|
||
break;
|
||
case 'marginLeft':
|
||
start[name]=obj.offsetLeft;
|
||
break;
|
||
case 'borderWidth':
|
||
start[name]=0;
|
||
break;
|
||
//...
|
||
}
|
||
}
|
||
dis[name]=json[name]-start[name];
|
||
}
|
||
|
||
var n=0;
|
||
|
||
clearInterval(obj.timer);
|
||
obj.timer=setInterval(function(){
|
||
n++;
|
||
for(var name in json){
|
||
switch(options.easing){
|
||
case 'linear':
|
||
var a=n/count;
|
||
var cur=start[name]+dis[name]*a;
|
||
break;
|
||
case 'ease-in':
|
||
var a=n/count;
|
||
var cur=start[name]+dis[name]*a*a*a;
|
||
break;
|
||
case 'ease-out':
|
||
var a=1-n/count;
|
||
var cur=start[name]+dis[name]*(1-a*a*a);
|
||
break;
|
||
}
|
||
|
||
if(name=='opacity'){
|
||
obj.style.opacity=cur;
|
||
obj.style.filter='alpha(opacity:'+cur*100+')';
|
||
}else{
|
||
obj.style[name]=cur+'px';
|
||
}
|
||
}
|
||
|
||
if(n==count){
|
||
clearInterval(obj.timer);
|
||
options.complete && options.complete();
|
||
}
|
||
},30);
|
||
},
|
||
getStyle: function(obj,name){
|
||
return (obj.currentStyle || getComputedStyle(obj,false))[name];
|
||
},
|
||
//随机数
|
||
rnd: function(n,m){
|
||
return parseInt(Math.random()*(m-n)+n);
|
||
},
|
||
//在数组中找
|
||
finInArr: function(arr,n){
|
||
for(var i = 0 ; i < arr.length; i++){
|
||
if(arr[i] == n){//存在
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
}
|
||
})
|
||
})(jQuery,window,document);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|