This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
wcui
Archived
1
0
Fork 0
wcui/js/lib/drag/main.js

217 lines
7.8 KiB
JavaScript
Raw Normal View History

2017-03-30 01:40:59 +08:00
/**
*
* @authors yutent (yutent@doui.cc)
* @date 2017-03-29 18:39:35
*
*/
"use strict";
define(['yua'], function(){
function getBindingCallback(elem, name, vmodels) {
var callback = elem.getAttribute(name)
if (callback) {
for (var i = 0, vm; vm = vmodels[i++]; ) {
if (vm.hasOwnProperty(callback) && typeof vm[callback] === "function") {
return vm[callback]
}
}
}
}
2017-09-13 16:51:15 +08:00
yua.ui.drag = '1.0.0'
2017-03-30 01:40:59 +08:00
// 元素拖动
yua.directive('drag', {
priority: 1500,
init: function(binding){
binding.expr = '"' + binding.expr + '"'
yua(binding.element).css('cursor', 'move')
//取得拖动的3种状态回调
//按下,且拖拽之前
2017-09-04 01:02:25 +08:00
binding.beforedrag = getBindingCallback(binding.element, 'data-beforedrag', binding.vmodels)
2017-03-30 01:40:59 +08:00
//拖拽过程
binding.dragging = getBindingCallback(binding.element, 'data-dragging', binding.vmodels)
// 拖拽结束,且释放鼠标
binding.dragged = getBindingCallback(binding.element, 'data-dragged', binding.vmodels)
//默认允许溢出可视区
binding.overflow = true
2017-03-30 01:40:59 +08:00
//方向,x轴, y轴, xy轴
binding.axis = 'xy'
if(!!binding.element.dataset.axis){
binding.axis = binding.element.dataset.axis
delete binding.element.dataset.axis
}
//默认不限制拖拽区域
binding.limit = false
if(!!binding.element.dataset.limit) {
binding.limit = binding.element.dataset.limit
//这里,只要不为空,除parent外,其他值都默认为window, 故"可溢出"为false
binding.overflow = false
2017-03-30 01:40:59 +08:00
delete binding.element.dataset.limit
}
delete binding.element.dataset.beforedrag
delete binding.element.dataset.dragging
delete binding.element.dataset.dragged
},
update: function(val){
var _this = this,
target = val ? this.element.parentNode : this.element,
$drag = yua(this.element),
$doc = yua(document),
$target = null,
parentElem = null;
2017-03-30 01:40:59 +08:00
// val值不为空时, 获取真正的拖动元素
// 仅从父级上找
while(val && target){
if(target.classList.contains(val) || target.id === val){
break
}else{
target = target.parentNode
}
}
$target = yua(target);
// 限制范围为parent时,获取父级元素
if(this.limit === 'parent'){
parentElem = target.parentNode
2017-03-30 01:40:59 +08:00
}
2017-09-13 16:51:15 +08:00
var dx,dy,mx,my,ox,oy,fox,foy,tw,th,ww,wh,bst,bsl;
2017-03-30 01:40:59 +08:00
$drag.bind('mousedown', function(ev){
var gcs = getComputedStyle(target),
cst = gcs.transform.replace(/matrix\((.*)\)/, '$1'),
offset = $target.offset();
cst = cst !== 'none' ? cst.split(', ') : [1,0,0,1,0,0]
cst[4] -= 0
cst[5] -= 0
//记录初始的transform位移
dx = cst[4]
dy = cst[5]
//滚动条的偏移
bst = $doc.scrollTop()
bsl = $doc.scrollLeft()
2017-03-30 01:40:59 +08:00
// 计算元素的offset值, 需要修正
ox = offset.left - dx - bsl
oy = offset.top - dy - bst
mx = ev.pageX //按下鼠标的的坐标值
my = ev.pageY //按下鼠标的的坐标值
// 在按下时才获取窗口大小, 是为了防止人为的改变窗口大小,导致计算不准备
// 同时减少不必要的事件监听(页面上可能会很多可拖动元素)
ww = window.innerWidth;
wh = window.innerHeight;
// 同样,在点击之后获取元素的宽高,可保证获取到的是真实的值
tw = target.clientWidth;
th = target.clientHeight;
//拖拽前回调
if(_this.beforedrag){
var result = _this.beforedrag.call(_this.vmodels, target, ox, oy)
if(result === false){
return
}
2017-03-30 01:40:59 +08:00
}
//限制区域, 4个值依次是: 上, 下, 左, 右
var limit = [0, wh - th, 0, ww - tw]
if(_this.limit === 'parent') {
var pgcs = getComputedStyle(parentElem),
2017-03-30 01:40:59 +08:00
pcst = pgcs.transform.replace(/matrix\((.*)\)/, '$1'),
poffset = yua(parentElem).offset();
2017-03-30 01:40:59 +08:00
pcst = pcst !== 'none' ? pcst.split(', ') : [1,0,0,1,0,0]
var pox = poffset.left - pcst[4] - bsl,
poy = poffset.top - pcst[5] - bst;
limit = [poy, poy + parentElem.clientHeight - th, pox, pox + parentElem.clientWidth - tw]
2017-03-30 01:40:59 +08:00
}
var mvfn = $doc.bind('mousemove', function(ev){
//坐标轴限制
if(_this.axis !== 'y'){
cst[4] = ev.pageX - mx + dx
}
if(_this.axis !== 'x'){
cst[5] = ev.pageY - my + dy
}
2017-09-13 16:51:15 +08:00
fox = ox + cst[4], //修正的offset
foy = oy + cst[5]; //修正的offset
2017-03-30 01:40:59 +08:00
//如果不允许溢出可视区
if(!_this.overflow){
if(_this.axis !== 'y'){
if(fox <= limit[2]) {
fox = limit[2]
//修正矩阵
cst[4] = fox - ox
}
if(fox >= limit[3]){
fox = limit[3]
//修正矩阵
cst[4] = fox - ox
}
}
if(_this.axis !== 'x'){
if(foy <= limit[0]) {
foy = limit[0]
//修正矩阵
cst[5] = foy - oy
}
if(foy >= limit[1]){
foy = limit[1]
//修正矩阵
cst[5] = foy - oy
}
}
}
$target.css({
transform: 'matrix(' + cst.join(', ') + ')'
})
//拖拽过程的回调
if(_this.dragging){
_this.dragging.call(_this.vmodels, target, fox, foy)
}
// 防止拖动到边缘时导致页面滚动
ev.preventDefault()
}),
upfn = $doc.bind('mouseup', function(ev){
$doc.unbind('mousemove', mvfn)
$doc.unbind('mouseup', upfn)
//结束回调
if(_this.dragged){
_this.dragged.call(_this.vmodels, target, fox, foy)
}
});
})
}
})
})