首页 技术 正文
技术 2022年11月13日
0 收藏 698 点赞 2,497 浏览 6272 个字

<!–
h1 {
background: rgb(21, 98, 231);
border-radius: 15px 15px 15px 15px;
box-shadow: 0px 0px 8px rgb(0, 0, 0);
text-indent: 0.5em;
}
–>

前言

在某个时刻, 我认识了一个朋友.

此人在我的教唆下, 踏上了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文件.

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,489
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,904
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,737
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,490
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,128
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,291