├── .tags
├── .tags1
├── README.md
├── drag-by-javascript
├── app.js
└── index.html
├── drag-by-jquery-plugin
├── app.js
├── index.html
└── jquery-2.0.3.js
├── drag-by-jquery
├── app.js
├── index.html
└── jquery-2.0.3.js
├── drag-by-jsoop
├── app.js
└── index.html
└── drag-by-react
├── app.js
└── index.html
/.tags:
--------------------------------------------------------------------------------
1 | html /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^$/;" function line:2
2 | head /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^
$/;" function line:4
3 | meta /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^ $/;" function line:5
4 | meta /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^ $/;" function line:6
5 | title /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^ 使用JavaScript实现拖拽<\/title>$/;" function line:7
6 | style /Users/yangbo/develop/me/drag-by-many-ways/drag-by-javascript/index.html /^
25 |
26 |
27 |
28 | JS
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/drag-by-jquery-plugin/app.js:
--------------------------------------------------------------------------------
1 | ;
2 | (function () {
3 | var isMobile = 'ontouchstart' in document;
4 | var _moveunderway = null;
5 | var _moveend = null;
6 |
7 | // 声明构造函数
8 | function Drag (selector) {
9 |
10 | this.oTarget = null;
11 | if (typeof selector == 'object') {
12 | this.oTarget = selector;
13 | } else {
14 | this.oTarget = document.querySelector(selector);
15 | }
16 |
17 | this.startX = 0;
18 | this.startY = 0;
19 | this.targetSourceX = 0;
20 | this.targetSourceY = 0;
21 |
22 | if (isMobile) {
23 | this.oTarget.addEventListener('touchstart', this.movestart.bind(this), false);
24 | this.oTarget.addEventListener('touchmove', this.moveunderway.bind(this), false);
25 | this.oTarget.addEventListener('touchend', this.moveend.bind(this), false);
26 | } else {
27 | this.oTarget.addEventListener('mousedown', this.movestart.bind(this), false);
28 | }
29 | }
30 |
31 | // 添加原型方法
32 | Drag.prototype.movestart = function (event) {
33 | this.startX = isMobile ? event.changedTouches[0].pageX : event.pageX;
34 | this.startY = isMobile ? event.changedTouches[0].pageY : event.pageY;
35 |
36 | var styles = document.defaultView.getComputedStyle(this.oTarget, false);
37 | this.targetSourceX = parseInt(styles.left);
38 | this.targetSourceY = parseInt(styles.top);
39 |
40 | if (!isMobile) {
41 | _moveunderway = this.moveunderway.bind(this);
42 | _moveend = this.moveend.bind(this);
43 | document.addEventListener('mousemove', _moveunderway, false);
44 | document.addEventListener('mouseup', _moveend, false);
45 | }
46 | }
47 |
48 | Drag.prototype.moveunderway = function (event) {
49 | var currentX = isMobile ? event.changedTouches[0].pageX : event.pageX;
50 | var currentY = isMobile ? event.changedTouches[0].pageY : event.pageY;
51 | var distanceX = currentX - this.startX;
52 | var distanceY = currentY - this.startY;
53 | var targetCurrentX = this.targetSourceX + distanceX;
54 | var targetCurrentY = this.targetSourceY + distanceY;
55 | this.oTarget.style.left = targetCurrentX + 'px';
56 | this.oTarget.style.top = targetCurrentY + 'px';
57 | }
58 |
59 | Drag.prototype.moveend = function (event) {
60 | if (!isMobile) {
61 | document.removeEventListener('mousemove', _moveunderway);
62 | document.removeEventListener('mouseup', _moveend);
63 | }
64 | }
65 |
66 | window.Drag = Drag;
67 | })();
68 |
69 |
70 | (function ($) {
71 | $.fn.extend({
72 | becomeDrag: function () {
73 | new Drag(this[0]);
74 | return this;
75 | }
76 | })
77 | })(jQuery);
78 |
79 | $('#target').becomeDrag();
80 |
81 |
82 | $.fn.extend({
83 | add: function(a, b) {
84 | return a + b;
85 | }
86 | })
87 |
88 | $(document.body).add(10, 20);
89 |
--------------------------------------------------------------------------------
/drag-by-jquery-plugin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 拖拽
7 |
23 |
24 |
25 | JS
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/drag-by-jquery/app.js:
--------------------------------------------------------------------------------
1 | ;
2 | (function(ROOT) {
3 | var jQuery = function(selector) {
4 |
5 | // 在jQuery中直接返回new过的实例,这里的init是jQuery的真正构造函数
6 | return new jQuery.fn.init(selector)
7 | }
8 |
9 | jQuery.fn = jQuery.prototype = {
10 | constructor: jQuery,
11 |
12 | version: '1.0.0',
13 |
14 | init: function(selector) {
15 | // 在jquery中这里有一个复杂的判断,但是这里我做了简化
16 | var elem, selector;
17 | elem = document.querySelector(selector);
18 | this[0] = elem;
19 |
20 | // 在jquery中返回一个由所有原型属性方法组成的数组,我们这里简化,直接返回this即可
21 | // return jQuery.makeArray(selector, this);
22 | return this;
23 | },
24 |
25 | // 在原型上添加一堆方法
26 | toArray: function() {},
27 | get: function() {},
28 | each: function() {},
29 | ready: function() {},
30 | first: function() {},
31 | slice: function() {}
32 | // ... ...
33 | }
34 |
35 | jQuery.fn.init.prototype = jQuery.fn;
36 |
37 | // 实现jQuery的两种扩展方式
38 | jQuery.extend = jQuery.fn.extend = function(options) {
39 |
40 | // 在jquery源码中会根据参数不同进行很多判断,我们这里就直接走一种方式,所以就不用判断了
41 | var target = this;
42 | var copy;
43 |
44 | for(name in options) {
45 | copy = options[name];
46 | target[name] = copy;
47 | }
48 | return target;
49 | }
50 |
51 | // jQuery中利用上面实现的扩展机制,添加了许多方法,其中
52 |
53 | // 直接添加在构造函数上,被称为工具方法
54 | jQuery.extend({
55 | isFunction: function() {},
56 | type: function() {},
57 | parseHTML: function() {},
58 | parseJSON: function() {},
59 | ajax: function() {}
60 | // ...
61 | })
62 |
63 | // 添加到原型上
64 | jQuery.fn.extend({
65 | queue: function() {},
66 | promise: function() {},
67 | attr: function() {},
68 | prop: function() {},
69 | addClass: function() {},
70 | removeClass: function() {},
71 | val: function() {},
72 | css: function() {}
73 | // ...
74 | })
75 |
76 | // $符号的由来,实际上它就是jQuery,一个简化的写法,在这里我们还可以替换成其他可用字符
77 | ROOT.jQuery = ROOT.$ = jQuery;
78 |
79 | })(window);
80 |
--------------------------------------------------------------------------------
/drag-by-jquery/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 拖拽
7 |
23 |
24 |
25 | JS
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/drag-by-jsoop/app.js:
--------------------------------------------------------------------------------
1 | ;
2 | (function() {
3 | // 这是一个私有属性,不需要被实例访问
4 | var transform = getTransform();
5 |
6 | function Drag(selector) {
7 | // 放在构造函数中的属性,都是属于每一个实例单独拥有
8 | this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector);
9 | this.startX = 0;
10 | this.startY = 0;
11 | this.sourceX = 0;
12 | this.sourceY = 0;
13 |
14 | this.init();
15 | }
16 |
17 |
18 | // 原型
19 | Drag.prototype = {
20 | constructor: Drag,
21 |
22 | init: function() {
23 | // 初始时需要做些什么事情
24 | this.setDrag();
25 | },
26 |
27 | // 稍作改造,仅用于获取当前元素的属性,类似于getName
28 | getStyle: function(property) {
29 | return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property];
30 | },
31 |
32 | // 用来获取当前元素的位置信息,注意与之前的不同之处
33 | getPosition: function() {
34 | var pos = {x: 0, y: 0};
35 | if(transform) {
36 | var transformValue = this.getStyle(transform);
37 | if(transformValue == 'none') {
38 | this.elem.style[transform] = 'translate(0, 0)';
39 | } else {
40 | var temp = transformValue.match(/[0-9,\s\.]+/)[0].split(',');
41 | pos = {
42 | x: parseInt(temp[4].trim()),
43 | y: parseInt(temp[5].trim())
44 | }
45 | }
46 | } else {
47 | if(this.getStyle('position') == 'static') {
48 | this.elem.style.position = 'relative';
49 | } else {
50 | pos = {
51 | x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0),
52 | y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0)
53 | }
54 | }
55 | }
56 |
57 | return pos;
58 | },
59 |
60 | // 用来设置当前元素的位置
61 | setPostion: function(pos) {
62 | if(transform) {
63 | this.elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)';
64 | } else {
65 | this.elem.style.left = pos.x + 'px';
66 | this.elem.style.top = pos.y + 'px';
67 | }
68 | },
69 |
70 | // 该方法用来绑定事件
71 | setDrag: function() {
72 | var self = this;
73 | this.elem.addEventListener('mousedown', start, false);
74 | function start(event) {
75 | self.startX = event.pageX;
76 | self.startY = event.pageY;
77 |
78 | var pos = self.getPosition();
79 |
80 | self.sourceX = pos.x;
81 | self.sourceY = pos.y;
82 |
83 | document.addEventListener('mousemove', move, false);
84 | document.addEventListener('mouseup', end, false);
85 | }
86 |
87 | function move(event) {
88 | var currentX = event.pageX;
89 | var currentY = event.pageY;
90 |
91 | var distanceX = currentX - self.startX;
92 | var distanceY = currentY - self.startY;
93 |
94 | self.setPostion({
95 | x: (self.sourceX + distanceX).toFixed(),
96 | y: (self.sourceY + distanceY).toFixed()
97 | })
98 | }
99 |
100 | function end(event) {
101 | document.removeEventListener('mousemove', move);
102 | document.removeEventListener('mouseup', end);
103 | // do other things
104 | }
105 | }
106 | }
107 |
108 | // 私有方法,仅仅用来获取transform的兼容写法
109 | function getTransform() {
110 | var transform = '',
111 | divStyle = document.createElement('div').style,
112 | transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
113 |
114 | i = 0,
115 | len = transformArr.length;
116 |
117 | for(; i < len; i++) {
118 | if(transformArr[i] in divStyle) {
119 | return transform = transformArr[i];
120 | }
121 | }
122 |
123 | return transform;
124 | }
125 |
126 | // 一种对外暴露的方式
127 | window.Drag = Drag;
128 | })();
129 |
130 | // 使用:声明2个拖拽实例
131 | new Drag('target');
132 | new Drag('target2');
133 |
134 | (function ($) {
135 | $.fn.extend({
136 | becomeDrag: function () {
137 | new Drag(this[0]);
138 | return this;
139 | }
140 | })
141 | })(jQuery);
142 |
--------------------------------------------------------------------------------
/drag-by-jsoop/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 拖拽
7 |
37 |
38 |
39 | JS
40 | JS2
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/drag-by-react/app.js:
--------------------------------------------------------------------------------
1 | // 暂时先不管html5的拖拽事件
2 | var Drag = React.createClass({
3 | getInitialState: function () {
4 | return {
5 | startX: 0,
6 | startY: 0,
7 | targetSourceX: 0,
8 | targetSourceY: 0,
9 | targetCurrentX: 0,
10 | targetCurrentY: 0,
11 | isMobile: 'ontouchstart' in document
12 | }
13 | },
14 | movestart: function (e) {
15 | var startX = this.state.isMobile ? e.nativeEvent.changedTouches[0].pageX : e.nativeEvent.pageX;
16 | var startY = this.state.isMobile ? e.nativeEvent.changedTouches[0].pageY : e.nativeEvent.pageY;
17 | this.setState({
18 | startX: startX,
19 | startY: startY
20 | })
21 |
22 | var _this = this;
23 |
24 | if (!this.state.isMobile) {
25 | var oTarget = this.refs.target;
26 | document.addEventListener('mousemove', mousemove, false);
27 | document.addEventListener('mouseup', mouseup, false);
28 |
29 | function mousemove (e) {
30 | var currentX = e.pageX;
31 | var currentY = e.pageY;
32 | var distanceX = currentX - _this.state.startX;
33 | var distanceY = currentY - _this.state.startY;
34 |
35 | var targetCurrentX = _this.state.targetSourceX + distanceX;
36 | var targetCurrentY = _this.state.targetSourceY + distanceY;
37 | _this.setState({
38 | targetCurrentX: targetCurrentX,
39 | targetCurrentY: targetCurrentY
40 | })
41 | }
42 |
43 | function mouseup (e) {
44 | _this.setState({
45 | targetSourceX: _this.state.targetCurrentX,
46 | targetSourceY: _this.state.targetCurrentY
47 | })
48 | document.removeEventListener('mousemove', mousemove);
49 | document.removeEventListener('mouseup', mouseup);
50 | }
51 | }
52 | },
53 | moveunderway: function (e) {
54 | var currentX = e.nativeEvent.changedTouches[0].pageX;
55 | var currentY = e.nativeEvent.changedTouches[0].pageY;
56 | var distanceX = currentX - this.state.startX;
57 | var distanceY = currentY - this.state.startY;
58 | var targetCurrentX = this.state.targetSourceX + distanceX;
59 | var targetCurrentY = this.state.targetSourceY + distanceY;
60 | this.setState({
61 | targetCurrentX: targetCurrentX,
62 | targetCurrentY: targetCurrentY
63 | })
64 | },
65 | moveend: function (e) {
66 | this.setState({
67 | targetSourceX: this.state.targetCurrentX,
68 | targetSourceY: this.state.targetCurrentY
69 | })
70 | if (!this.state.isMobile) {
71 | var oTarget = this.refs.target;
72 | oTarget.removeEventListener('mousemove', this.moveunderway.bind(this));
73 | oTarget.removeEventListener('mouseup', this.moveend.bind(this));
74 | }
75 | },
76 | render: function () {
77 | var targetStyle = {
78 | width: '100px',
79 | height: '100px',
80 | backgroundColor: 'orange',
81 | fontSize: '30px',
82 | color: '#ffffff',
83 | textAlign: 'center',
84 | lineHeight: '100px',
85 | position: 'relative',
86 | cursor: 'move',
87 | userSelect: 'none',
88 | left: `${this.state.targetCurrentX}px`,
89 | top: `${this.state.targetCurrentY}px`
90 | }
91 | return (
92 | REACT
98 | )
99 | }
100 | })
101 |
102 | ReactDOM.render(, document.querySelector('#content'))
--------------------------------------------------------------------------------
/drag-by-react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | react component
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------