1.index.html填充靜態(tài)數(shù)據(jù)
在index.html頁面id="user-choosn-tool"的元素下拷貝5個圖標(biāo)
<div class="ico_03 color ico_box" id="user-choosn-tool" style="position: relative;">
<dl class="drag-element cross-element" data-index="0" style="left: 0px; top: 20px;">
<a href="javascript:void(0);">
<dd>
<img src="/images/ico_1.png">
</dd>
<dt name="Portal_Reimburse">我的報銷</dt>
</a>
</dl>
<dl class="drag-element cross-element" data-index="1" style="left: 100px; top: 20px;">
<a href="javascript:void(0);">
<dd>
<img src="/images/ico_2.png">
</dd>
<dt name="Portal_Reimburse">我的考勤</dt>
</a>
</dl>
<dl class="drag-element cross-element" data-index="2" style="left: 200px; top: 20px;">
<a href="javascript:void(0);">
<dd>
<img src="/images/ico_3.png">
</dd>
<dt name="Portal_Reimburse">通訊錄</dt>
</a>
</dl>
<dl class="drag-element cross-element" data-index="3" style="left: 300px; top: 20px;">
<a href="javascript:void(0);">
<dd>
<img src="/images/ico_4.png">
</dd>
<dt name="Portal_Reimburse">請假管理</dt>
</a>
</dl>
<dl class="" id="submit-btn" style="left: 400px; top: 20px;">
<a href="javascript: void(0);">
<dd class="tj_ico">
<img src="/images/ico_bc_2.png">
</dd>
<dt>保存</dt>
</a>
</dl>
<div class="clear"></div>
</div>
啟動項目,在瀏覽器中打開http://localhost:3000户辞,頁面輸出如下圖
image.png
2.拖拽
2.1 添加drag.js
在javascripts文件夾下新建drag.js文件翔横,然后在index.html頁面引入下面的三個js文件
<script type="text/javascript" src="/javascripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="/javascripts/jquery.easing.min.js"></script>
<script type="text/javascript" src="/javascripts/drag.js"></script>
2.2 添加Drag構(gòu)造函數(shù)
drag.js的代碼如下,這里使用閉包啊掏,防止污染外部變量
(function ($) {
function Drag(el, options){
this.$el = el;
this.options = options;
this.init();
}
Drag.prototype = {
init: function() {
console.log('init')
}
}
var DEFAULTS = {
duration: 500, //運動持續(xù)時間
easing: 'easeInOutBack', // 動畫效果
submitBtn: '#submit-btn', //提交按鈕
leftDistance: 100, // 每個元素間的間距
dragEleClass: '', // 可拖拽的一組元素
dragLimitId: '', // 拖拽元素的父元素蠢络,限制拖拽元素的拖拽區(qū)域
crossEleClass: '.cross-element', // 跟哪組元素做碰撞
crossChangeEle: 'dd', //碰撞之后要改變的元素
crossChangeStyle: 'borderColor', //碰撞元素要改變的樣式
crossChangeValue: '#f00', //碰撞元素要改變成什么樣式值
dragAfter: function () { } //拖拽之后執(zhí)行的方法
};
// 使用jQuery添加一個實例方法,讓外界元素調(diào)用
$.fn.drag = function(option){
var options = $.extend(true, {}, DEFAULTS, typeof option === 'object' && option),
args = Array.prototype.slice.call(arguments);
args.shift();
return this.each(function(){
var $el = $(this),
instance = $el.data('drag');
if(!instance){
$el.data('drag', (instance = new Drag($el, options)));
}
if(typeof option === 'string'){
instance[option].apply(instance, args);
}
});
}
})(jQuery);
2.3 添加index.js
在javascripts文件夾下新建一個index.js文件迟蜜,并且在index.html引入該文件刹孔,index.js文件代碼如下
(function ($) {
$('#user-choosn-tool').find('.drag-element').drag({
'dragLimitId': '#user-choosn-tool',
'dragEleClass': '.drag-element'
});
})(jQuery);
到這里刷新瀏覽器,可以看到控制臺上打印了4次 "init"
image.png
2.4 定位元素
image.png
如上圖娜睛,在index.html頁面里面髓霞,每個圖標(biāo)的left值都是寫死的,在實際應(yīng)用中這樣肯定是不合理的畦戒,我們需要在程序里計算出每個圖標(biāo)的位置方库,此時drag.js的部分代碼如下
Drag.prototype = {
init: function () {
var self = this,
opt = self.options;
self.leftDistance = opt.leftDistance;
self.$limit = $(opt.dragLimitId);
self.$dragEles = self.$limit.find(opt.dragEleClass);
self.$btn = $(opt.submitBtn);
self.setPosition();
self.initLocation();
self.initBtnLocation();
return self;
},
// 初始化元素位置
initLocation: function () {
var self = this,
leftDistance = self.leftDistance,
$el = self.$el;
$limit = self.$limit;
var left = self.getIndex($el) * leftDistance,
top = 20;
$el.css({
'left': left,
'top': top
});
return self;
},
// 初始化保存按鈕的位置
initBtnLocation: function () {
var self = this,
$lastDragPos = self.$dragEles.last().position(),
btnLeft = Math.ceil($lastDragPos.left + self.leftDistance),
btnTop = $lastDragPos.top;
self.$btn.css({
'position': 'absolute',
'left': btnLeft,
'top': btnTop
});
return self;
},
// 給父元素設(shè)置定位
setPosition: function () {
var $limit = this.$limit;
if( $limit.length > 0 && $limit.css('position') === 'static' ){
$limit.css('position', 'relative');
}
return this;
},
getIndex: function ($el) {
return $el.attr('data-index') || $el.data('index') || $el.index();
}
}
到這里,就可以把index.html頁面的那些定位樣式去掉了障斋,刷新瀏覽器可以看到頁面展示效果一致
2.5 綁定拖拽事件
給可拖拽的元素綁定事件纵潦,drag.js的部分代碼如下
init: function () {
var self = this,
opt = self.options;
self.leftDistance = opt.leftDistance;
self.$limit = $(opt.dragLimitId);
self.$dragEles = self.$limit.find(opt.dragEleClass);
self.$crossEles = opt.crossEleClass ? $(opt.crossEleClass) : self.$dragEles;
self.$btn = $(opt.submitBtn);
self.originVal = self.$dragEles.find(opt.crossChangeEle).css(opt.crossChangeStyle);
self.setPosition();
self.initLocation();
self.initBtnLocation();
self.bindEvent();
return self;
},
bindEvent: function () {
var self = this,
opt = self.options,
$el = self.$el,
$limit = self.$limit;
$el.mousedown(function(e){
e.preventDefault();
var isAnimated = false;
self.$dragEles.each(function(){
if($(this).is(':animated')){
isAnimated = true;
return false;
}
});
if(isAnimated){
return;
}
var pos = $el.position(),
disX = e.pageX - pos.left,
disY = e.pageY - pos.top,
$nearest = '';
// 拖拽之前先保留一些信息
$el.data({
'originLeft': pos.left,
'originTop': pos.top,
'zIndex': $el.css('zIndex') || 1
});
$(document).on('mousemove.drag', function(e){
$el.css({
'left': e.pageX - disX,
'top': e.pageY - disY,
'zIndex': 999
});
if ($limit.length > 0) {
self.checkDragPos();
}
$nearest = self.nearest();
if ($nearest) {
self.$crossEles.find(opt.crossChangeEle).css(opt.crossChangeStyle, self.originVal);
$nearest.find(opt.crossChangeEle).css(opt.crossChangeStyle, opt.crossChangeValue);
} else {
self.$crossEles.find(opt.crossChangeEle).css(opt.crossChangeStyle, self.originVal);
}
}).on('mouseup.drag', function(){
$(this).off('.drag');
typeof self.options.dragAfter === 'function' && self.options.dragAfter.call(self);
// 拖拽結(jié)束徐鹤,如果沒有最近的元素就把位置還原
if (!$nearest) {
$el.animate({
'left': $el.data('originLeft'),
'top': $el.data('originTop')
}, opt.duration, opt.easing, function(){
$el.css('zIndex', $el.data('zIndex'));
});
} else {
self.moveDragPos($nearest);
}
});
});
return self;
}
2.6 檢查拖拽元素位置
在拖拽的過程中,需要時刻檢測拖拽元素的位置邀层,不能讓拖拽元素拖到limit元素的外面去
checkDragPos: function () {
var self = this,
$el = self.$el,
$limit = self.$limit,
pos = $el.position(),
maxTop = $limit.outerHeight() - $el.outerHeight(true),
maxLeft = $limit.outerWidth() - $el.outerWidth(true);
if(pos.top < 0){
$el.css('top', 0);
} else if(pos.top > maxTop){
$el.css('top', maxTop);
}
if(pos.left < 0){
$el.css('left', 0);
} else if(pos.left > maxLeft){
$el.css('left', maxLeft);
}
return self;
}
2.7 獲取離拖拽元素最近的元素
拖拽過程中返敬,還需要時刻檢查離拖拽元素最近的元素
nearest: function () {
var self = this,
$el = self.$el,
$eles = self.$crossEles;
value = 9999,
index = -1;
for(var i = 0; i < $eles.length; i++){
var $obj = $eles.eq(i);
if($el.attr('data-index') == $obj.attr('data-index')){
continue;
}
if(self.isCross($el, $obj)){
var d = self.distance($el, $obj);
if(d < value){
value = d;
index = i;
}
}
}
if(index !== -1){
return $eles.eq(index);
} else{
return false;
}
}
2.8 碰撞檢測
拖拽過程中,判斷nearest元素是否和拖拽元素有重疊寥院,如果重疊需要給重疊的元素設(shè)置一些樣式劲赠,提升用戶體驗
isCross: function ($el1, $el2) {
var pos1 = $el1.position(),
pos2 = $el2.position(),
t1 = pos1.top,
b1 = pos1.top + $el1.innerHeight(),
l1 = pos1.left,
r1 = pos1.left + $el1.innerWidth(),
t2 = pos2.top,
b2 = pos2.top + $el2.innerHeight(),
l2 = pos2.left,
r2 = pos2.left + $el2.innerWidth();
if(t1 > b2 || b1 < t2 || r1 < l2 || l1 > r2){
return false;
} else{
return true;
}
}
2.9 移動元素位置
拖拽結(jié)束時(mouseup事件),如果有重疊的元素秸谢,就需要移動元素的位置
moveDragPos: function ($nearest) {
var self = this,
opt = self.options,
index = $nearest.attr('data-index'),
length = self.$el.attr('data-index');
self.$crossEles.each(function(){
var $this = $(this);
if($this.get(0) != self.$el.get(0)){
$this.data({
'originTop': $this.position().top,
'originLeft': $this.position().left,
'originIndex': $this.attr('data-index')
});
}
});
if(length > index){ // 向前拖拽
for(var i = length - 1; i >= index; i--){
(function(i){
var $ele = self.$crossEles.eq(0).parent().find('[data-index=' + i + ']'),
$nextEle = self.$crossEles.eq(0).parent().find('[data-index=' + (i + 1) + ']'),
top = $nextEle.data('originTop'),
left = $nextEle.data('originLeft'),
_index = Number($ele.attr('data-index'));
$ele.delay( (i - index) * 80 ).animate({
'top': top,
'left': left //'+=100px'
}, 200, 'linear', function(){
$(this).attr('data-index', _index + 1).find(opt.crossChangeEle).css(opt.crossChangeStyle, self.originVal);
});
if(i == index){
self.timer = setTimeout(function(){
self.$el.animate({
'top': $nearest.data('originTop'),
'left': $nearest.data('originLeft')
}, 100, 'linear', function(){
$(this).attr('data-index', $nearest.data('originIndex')).css('zIndex', $(this).data('zIndex'));
});
}, (length - index) * 110);
}
})(i);
}
} else if(length < index){ // 向后拖拽
for(var i = index; i > length; i--){
(function(i){
var $ele = self.$crossEles.eq(0).parent().find('[data-index=' + i + ']'),
$nextEle = self.$crossEles.eq(0).parent().find('[data-index=' + (i - 1) + ']'),
top = $nextEle.data('originTop'),
left = $nextEle.data('originLeft'),
_index = Number($ele.attr('data-index'));
$ele.delay( (index - i) * 80 ).animate({
'top': top,
'left': left //'-=100px'
}, 200, 'linear', function(){
$(this).attr('data-index', _index - 1).find(opt.crossChangeEle).css(opt.crossChangeStyle, self.originVal);
});
if(i == index){
self.timer = setTimeout(function(){
self.$el.animate({
'top': $nearest.data('originTop'),
'left': $nearest.data('originLeft')
}, 100, 'linear', function(){
$(this).attr('data-index', $nearest.data('originIndex')).css('zIndex', $(this).data('zIndex'));
});
}, (index - length) * 110);
}
})(i);
}
}
}
到這里拖拽的功能基本就完成了凛澎,下一篇就是從接口獲取數(shù)據(jù)了