js 实现win7任务栏拖动效果
前言
在某个时刻, 我认识了一个朋友.
此人在我的教唆下, 踏上了js的不归路.
前天他问我, Win7任务栏拖动效果怎么实现.
我随口就跟他说, 这简单的一逼.
在我一晚上的折腾之后, 一份潦草的代码总算实现了功能.
PS: 我是搞C++的, js略懂一二..
源码
话不多说, 上源码.
// 常量 var CELL_WIDTH = 100; var CELL_HEIGHT = 50; var Utils = { pixelToInt: function(str) { return parseInt( str.replace("px", "") ); }, getTagLeft: function($tag) { return this.pixelToInt( $tag.css("left") ); }, getTagTop: function($tag) { return this.pixelToInt( $tag.css("top") ); }, getTagWidth: function($tag) { return this.pixelToInt( $tag.css("width") ); }, getTagHeight: function($tag) { return this.pixelToInt( $tag.css("height") ); }, setTagLeft: function($tag, x) { $tag.css("left", x + "px"); }, setTagTop: function($tag, y) { $tag.css("top", y + "px"); }, setTagWidth: function($tag, width) { $tag.css("width", width + "px"); }, setTagHeight: function($tag, height) { $tag.css("left", height + "px"); }, swapNode: function(ary, idx1, idx2) { var t = ary[idx1]; ary[idx1] = ary[idx2]; ary[idx2] = t; } }; function Taskbar() { this._cells = []; this._frameTag = null; this._cellWidth = 0; this._cellHeight = 0; this._selNode = null; this._selIndex = -1; this._swapQueue = []; // 考虑优化. this._offsetPoint = {"x": 0, "y": 0}; } Taskbar.prototype.getTag = function() { return this._frameTag; } Taskbar.prototype.init = function(x, y, width, height, rgb) { this._frameTag = $("<div></div>"); this.setPosition(x, y); this.setContentSize(width, height); this.setBackgroundColor(rgb); var self = this; this._frameTag.bind("mousedown", {"bar": self}, this.mouseDown); this._frameTag.bind("mouseup", {"bar": self}, this.mouseUp); this._frameTag.bind("mousemove", {"bar": self}, this.mouseMove); // this._frameTag.bind("mouseout", {"bar": self}, this.mouseOut); } Taskbar.prototype.setPosition = function(x, y) { this._frameTag.css("position", "absolute"); this._frameTag.css("left", x + "px"); this._frameTag.css("top", y + "px"); } Taskbar.prototype.setContentSize = function(width, height) { this._frameTag.css("width", width + "px"); this._frameTag.css("height", height + "px"); } Taskbar.prototype.setBackgroundColor = function(rgb) { // rgb => "rgb(0, 0, 0)". this._frameTag.css("background", rgb); } Taskbar.prototype.appendNode = function($node) { var frameWidth = Utils.getTagWidth( this._frameTag ); var frameHeight = Utils.getTagHeight( this._frameTag ); var length = this._cells.length + 1; this._cellWidth = frameWidth / length; this._cellHeight = frameHeight; this._cells.push($node); $node.appendTo( this._frameTag ); for ( var i = 0; i != length; ++i ) { Utils.setTagLeft( this._cells[i], i * this._cellWidth ); Utils.setTagWidth( this._cells[i], this._cellWidth); } } Taskbar.prototype.mouseDown = function(e) { var bar = e.data["bar"]; if ( bar._selNode ) { return ; } var index = bar.hitTest(e.clientX, e.clientY); if ( !bar.isInvalidIndex(index) ) { // 激活. bar._selIndex = index; bar._selNode = bar._cells[ index ]; bar._selNode.css("z-index", 99); bar._cells[ index ] = null; // 保存偏移量, 保持鼠标拖动. var point = bar.converPoint(e.clientX, e.clientY); bar._offsetPoint.x = point.x - index * bar._cellWidth; bar._offsetPoint.y = point.y; console.log("down"); } } Taskbar.prototype.mouseUp = function(e) { var bar = e.data["bar"]; if ( bar._selNode ) { // 加入交换. bar.appendSwap(bar._selNode, bar._selIndex); // 鼠标抬起后, 把选中的节点复位. // bar._cells[ bar._selIndex ] = bar._selNode; bar._cells[ bar._selIndex ].css("z-index", 1); bar._selIndex = -1; bar._selNode = null; console.log("up"); } } Taskbar.prototype.mouseOut = function(e) { var bar = e.data["bar"]; bar.mouseUp(e); console.log("mouseout"); } Taskbar.prototype.mouseMove = function(e) { var bar = e.data["bar"]; if ( bar._selNode ) { var point = bar.converPoint(e.clientX, e.clientY); var moveX = point.x - bar._offsetPoint.x; // 防止位置溢出. bar.noOverflow( bar._selNode, moveX ); // 挤开旁边的 float block. var curX = Utils.getTagLeft(bar._selNode), width = Utils.getTagWidth(bar._selNode), testX = curX + width / 2, hitIndex = bar.hitTest(testX, 0); if ( bar._selIndex != hitIndex ) { bar.appendSwap(bar._cells[hitIndex], bar._selIndex); bar._selIndex = hitIndex; } } } Taskbar.prototype.appendSwap = function($node, index) { this._cells[index] = $node; this._swapQueue.push({"node": $node, "index": index}); this.resetNode(); } Taskbar.prototype.noOverflow = function($node, moveX) { var width = Utils.getTagWidth( $node ), frameWidth = Utils.getTagWidth( this._frameTag ); if (moveX < 0) moveX = 0; else if ( moveX + width > frameWidth ) moveX = frameWidth - width; Utils.setTagLeft( $node, moveX ); } Taskbar.prototype.resetNode = function() { var self = this; var call = function($node, index) { var oldX = Utils.getTagLeft($node), newX = index * self._cellWidth, diff = newX - oldX, stepCount = 10, step = diff / stepCount, curX = oldX; ( function call() { if ( stepCount != 0 ) { curX += step; Utils.setTagLeft($node, curX); setTimeout(call, 10); } else { $node.css("z-index", 0); Utils.setTagLeft($node, newX); } --stepCount; } )(); }; for (var i in this._swapQueue) { call(this._swapQueue[i].node, this._swapQueue[i].index); } this._swapQueue = []; } Taskbar.prototype.hitTest = function(x, y) { // y参数完全是个酱油. var point = this.converPoint(x, y); return parseInt(point.x / this._cellWidth); } Taskbar.prototype.converPoint = function(x, y) { var frameX = Utils.getTagLeft( this._frameTag ); frameY = Utils.getTagTop( this._frameTag ); return { "x": x -= frameX, "y": y -= frameY }; } Taskbar.prototype.isInvalidIndex = function(index) { return index < 0 || index >= this._cells.length; } function init() { var getCell = function(cls, left, top, name) { return $( "<div class='_cls' name='_name' style='left: _leftpx; top: _toppx; width: _widthpx; height: _heightpx;'></div>" .replace("_cls", cls) .replace("_left", left) .replace("_top", top) .replace("_name", name) .replace("_width", CELL_WIDTH) .replace("_height", CELL_HEIGHT) ); }; for (var i = 0; i != 5; ++i) { var taskbar = new Taskbar(); taskbar.init(0, i * 60, 500, 50, "rgb(0, 0, 0)"); taskbar.getTag().appendTo( $("body") ); for (var j = 0; j != i + 5; ++j) { taskbar.appendNode( getCell("cell", 0, 0, 0) ); } } } $(document).ready(init);
这个思路其实很简单.
创建一个Taskbar对象, 这个对象设定好坐标, 尺寸, 背景色.
随后往这个对象appendChild, 子节点会自动适配大小.
我们用一个 作业队列 来保存需要移动的任务.
这个队列保存需要被移动的节点, 和被动到哪个位置上.
随后会触发一个交换的动作, 这个动作是持续性的, 因此可以看到节点平滑移动.
在我们down下操作之后, 被down下的那个节点位置设置null.
随后我们用一个 _selNode 保存这个节点.
同时用 _selIndex 保存这个节点本应该属于的位置.(这句话很难形容, 但是我想不出怎么说!)
随后在move操作下, 判断这个 _selNode 是否"越线", 一旦越线则push一个交换作业.
随后就像上面所说, 触发交换动作.
在up操作触发之后, 只需要把 _selNode和_selIndex push到作业队列即可.
因为所有的mouse响应都在背景的div里, 因此鼠标超出范围则不会响应..
例如, 我down之后, 鼠标移出范围再up, 此时的up将不会被响应..
我在down中加了一条判断来解决此bug..
在超出范围up, 回到范围之后, 依然是down状态.
html 文件内容
<!DOCTYPE html> <html> <head> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="xy.js"></script> <style type="text/css"> * { margin: 0; border: 0; } .cell { position: absolute; width: 100px; height: 50px; border: solid; background: rgb(21, 98, 231); } </style> </head> <body> </body> </html>
之前写的匆忙, 只把脚本部分贴了上来, 漏掉了html文件.
js 实现win7任务栏拖动效果的更多相关文章
- HTML 通过js实现div的拖动效果
最近做项目,碰到一个问题,需要对div实现拖动效果. 在度娘找了很多,要么觉得代码太长,要么就是效果不理想,不过最后还是找到了一个不错的,感谢大神的留贴,方便了我们,就把代码贴下面了: <!DO ...
- js实现一个可以兼容PC端和移动端的div拖动效果
前段时间写了一个简单的div拖动效果,不料昨天项目上正好需要一个相差不多的需求,就正好用上了,但是在移动端的时候却碰到了问题,拖动时候用到的三个事件:mousedown.mousemove.mouse ...
- 通过html和css做出下拉导航栏的效果
通过观察了百度的首页,对于更多产品一栏,觉得可以不涉及JS便可写出下拉导航栏的效果 1.先设计出大体的框架 <div class="nav"> <ul> & ...
- js鼠标滚轮滚动图片切换效果
效果体验网址:http://keleyi.com/keleyi/phtml/image/12.htm HTML文件代码: <!DOCTYPE html PUBLIC "-//W3C// ...
- vc++ mfc中拖动效果的实现 借助于CImageList
拖动是界面编程频繁使用的一个效果,在windows系统下可谓大行其道.纵观时下的应用软件几乎各个都支持各种各样拖动的效果,windows7更是把拖动做到了极致.其实说起来拖动的实现也很简单,对于有句柄 ...
- jquery div拖动效果示例代码
div拖动效果想必大家都有见到过吧,实现的方法也是有很多的,下面为大家将介绍使用jquery是如何实现的,感兴趣的朋友不要错过 复制代码代码如下: <%@ page language=" ...
- js实现中文简繁切换效果
html代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...
- Web的鼠标拖动效果
以前写过一个拖动效果的Demo,拖拽元素新位置的计算是放在拖拽元素的mousemove事件中进行的.计算效率差,而且效果不好.所以一直有想怎样才能做出jquery-ui那种顺滑的拖拽效果. 其实顺滑的 ...
- jquery 实现导航栏滑动效果
精简的代码实现导航栏滑动效果,实现详解: 1.滑块位置:通过父节点position=fixed,子节点position=absolute方式,实现子节点浮动: 2.导航栏居中:通过left=0px,r ...
随机推荐
- 转:阿里旺旺导致python安装包失败的解决办法
我以前使用web.py没事,今天运行时报错, mimetypes.init() # try to read system mime.types File "D:\ProgramFiles\p ...
- Sudoku(回溯)
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 12075 Accepted: 6026 Special Judge ...
- 通过redis的monitor命令排除故障
项目里有10台服务器都在一个刀箱里,其中一台是redis缓存服务器,另外的是app服务器.通过监控发现这个刀箱的流量750M,其中缓存服务器的流量达105M,这么高的流量已经造成其它项目的服务器网络延 ...
- HDU4003 Find Metal Mineral
看别人思路的 树形分组背包. 题意:给出结点数n,起点s,机器人数k,然后n-1行给出相互连接的两个点,还有这条路线的价值,要求最小花费 思路:这是我从别人博客里找到的解释,因为很详细就引用了 dp[ ...
- qt项目转vs项目
Qt creator是一个非常好用的跨平台项目管理工具和集成开发环境(IDE).但是对于我自己来说Visual Studio依然是我最顺手的开发工具,由于Qt使用了moc,这样要是自己管理Visual ...
- 【模拟】Class 解题报告
[问题描述] 信息班这期的课将要结束了,老师要从现在班上的同学中选出比较优秀的同学进入下一期的学习.而录取标准则是将平时作业和考试一起考虑,综合成绩排在前面的则录取.经过一番思考,老师作了以下的筛选计 ...
- selenium python presence_of_element_located vs visibility_of_element_located
背景: 用WebDriverWait时,一开始用的是presence_of_element_located,我对它的想法就是他就是用来等待元素出现.结果屡屡出问题.元素默认是隐藏的,导致等待过早的就结 ...
- poj2299
好吧,看到这个图片就知道是干什么的了,求逆序数- - 可以用线段树,貌似还可以用归并排序,这题应该是考的归并排序,毕竟是递归分治- - 基本上都忘了,再写一写试试吧. AC ///////////// ...
- poj1038
题目大意:网络导航? 标准的web浏览器包含向前和向后浏览最近的页面的特性,有一个方法来实现这些用两个栈来跟踪页面达到向前和向后的移动,在这个问题里面,你被要求实现这些. 以下命令需要支持: BACK ...
- 5th day
感觉mysql里面的东西好多,很容易忘记,不是很熟练,知道某些函数有某种功能,但就是想不起来函数的名字,需要去翻笔记,真的还需要大量的练习,毕竟这块的内容可以说是全新的...不知道后面做项目怎么样,这 ...