面向对象思想-封装拖拽对象
来源:互联网 发布:乐高ev3编程视频教程 编辑:程序博客网 时间:2024/04/30 02:57
1、我们常常会通过修改元素的top,left,translate来其的位置发生改变。修改元素的left,top值,但会引起页面重绘,而transform不会,所以要优先使用transform。
2、如何获取当前浏览器支持的transform兼容写法
3、获取元素的初始位置:
4、需要绑定的事件:mousedown,mousemove,mouseup
而在移动端,分别与之对应的则是touchstart、touchmove、touchend。
5、原理
当事件触发时,我们可以通过事件对象获取到鼠标的精切位置。这是实现拖拽的关键。当鼠标按下(mousedown触发)时,我们需要记住鼠标的初始位置与目标元素的初始位置,我们的目标就是实现当鼠标移动时,目标元素也跟着移动,根据常理我们可以得出如下关系:
移动后的鼠标位置 - 鼠标初始位置 = 移动后的目标元素位置 - 目标元素的初始位置
如果鼠标位置的差值我们用dis来表示,那么目标元素的位置就等于:
移动后目标元素的位置 = dis + 目标元素的初始位置通过事件对象,我们可以精确的知道鼠标的当前位置,因此当鼠标拖动(mousemove)时,我们可以不停的计算出鼠标移动的差值,以此来求出目标元素的当前位置。这个过程,就实现了拖拽。
而在鼠标松开(mouseup)结束拖拽时,我们需要处理一些收尾工作。
6、封装原则
如何合理的处理属性与方法的位置。
构造函数中: 属性与方法为当前实例单独拥有,只能被当前实例访问,并且每声明一个实例,其中的方法都会被重新创建一次。
原型中: 属性与方法为所有实例共同拥有,可以被所有实例访问,新声明实例不会重复创建方法。
模块作用域中:属性和方法不能被任何实例访问,但是能被内部方法访问,新声明的实例,不会重复创建相同的方法。
对于方法的判断比较简单。
因为在构造函数中的方法总会在声明一个新的实例时被重复创建,因此我们声明的方法都尽量避免出现在构造函数中。
而如果你的方法中需要用到构造函数中的变量,或者想要公开,那就需要放在原型中。
如果方法需要私有不被外界访问,那么就放置在模块作用域中。
对于属性的判断
对于属性放置于什么位置需要在实际开发中不断的总结经验。
如果属性值只能被实例单独拥有,比如person对象的name,只能属于某一个person实例,又比如这里拖拽对象中,某一个元素的初始位置,也仅仅只是这个元素的当前位置,这个属性,则适合放在构造函数中。
而如果一个属性仅仅供内部方法访问,这个属性就适合放在模块作用域中。
模块封装代码:
; //文件合并时,防止前一个文件末尾没加分号 (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(); }, getStyle: function(property) { return window.getComputedStyle ? window.getComputedStyle(this.elem, null).getPropertyValue(property) : this.currentStyle.getAttribute(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; }, // 用来设置当前元素的位置 setPosition: 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 curX = event.pageX; var curY = event.pageY; // 计算差值 var disX = curX - self.startX; var disY = curY - self.startY; self.setPosition({ x: (self.sourceX + disX).toFixed(), y: (self.sourceY + disY).toFixed() }); } function end(event) { document.removeEventListener('mousemove', move); document.removeEventListener('mouseup', end); //do other things } } } //私有方法 function getTransform() { var transform = '', divStyle = document.createElement('div').style, transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform']; //通过循环找出浏览器识别的那个,in操作符用于判断是否识别 for (var i = 0, len = transformArr.length; i < len; i++) { if (transformArr[i] in divStyle) { return transform = transformArr[i]; } } return transform; } window.Drag = Drag; })(); new Drag('target'); new Drag('target2');
html:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title> <style> * { padding: 0; margin: 0; } #target, #target2 { width: 50px; height: 50px; background-color: orange; cursor: move; } #target2 { background-color: red; } </style></head><body> <div style="height:1000px">hha</div> <div id="target"></div> <div id="target2"></div> </body></html>
jquery实例方法扩展:
// 通过扩展方法将拖拽扩展为jQuery的一个实例方法(function ($) { $.fn.extend({ becomeDrag: function () { new Drag(this[0]); return this; // 注意:为了保证jQuery所有的方法都能够链式访问,每一个方法的最后都需要返回this,即返回jQuery实例 } })})(jQuery);
参考链接:http://www.jianshu.com/p/b3dee0e84454
http://www.jianshu.com/p/3f97570d22b4
- 面向对象思想-封装拖拽对象
- 面向对象编程思想---封装
- Java面向对象思想之一:封装
- iOS 面向对象思想之封装
- 跳出面向对象思想(三) 封装
- 封装,面向对象设计编程思想
- 面向对象封装插件思想 jquery
- js面向对象思想封装拖拽功能,兼容pc和移动端
- 对象封装思想
- Java经典封装JDBC模板(充分体现面向对象思想)
- java面向对象基本思想--封装继承多态
- Java经典封装JDBC模板(充分体现面向对象思想)
- java编程面向对象思想:封装,继承,多态
- Java经典封装JDBC模板(充分体现面向对象思想)
- Java经典封装JDBC模板(充分体现面向对象思想)
- a.面向对象编程思想(封装继承多态接口)
- Java经典封装JDBC模板(充分体现面向对象思想)
- 重温面向对象的思想OOP——封装
- poj 2065 SETI(高斯消元)
- 循环队列
- 聚类方法之k-mean算法
- hpuoj【1410】QAQ & 火星情报局【数学】
- Django编写中间件实现url自定义过滤
- 面向对象思想-封装拖拽对象
- PHP与Shell交互
- 前端入门方法
- curl详细用法
- 《numpy学习指南》学习笔记——常用函数
- 数据库优化
- 虚方法与抽象方法有什么区别
- 动态sql(8)
- C# Post请求json数据