新闻资讯

当前位置:新萄京娱乐场手机版 > 新闻资讯 > 原文出处

原文出处

来源:http://www.chrisproduction.com 作者:新萄京娱乐场手机版 时间:2019-10-14 02:15

前端基础进阶(10):面向对象实战之封装拖拽对象

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

原稿出处: 波同学   

图片 1

终于

方今几篇小说,笔者跟我们大快朵颐了JavaScript的部分基础知识,那篇小说,将会步入第一个实战环节:利用前边几章的所关联到的学识,封装三个拖拽对象。为了可以帮助我们精晓越多的法门与举行自己检查自纠,小编会使用三种差异的章程来促成拖拽。

  • 不封装对象直接促成;
  • 采取原生JavaScript封装拖拽对象;
  • 经过扩展jQuery来落到实处拖拽对象。

本文的例证会停放于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的值。

你只怕感兴趣的稿子:

  • jQuery常用知识点计算以至平时打包常用函数
  • 传说jquery封装的四个js分页
  • jquery数组封装使用办法分享(jquery数组遍历)
  • Jquery封装tab自动切换效果的求实贯彻
  • jquery自动将form表单封装成json的现实性实现
  • jquery datatable后台封装数据示例代码
  • jQuery主题图切换特效插件封装实例
  • 基于jquery的用dl模拟完成可自定义样式的SELECT下拉列表(已打包)
  • jQueryUI的Dialog的轻易包装
  • 【优异源码收藏】基于jQuery的品类常见函数封装会集
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那多少个事件能够扶植大家落到实处拖拽。

  • 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.add伊芙ntListener('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.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、封装拖拽对象

在眼下一章小编给我们大快朵颐了面向对象怎么着落实,基于那个基础知识,大家来将地点完毕的拖拽封装为四个拖拽对象。大家的目标是,只要大家声澳优个拖拽实例,那么传入的靶子成分将机关具备能够被拖拽的意义。

在实际上开辟中,二个指标大家平时会单独放在多个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.add伊芙ntListener('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.add伊芙ntListener('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.remove伊芙ntListener('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');

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

本文由新萄京娱乐场手机版发布于新闻资讯,转载请注明出处:原文出处

关键词: