js 实现win7任务栏拖动效果
2020-12-13 06:14
标签:style blog color os io for ar cti 在某个时刻, 我认识了一个朋友. 此人在我的教唆下, 踏上了js的不归路. 前天他问我, Win7任务栏拖动效果怎么实现. 我随口就跟他说, 这简单的一逼. 在我一晚上的折腾之后, 一份潦草的代码总算实现了功能. PS: 我是搞C++的, js略懂一二.. 话不多说, 上源码. 这个思路其实很简单. 创建一个Taskbar对象, 这个对象设定好坐标, 尺寸, 背景色. 随后往这个对象appendChild, 子节点会自动适配大小. 我们用一个 作业队列 来保存需要移动的任务. 这个队列保存需要被移动的节点, 和被动到哪个位置上. 随后会触发一个交换的动作, 这个动作是持续性的, 因此可以看到节点平滑移动. 在我们down下操作之后, 被down下的那个节点位置设置null. 随后我们用一个 _selNode 保存这个节点. 同时用 _selIndex 保存这个节点本应该属于的位置.(这句话很难形容, 但是我想不出怎么说!) 随后在move操作下, 判断这个 _selNode 是否"越线", 一旦越线则push一个交换作业. 随后就像上面所说, 触发交换动作. 在up操作触发之后, 只需要把 _selNode和_selIndex push到作业队列即可. 因为所有的mouse响应都在背景的div里, 因此鼠标超出范围则不会响应.. 例如, 我down之后, 鼠标移出范围再up, 此时的up将不会被响应.. 我在down中加了一条判断来解决此bug.. 在超出范围up, 回到范围之后, 依然是down状态. js 实现win7任务栏拖动效果,搜素材,soscw.com js 实现win7任务栏拖动效果 标签:style blog color os io for ar cti 原文地址:http://www.cnblogs.com/mmc1206x/p/3901281.html前言
源码
1 // 常量
2 var CELL_WIDTH = 100;
3 var CELL_HEIGHT = 50;
4
5 var Utils = {
6 pixelToInt: function(str)
7 {
8 return parseInt( str.replace("px", "") );
9 },
10 getTagLeft: function($tag)
11 {
12 return this.pixelToInt( $tag.css("left") );
13 },
14 getTagTop: function($tag)
15 {
16 return this.pixelToInt( $tag.css("top") );
17 },
18 getTagWidth: function($tag)
19 {
20 return this.pixelToInt( $tag.css("width") );
21 },
22 getTagHeight: function($tag)
23 {
24 return this.pixelToInt( $tag.css("height") );
25 },
26 setTagLeft: function($tag, x)
27 {
28 $tag.css("left", x + "px");
29 },
30 setTagTop: function($tag, y)
31 {
32 $tag.css("top", y + "px");
33 },
34 setTagWidth: function($tag, width)
35 {
36 $tag.css("width", width + "px");
37 },
38 setTagHeight: function($tag, height)
39 {
40 $tag.css("left", height + "px");
41 },
42 swapNode: function(ary, idx1, idx2)
43 {
44 var t = ary[idx1];
45 ary[idx1] = ary[idx2];
46 ary[idx2] = t;
47 }
48 };
49
50 function Taskbar()
51 {
52 this._cells = [];
53 this._frameTag = null;
54 this._cellWidth = 0;
55 this._cellHeight = 0;
56 this._selNode = null;
57 this._selIndex = -1;
58
59 this._swapQueue = [];
60 // 考虑优化.
61 this._offsetPoint = {"x": 0, "y": 0};
62 }
63
64 Taskbar.prototype.getTag = function()
65 {
66 return this._frameTag;
67 }
68
69 Taskbar.prototype.init = function(x, y, width, height, rgb)
70 {
71 this._frameTag = $("");
72 this.setPosition(x, y);
73 this.setContentSize(width, height);
74 this.setBackgroundColor(rgb);
75
76 var self = this;
77 this._frameTag.bind("mousedown", {"bar": self}, this.mouseDown);
78 this._frameTag.bind("mouseup", {"bar": self}, this.mouseUp);
79 this._frameTag.bind("mousemove", {"bar": self}, this.mouseMove);
80 // this._frameTag.bind("mouseout", {"bar": self}, this.mouseOut);
81 }
82
83 Taskbar.prototype.setPosition = function(x, y)
84 {
85 this._frameTag.css("position", "absolute");
86 this._frameTag.css("left", x + "px");
87 this._frameTag.css("top", y + "px");
88 }
89
90 Taskbar.prototype.setContentSize = function(width, height)
91 {
92 this._frameTag.css("width", width + "px");
93 this._frameTag.css("height", height + "px");
94 }
95
96 Taskbar.prototype.setBackgroundColor = function(rgb)
97 {
98 // rgb => "rgb(0, 0, 0)".
99 this._frameTag.css("background", rgb);
100 }
101
102 Taskbar.prototype.appendNode = function($node)
103 {
104 var frameWidth = Utils.getTagWidth( this._frameTag );
105 var frameHeight = Utils.getTagHeight( this._frameTag );
106 var length = this._cells.length + 1;
107 this._cellWidth = frameWidth / length;
108 this._cellHeight = frameHeight;
109 this._cells.push($node);
110 $node.appendTo( this._frameTag );
111
112 for ( var i = 0; i != length; ++i )
113 {
114 Utils.setTagLeft( this._cells[i], i * this._cellWidth );
115 Utils.setTagWidth( this._cells[i], this._cellWidth);
116 }
117 }
118
119 Taskbar.prototype.mouseDown = function(e)
120 {
121 var bar = e.data["bar"];
122
123 if ( bar._selNode )
124 {
125 return ;
126 }
127
128 var index = bar.hitTest(e.clientX, e.clientY);
129 if ( !bar.isInvalidIndex(index) )
130 {
131 // 激活.
132 bar._selIndex = index;
133 bar._selNode = bar._cells[ index ];
134 bar._selNode.css("z-index", 99);
135 bar._cells[ index ] = null;
136
137 // 保存偏移量, 保持鼠标拖动.
138 var point = bar.converPoint(e.clientX, e.clientY);
139 bar._offsetPoint.x = point.x - index * bar._cellWidth;
140 bar._offsetPoint.y = point.y;
141 console.log("down");
142 }
143
144 }
145
146 Taskbar.prototype.mouseUp = function(e)
147 {
148 var bar = e.data["bar"];
149
150 if ( bar._selNode )
151 {
152 // 加入交换.
153 bar.appendSwap(bar._selNode, bar._selIndex);
154
155 // 鼠标抬起后, 把选中的节点复位.
156 // bar._cells[ bar._selIndex ] = bar._selNode;
157 bar._cells[ bar._selIndex ].css("z-index", 1);
158 bar._selIndex = -1;
159 bar._selNode = null;
160 console.log("up");
161 }
162 }
163
164 Taskbar.prototype.mouseOut = function(e)
165 {
166 var bar = e.data["bar"];
167 bar.mouseUp(e);
168 console.log("mouseout");
169 }
170
171 Taskbar.prototype.mouseMove = function(e)
172 {
173 var bar = e.data["bar"];
174 if ( bar._selNode )
175 {
176 var point = bar.converPoint(e.clientX, e.clientY);
177 var moveX = point.x - bar._offsetPoint.x;
178
179 // 防止位置溢出.
180 bar.noOverflow( bar._selNode, moveX );
181
182 // 挤开旁边的 float block.
183 var curX = Utils.getTagLeft(bar._selNode),
184 width = Utils.getTagWidth(bar._selNode),
185 testX = curX + width / 2,
186 hitIndex = bar.hitTest(testX, 0);
187 if ( bar._selIndex != hitIndex )
188 {
189 bar.appendSwap(bar._cells[hitIndex], bar._selIndex);
190 bar._selIndex = hitIndex;
191 }
192 }
193 }
194
195 Taskbar.prototype.appendSwap = function($node, index)
196 {
197 this._cells[index] = $node;
198
199 this._swapQueue.push({"node": $node, "index": index});
200 this.resetNode();
201 }
202
203 Taskbar.prototype.noOverflow = function($node, moveX)
204 {
205 var width = Utils.getTagWidth( $node ),
206 frameWidth = Utils.getTagWidth( this._frameTag );
207
208 if (moveX )
209 moveX = 0;
210 else if ( moveX + width > frameWidth )
211 moveX = frameWidth - width;
212
213 Utils.setTagLeft( $node, moveX );
214 }
215
216 Taskbar.prototype.resetNode = function()
217 {
218 var self = this;
219 var call = function($node, index)
220 {
221 var oldX = Utils.getTagLeft($node),
222 newX = index * self._cellWidth,
223 diff = newX - oldX,
224 stepCount = 10,
225 step = diff / stepCount,
226 curX = oldX;
227 (
228 function call()
229 {
230 if ( stepCount != 0 )
231 {
232 curX += step;
233 Utils.setTagLeft($node, curX);
234 setTimeout(call, 10);
235 }
236 else
237 {
238 $node.css("z-index", 0);
239 Utils.setTagLeft($node, newX);
240 }
241 --stepCount;
242 }
243 )();
244 };
245
246 for (var i in this._swapQueue)
247 {
248 call(this._swapQueue[i].node, this._swapQueue[i].index);
249 }
250 this._swapQueue = [];
251 }
252
253 Taskbar.prototype.hitTest = function(x, y)
254 {
255 // y参数完全是个酱油.
256 var point = this.converPoint(x, y);
257 return parseInt(point.x / this._cellWidth);
258 }
259
260 Taskbar.prototype.converPoint = function(x, y)
261 {
262 var frameX = Utils.getTagLeft( this._frameTag );
263 frameY = Utils.getTagTop( this._frameTag );
264 return {
265 "x": x -= frameX,
266 "y": y -= frameY
267 };
268 }
269
270 Taskbar.prototype.isInvalidIndex = function(index)
271 {
272 return index = this._cells.length;
273 }
274
275 function init()
276 {
277 var getCell = function(cls, left, top, name)
278 {
279 return $(
280 ""
281 .replace("_cls", cls)
282 .replace("_left", left)
283 .replace("_top", top)
284 .replace("_name", name)
285 .replace("_width", CELL_WIDTH)
286 .replace("_height", CELL_HEIGHT) );
287 };
288
289 // for (var i = 0; i != 5; ++i)
290 // {
291 // var taskbar = new Taskbar();
292 // taskbar.init(0, i * 60, 500, 50, "rgb(0, 0, 0)");
293 // taskbar.getTag().appendTo( $("body") );
294 // for (var j = 0; j != i + 5; ++j)
295 // {
296 // taskbar.appendNode( getCell("cell", 0, 0, 0) );
297 // }
298 // }
299 }
300
301 $(document).ready(init);