菜单

银河官方网站:面向对象实战之封装拖拽对象,常用函数

2019年10月5日 - 银河官方网站
银河官方网站:面向对象实战之封装拖拽对象,常用函数

前边多个基础晋级(10):面向对象实战之封装拖拽对象

2017/04/02 · JavaScript
·
面向对象

原稿出处: 波同学   

银河官方网站 1

终于

前边几篇小说,作者跟大家分享了JavaScript的片段基础知识,那篇小说,将会进来第一个实战环节:利用前面几章的所关联到的学识,封装三个拖拽对象。为了能够扶助大家精通更加多的格局与举办自查自纠,笔者会使用三种分化的方法来促成拖拽。

正文的例子会停放于codepen.io中,供我们在读书时平素查看。即使对于codepen不领悟的校友,能够花点时间稍微领悟一下。

拖拽的兑现进度会涉嫌到非常多的实用小知识,由此为了加固本身自个儿的文化储存,也为了大家能够学到越来越多的学问,作者会尽量详细的将有个别细节分享出来,相信我们认真读书之后,一定能学到一些东西。

复制代码 代码如下:

1、如何让三个DOM成分动起来

咱俩平时会因而改形成分的top,left,translate来其的岗位爆发转移。在底下的例证中,每点击贰次按键,对应的因素就能够移动5px。大家可点击查看。

点击查阅贰个让成分动起来的小例子

是因为修改三个要素top/left值会引起页面重绘,而translate不会,由此从性质优化上来剖断,大家会先行使用translate属性。

//获取元素的样式值。
function getStyle(elem,name){
if(elem.style[name]){
return elem.style[name];
}else if(elem.currentStyle){
return elem.currentStyle[name];
}else if(document.defaultView&&document.defaultView.getComputedStyle){
name=name.replace(/([A-Z])/g,”-$1″);
name=name.toLowerCase();
var s=document.defaultView.getComputedStyle(elem,””);
return s&&s.getPropertyValue(name);
}else{
return null
}
}
//获取成分相对于这一个页面包车型大巴x和y坐标。
function pageX(elem){
return
elem.offsetParent?(elem.offsetLeft+pageX(elem.offsetParent)):elem.offsetLeft;
}
function pageY(elem){
return
elem.offsetParent?(elem.offsetTop+pageY(elem.offsetParent)):elem.offsetTop;
}
//获取成分相对于父成分的x和y坐标。
function parentX(elem){
return
elem.parentNode==elem.offsetParent?elem.offsetLeft:pageX(elem)-pageX(elem.parentNode);
}
function parentY(elem){
return
elem.parentNode==elem.offsetParent?elem.offsetTop:pageY(elem)-pageY(elem.parentNode);
}
//获取使用css定位的成分的x和y坐标。
function posX(elem){
return parseInt(getStyle(elem,”left”));
}
function posY(elem){
return parseInt(getStyle(elem,”top”));
}
//设置成分地方。
function setX(elem,pos){
elem.style.left=pos+”px”;
}
function setY(elem,pos){
elem.style.top=pos+”px”;
}
//增日成分X和y坐标。
function addX(elem,pos){
set(elem,(posX(elem)+pos));
}
function addY(elem,pos){
set(elem,(posY(elem)+pos));
}
//获取成分运用css调整大小的可观和增幅
function getHeight(elem){
return parseInt(getStyle(elem,”height”));
}
function getWidth(elem){
return parseInt(getStyle(elem,”width”));
}
//获取成分恐怕,完整的高度和幅度
function getFullHeight(elem){
if(getStyle(elem,”display”)!=”none”){
return getHeight(elem)||elem.offsetHeight;
}else{
var
old=resetCss(elem,{display:”block”,visibility:”hidden”,position:”absolute”});
var h=elem.clientHeight||getHeight(elem);
restoreCss(elem,old);
return h;
}
}
function getFullWidth(elem){
if(getStyle(elem,”display”)!=”none”){
return getWidth(elem)||elem.offsetWidth;
}else{
var
old=resetCss(elem,{display:”block”,visibility:”hidden”,position:”absolute”});
var w=elem.clientWidth||getWidth(elem);
restoreCss(elem,old);
return w;
}
}
//设置css,并保留旧的css
function resetCss(elem,prop){
var old={};
for(var i in prop){
old[i]=elem.style[i];
elem.style[i]=prop[i];
}
return old;
}
function restoreCss(elem,prop){
for(var i in prop){
elem.style[i]=prop[i];
}
}
//显示和隐身
function show(elem){
elem.style.display=elem.$oldDisplay||” “;
}
function hide(elem){
var curDisplay=getStyle(elem,”display”);
if(curDisplay!=”none”){
elem.$oldDisplay=curDisplay;
elem.style.display=”none”;
}
}
//设置反射率
function setOpacity(elem,num){
if(elem.filters){
elem.style.filter=”alpha(opacity=”+num+”)”;
}else{
elem.style.opacity=num/100;
}
}
//滑动
function slideDown(elem){
var h=getFullHeight(elem);
elem.style.height=”0px”;
show(elem);
for(var i=0;i<=100;i+=5){
new function(){
var pos=i;
setTimeout(function(){elem.style.height=(pos/100*h)+”px”;},(pos*10));
}
}
}
//渐变
function fadeIn(elem){
show(elem);
setOpacity(elem,0);
for(var i=0;i<=100;i+=5){
new function(){
var pos=i;
setTimeout(function(){setOpacity(elem,pos);},(pos+1)*10);
}
}
}
//获取鼠标光标相对于整个页面包车型大巴职责。
function getX(e){
e=e||window.event;
return e.pageX||e.clientX+document.body.scrollLeft;
}
function getY(e){
e=e||window.event;
return e.pageY||e.clientY+document.body.scrollTop;
}
//获取鼠标光标相对于近年来因素的岗位。
function getElementX(e){
return (e&&e.layerX)||window.event.offsetX;
}
function getElementY(e){
return (e&&e.layerY)||window.event.offsetY;
}
//获取页面包车型地铁惊人和宽窄
function getPageHeight(){
var de=document.documentElement;
return document.body.scrollHeight||(de&&de.scrollHeight);
}
function getPageWidth(){
var de=document.documentElement;
return document.body.scrollWidth||(de&&de.scrollWidth);
}
//获取滚动条的职务。
function scrollX(){
var de=document.documentElement;
return
self.pageXOffset||(de&&de.scrollLeft)||document.body.scrollLeft;
}
function scrollY(){
var de=document.documentElement;
return self.pageYOffset||(de&&de.scrollTop)||document.body.scrollTop;
}
//获取视口的莫斯中国科学技术大学学和宽窄。
function windowHeight() {
var de = document.documentElement;
return self.innerHeight||(de &&
de.offsetHeight)||document.body.offsetHeight;
}
function windowWidth() {
var de = document.documentElement;
return self.innerWidth||( de && de.offsetWidth
)||document.body.offsetWidth;
}

2、怎么着赢妥善前浏览器帮忙的transform宽容写法

transform是css3的属性,当我们应用它时就不得不面前蒙受包容性的难点。区别版本浏览器的相称写法大约有如下三种:

['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform']

所以大家须要看清当前浏览器情况辅助的transform属性是哪类,方法如下:

JavaScript

// 获取当前浏览器帮助的transform宽容写法 function getTransform() { var
transform = ”, divStyle = document.createElement(‘div’).style, //
恐怕涉嫌到的两种宽容性写法,通过巡回搜索浏览器识别的那么些 transformArr
= [‘transform’, ‘webkitTransform’, ‘MozTransform’, ‘msTransform’,
‘OTransform’], i = 0, len = transformArr.length; for(; i < len; i++)
{ if(transformArr[i] in divStyle) { // 找到之后立刻回去,甘休函数
return transform = transformArr[i]; } } //
若无找到,就径直再次来到空字符串 return transform; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 获取当前浏览器支持的transform兼容写法
function getTransform() {
    var transform = ”,
        divStyle = document.createElement(‘div’).style,
        // 可能涉及到的几种兼容性写法,通过循环找出浏览器识别的那一个
        transformArr = [‘transform’, ‘webkitTransform’, ‘MozTransform’, ‘msTransform’, ‘OTransform’],
 
        i = 0,
        len = transformArr.length;
 
    for(; i < len; i++)  {
        if(transformArr[i] in divStyle) {
            // 找到之后立即返回,结束函数
            return transform = transformArr[i];
        }
    }
 
    // 如果没有找到,就直接返回空字符串
    return transform;
}

该方法用于获取浏览器支持的transform属性。假诺回到的为空字符串,则意味近来浏览器并不援助transform,那一年我们就要求选择left,top值来改换元素的职位。倘若援救,就更改transform的值。

您或者感兴趣的篇章:

3、 怎么着获得成分的早先地点

小编们第一须求获得到对象成分的启幕地方,因而这里大家须求贰个特意用来获得成分样式的效能函数。

但是获取成分样式在IE浏览器与别的浏览器有一对见仁见智,因而大家须求三个包容性的写法。

JavaScript

function getStyle(elem, property) { //
ie通过currentStyle来赢得成分的样式,其余浏览器通过getComputedStyle来获取
return document.defaultView.getComputedStyle ?
document.defaultView.getComputedStyle(elem, false)[property] :
elem.currentStyle[property]; }

1
2
3
4
function getStyle(elem, property) {
    // ie通过currentStyle来获取元素的样式,其他浏览器通过getComputedStyle来获取
    return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property];
}

有了那几个艺术之后,就足以开首起首写获取目的成分伊始地方的方式了。

JavaScript

function getTargetPos(elem) { var pos = {x: 0, y: 0}; var transform =
getTransform(); if(transform) { var transformValue = getStyle(elem,
transform); if(transformValue == ‘none’) { elem.style[transform] =
‘translate(0, 0)’; return pos; } else { var temp =
transformValue.match(/-?\d+/g); return pos = { x:
parseInt(temp[4].trim()), y: parseInt(temp[5].trim()) } } } else {
if(getStyle(elem, ‘position’) == ‘static’) { elem.style.position =
‘relative’; return pos; } else { var x = parseInt(getStyle(elem, ‘left’)
? getStyle(elem, ‘left’) : 0); var y = parseInt(getStyle(elem, ‘top’) ?
getStyle(elem, ‘top’) : 0); return pos = { x: x, y: y } } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function getTargetPos(elem) {
    var pos = {x: 0, y: 0};
    var transform = getTransform();
    if(transform) {
        var transformValue = getStyle(elem, transform);
        if(transformValue == ‘none’) {
            elem.style[transform] = ‘translate(0, 0)’;
            return pos;
        } else {
            var temp = transformValue.match(/-?\d+/g);
            return pos = {
                x: parseInt(temp[4].trim()),
                y: parseInt(temp[5].trim())
            }
        }
    } else {
        if(getStyle(elem, ‘position’) == ‘static’) {
            elem.style.position = ‘relative’;
            return pos;
        } else {
            var x = parseInt(getStyle(elem, ‘left’) ? getStyle(elem, ‘left’) : 0);
            var y = parseInt(getStyle(elem, ‘top’) ? getStyle(elem, ‘top’) : 0);
            return pos = {
                x: x,
                y: y
            }
        }
    }
}

在拖拽进程中,大家必要不停的设置目的成分的新职务,那样它才会活动起来,由此大家必要一个装置目的成分地点的章程。

JavaScript

// pos = { x: 200, y: 100 } function setTargetPos(elem, pos) { var
transform = getTransform(); if(transform) { elem.style[transform] =
‘translate(‘+ pos.x +’px, ‘+ pos.y +’px)’; } else { elem.style.left =
pos.x + ‘px’; elem.style.top = pos.y + ‘px’; } return elem; }

1
2
3
4
5
6
7
8
9
10
11
// pos = { x: 200, y: 100 }
function setTargetPos(elem, pos) {
    var transform = getTransform();
    if(transform) {
        elem.style[transform] = ‘translate(‘+ pos.x +’px, ‘+ pos.y +’px)’;
    } else {
        elem.style.left = pos.x + ‘px’;
        elem.style.top = pos.y + ‘px’;
    }
    return elem;
}
5、大家要求用到什么样事件?

在pc上的浏览器中,结合mousedown、mousemove、mouseup那七个事件能够扶持大家落实拖拽。

而在移动端,分别与之对应的则是touchstart、touchmove、touchend

当大家将成分绑定这么些事件时,有贰个事件目的将会作为参数字传送递给回调函数,通过事件指标,我们得以获取到近期鼠标的精确地点,鼠标地方音讯是实现拖拽的重要。

事件目的非常器重,个中包蕴了充足多的平价的音信,这里作者就不扩展了,大家能够在函数准将事件目的打字与印刷出来查看里面包车型客车现实性质,这么些方法对于记不清事件目的首要性质的童鞋特别实用。

6、拖拽的规律

当事件触发时,大家得以经过事件目的得到到鼠标的精切地方。这是促成拖拽的机要。当鼠标按下(mousedown触发)时,大家供给记住鼠标的上马地方与对象成分的启幕地方,大家的对象正是贯彻当鼠标移动时,目的成分也随着移动,依据原理我们得以吸收如下事关:

挪动后的鼠标地方 – 鼠标初始地方 = 移动后的目的成分地点 –
指标成分的初始地方

1
移动后的鼠标位置 – 鼠标初始位置 = 移动后的目标元素位置 – 目标元素的初始位置

假使鼠标地方的差值大家用dis来表示,那么目的成分的地方就分外:

移步后指标成分的任务 = dis + 指标成分的发端地点

1
移动后目标元素的位置 = dis + 目标元素的初始位置

通过事件目的,大家能够正确的驾驭鼠标的此时此刻职责,由此当鼠标拖动(mousemove)时,大家能够不停的测算出鼠标移动的差值,以此来求出指标元素的日前岗位。这一个历程,就完结了拖拽。

而在鼠标松开(mouseup)甘休拖拽时,大家须求管理局地收场职业。详细情形见代码。

7、 小编又来推荐思维导图帮助写代码了

经常有新人朋友跑来问小编,若是逻辑思维技术不强,能还是无法写代码做前端。作者的答案是:能。因为依赖思维导图,能够很自在的弥补逻辑的短板。並且比在本人头脑中脑补逻辑更是清晰明了,不易出错。

上面第六点我介绍了规律,因而咋做就体现不是那么难了,而具体的步调,则在底下的思想导图中明显给出,大家只供给根据这一个手续来写代码就能够,试试看,一定很自在。

银河官方网站 2

利用思维导图清晰的抒发出整个拖拽进程大家须要干的事体

8、代码完结

part1、希图专门的工作

JavaScript

// 获取指标成分对象 var oElem = document.getElementById(‘target’); //
证明2个变量用来保存鼠标开头地点的x,y坐标 var startX = 0; var startY =
0; // 表明2个变量用来保存指标成分初步地方的x,y坐标 var sourceX = 0; var
sourceY = 0;

1
2
3
4
5
6
7
8
9
10
// 获取目标元素对象
var oElem = document.getElementById(‘target’);
 
// 声明2个变量用来保存鼠标初始位置的x,y坐标
var startX = 0;
var startY = 0;
 
// 声明2个变量用来保存目标元素初始位置的x,y坐标
var sourceX = 0;
var sourceY = 0;

part2、功能函数

因为事先已经贴过代码,就不再另行

JavaScript

// 获取当前浏览器帮助的transform宽容写法 function getTransform() {} //
获取成分属性 function getStyle(elem, property) {} // 获取成分的上马位置function getTargetPos(elem) {} // 设置元素的启幕地点 function
setTargetPos(elem, potions) {}

1
2
3
4
5
6
7
8
9
10
11
// 获取当前浏览器支持的transform兼容写法
function getTransform() {}
 
// 获取元素属性
function getStyle(elem, property) {}
 
// 获取元素的初始位置
function getTargetPos(elem) {}
 
// 设置元素的初始位置
function setTargetPos(elem, potions) {}

part3、评释多个事件的回调函数

那四个点子正是促成拖拽的中坚所在,作者将严酷遵照地点思维导图中的步骤来产生大家的代码。

JavaScript

// 绑定在mousedown上的回调,event为流传的平地风波指标 function start(event)
{ // 获取鼠标伊始地方 startX = event.pageX; startY = event.pageY; //
获取元素开始地方 var pos = getTargetPos(oElem); sourceX = pos.x; sourceY
= pos.y; // 绑定 document.addEventListener(‘mousemove’, move, false);
document.addEventListener(‘mouseup’, end, false); } function move(event)
{ // 获取鼠标当前岗位 var currentX = event.pageX; var currentY =
event.pageY; // 总括差值 var distanceX = currentX – startX; var
distanceY = currentY – startY; // 总计并安装成分当前地点setTargetPos(oElem, { x: (sourceX + distanceX).toFixed(), y: (sourceY +
distanceY).toFixed() }) } function end(event) {
document.remove伊夫ntListener(‘mousemove’, move);
document.remove伊夫ntListener(‘mouseup’, end); // do other things }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 绑定在mousedown上的回调,event为传入的事件对象
function start(event) {
    // 获取鼠标初始位置
    startX = event.pageX;
    startY = event.pageY;
 
    // 获取元素初始位置
    var pos = getTargetPos(oElem);
 
    sourceX = pos.x;
    sourceY = pos.y;
 
    // 绑定
    document.addEventListener(‘mousemove’, move, false);
    document.addEventListener(‘mouseup’, end, false);
}
 
function move(event) {
    // 获取鼠标当前位置
    var currentX = event.pageX;
    var currentY = event.pageY;
 
    // 计算差值
    var distanceX = currentX – startX;
    var distanceY = currentY – startY;
 
    // 计算并设置元素当前位置
    setTargetPos(oElem, {
        x: (sourceX + distanceX).toFixed(),
        y: (sourceY + distanceY).toFixed()
    })
}
 
function end(event) {
    document.removeEventListener(‘mousemove’, move);
    document.removeEventListener(‘mouseup’, end);
    // do other things
}

OK,七个简约的拖拽,就这么欢跃的完结了。点击下边包车型大巴链接,能够在线查看该例子的demo。

运用原生js完毕拖拽

9、封装拖拽对象

在日前一章作者给我们大饱眼福了面向对象怎么着落实,基于那多少个基础知识,我们来将方面达成的拖拽封装为三个拖拽对象。大家的靶子是,只要我们声多美滋(Dumex)(Nutrilon)个拖拽实例,那么传入的对象成分将电动具备能够被拖拽的功力。

在其实付出中,二个对象我们平时会单独放在一个js文件中,这几个js文件将单身作为三个模块,利用种种模块的点子社团起来使用。当然这里没有复杂的模块交互,因为这么些例子,我们只供给四个模块就可以。

为了幸免变量污染,大家需求将模块放置于二个函数自试行办法模拟的块级功效域中。

JavaScript

; (function() { … })();

1
2
3
4
;
(function() {
    …
})();

在平凡的模块协会中,我们只是独自的将大多js文件降低成为七个js文件,因而这里的率先个分行则是为着防备上三个模块的末尾不用分号导致报错。至关重要。当然在经过require或许ES6模块等格局就不会冒出这么的处境。

大家精通,在包装贰个指标的时候,大家得以将品质与办法放置于构造函数只怕原型中,而在加码了自进行函数之后,我们又足以将质量和办法防止与模块的当中成效域。那是闭包的学问。

那么大家面对的挑衅就在于,怎么着客观的管理属性与方法的岗位。

自然,每一种对象的情景都不平等,不能够同等对待,大家供给显明的知情那二种职位的特色能力做出最相符的主宰。

对此艺术的论断比较简单。

因为在构造函数中的方法总会在声多美滋个新的实例时被再度创制,因而大家表明的艺术都尽量防止出现在构造函数中。

而借让你的法子中须求用到构造函数中的变量,可能想要公开,那就必要放在原型中。

假若艺术必要个人不被外界访问,那么就停放在模块成效域中。

对此属性放置于怎么着岗位有个别时候很难做出准确的剖断,因而小编很难交付多少个标准的概念告诉您怎么性质应当要放在什么岗位,那亟需在实质上支付中穿梭的下结论经验。然而总的来讲,依然要组成这两个岗位的表征来做出最合适的论断。

要是属性值只可以被实例单独具有,举例person对象的name,只好属于某叁个person实例,又举个例子此处拖拽对象中,某叁个要素的开端地方,也仅仅只是这几个因素的当前任务,那么些个性,则符合放在构造函数中。

而一旦多少个个性仅仅供内部方法访问,那天性情就切合放在模块作用域中。

有关面向对象,上边的几点思虑自身认为是这篇小说最值得认真思索的特出。要是在封装时未有思想清楚,比十分的大概会碰到不菲您出人意料的bug,所以建议我们结合本人的支付经历,多多思考,总括出自个儿的见识。

基于这个思虑,我们能够自身尝尝封装一下。然后与本身的做一些看待,看看大家的主张有怎样两样,在底下例子的注明中,作者将团结的主见表明出来。

点击查看已经封装好的demo

js 源码

JavaScript

; (function() { // 那是三个民用属性,无需被实例访谈 var transform =
getTransform(); function Drag(selector) { //
放在构造函数中的属性,都以属于每四个实例单独具有 this.elem = typeof
selector == ‘Object’ ? selector : document.getElementById(selector);
this.startX = 0; this.startY = 0; this.sourceX = 0; this.sourceY = 0;
this.init(); } // 原型 Drag.prototype = { constructor: Drag, init:
function() { // 伊始时供给做些什么业务 this.setDrag(); }, //
稍作改变,仅用于获取当前因素的天性,类似于getName getStyle:
function(property) { return document.defaultView.getComputedStyle ?
document.defaultView.getComputedStyle(this.elem, false)[property] :
this.elem.currentStyle[property]; }, //
用来博取当前因素的职分消息,注意与前边的分化之处 getPosition: function()
{ var pos = {x: 0, y: 0}; if(transform) { var transformValue =
this.getStyle(transform); if(transformValue == ‘none’) {
this.elem.style[transform] = ‘translate(0, 0)’; } else { var temp =
transformValue.match(/-?\d+/g); pos = { x: parseInt(temp[4].trim()),
y: parseInt(temp[5].trim()) } } } else { if(this.getStyle(‘position’)
== ‘static’) { this.elem.style.position = ‘relative’; } else { pos = {
x: parseInt(this.getStyle(‘left’) ? this.getStyle(‘left’) : 0), y:
parseInt(this.getStyle(‘top’) ? this.getStyle(‘top’) : 0) } } } return
pos; }, // 用来安装当前因素的岗位 setPostion: function(pos) {
if(transform) { this.elem.style[transform] = ‘translate(‘+ pos.x +’px,
‘+ pos.y +’px)’; } else { this.elem.style.left = pos.x + ‘px’;
this.elem.style.top = pos.y + ‘px’; } }, // 该格局用来绑定事件 setDrag:
function() { var self = this; this.elem.addEventListener(‘mousedown’,
start, false); function start(event) { self.startX = event.pageX;
self.startY = event.pageY; var pos = self.getPosition(); self.sourceX =
pos.x; self.sourceY = pos.y; document.addEventListener(‘mousemove’,
move, false); document.add伊夫ntListener(‘mouseup’, end, false); }
function move(event) { var currentX = event.pageX; var currentY =
event.pageY; var distanceX = currentX – self.startX; var distanceY =
currentY – self.startY; self.setPostion({ x: (self.sourceX +
distanceX).toFixed(), y: (self.sourceY + distanceY).toFixed() }) }
function end(event) { document.removeEventListener(‘mousemove’, move);
document.remove伊夫ntListener(‘mouseup’, end); // do other things } } }
// 私有方法,仅仅用来得到transform的合营写法 function getTransform() {
var transform = ”, divStyle = document.createElement(‘div’).style,
transformArr = [‘transform’, ‘webkitTransform’, ‘MozTransform’,
‘msTransform’, ‘OTransform’], i = 0, len = transformArr.length; for(; i
< len; i++) { if(transformArr[i] in divStyle) { return transform =
transformArr[i]; } } return transform; } // 一种对外揭露的格局window.Drag = Drag; })(); // 使用:注脚2个拖拽实例 new Drag(‘target’);
new Drag(‘target2’);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
;
(function() {
    // 这是一个私有属性,不需要被实例访问
    var transform = getTransform();
 
    function Drag(selector) {
        // 放在构造函数中的属性,都是属于每一个实例单独拥有
        this.elem = typeof selector == ‘Object’ ? selector : document.getElementById(selector);
        this.startX = 0;
        this.startY = 0;
        this.sourceX = 0;
        this.sourceY = 0;
 
        this.init();
    }
 
 
    // 原型
    Drag.prototype = {
        constructor: Drag,
 
        init: function() {
            // 初始时需要做些什么事情
            this.setDrag();
        },
 
        // 稍作改造,仅用于获取当前元素的属性,类似于getName
        getStyle: function(property) {
            return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property];
        },
 
        // 用来获取当前元素的位置信息,注意与之前的不同之处
        getPosition: function() {
            var pos = {x: 0, y: 0};
            if(transform) {
                var transformValue = this.getStyle(transform);
                if(transformValue == ‘none’) {
                    this.elem.style[transform] = ‘translate(0, 0)’;
                } else {
                    var temp = transformValue.match(/-?\d+/g);
                    pos = {
                        x: parseInt(temp[4].trim()),
                        y: parseInt(temp[5].trim())
                    }
                }
            } else {
                if(this.getStyle(‘position’) == ‘static’) {
                    this.elem.style.position = ‘relative’;
                } else {
                    pos = {
                        x: parseInt(this.getStyle(‘left’) ? this.getStyle(‘left’) : 0),
                        y: parseInt(this.getStyle(‘top’) ? this.getStyle(‘top’) : 0)
                    }
                }
            }
 
            return pos;
        },
 
        // 用来设置当前元素的位置
        setPostion: function(pos) {
            if(transform) {
                this.elem.style[transform] = ‘translate(‘+ pos.x +’px, ‘+ pos.y +’px)’;
            } else {
                this.elem.style.left = pos.x + ‘px’;
                this.elem.style.top = pos.y + ‘px’;
            }
        },
 
        // 该方法用来绑定事件
        setDrag: function() {
            var self = this;
            this.elem.addEventListener(‘mousedown’, start, false);
            function start(event) {
                self.startX = event.pageX;
                self.startY = event.pageY;
 
                var pos = self.getPosition();
 
                self.sourceX = pos.x;
                self.sourceY = pos.y;
 
                document.addEventListener(‘mousemove’, move, false);
                document.addEventListener(‘mouseup’, end, false);
            }
 
            function move(event) {
                var currentX = event.pageX;
                var currentY = event.pageY;
 
                var distanceX = currentX – self.startX;
                var distanceY = currentY – self.startY;
 
                self.setPostion({
                    x: (self.sourceX + distanceX).toFixed(),
                    y: (self.sourceY + distanceY).toFixed()
                })
            }
 
            function end(event) {
                document.removeEventListener(‘mousemove’, move);
                document.removeEventListener(‘mouseup’, end);
                // do other things
            }
        }
    }
 
    // 私有方法,仅仅用来获取transform的兼容写法
    function getTransform() {
        var transform = ”,
            divStyle = document.createElement(‘div’).style,
            transformArr = [‘transform’, ‘webkitTransform’, ‘MozTransform’, ‘msTransform’, ‘OTransform’],
 
            i = 0,
            len = transformArr.length;
 
        for(; i < len; i++)  {
            if(transformArr[i] in divStyle) {
                return transform = transformArr[i];
            }
        }
 
        return transform;
    }
 
    // 一种对外暴露的方式
    window.Drag = Drag;
})();
 
// 使用:声明2个拖拽实例
new Drag(‘target’);
new Drag(‘target2’);

如此一个拖拽对象就封装完成了。

建议大家依照作者提供的沉思方法,多多尝试封装一些零部件。比如封装二个弹窗,封装一个循环轮播等。练得多了,面向对象就不再是主题素材了。这种思维情势,在现在其余时候都是能够运用的。

下一章解析jQuery对象的兑现,与什么将大家这里封装的拖拽对象增添为jQuery插件。

2 赞 1 收藏
评论

银河官方网站 3

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图