拖放应该是浏览器中最流行的用户方式之一。为探索拖放,选择了由Aaron Boodman常见的DOM-Drag库,这个库提供了很多易用的特性,包括:
□ 拖放处理函数:可以在拖放ige父元素的同时拖放另一个子元素,这对创建类似窗口的界面十分有用
□ 回调函数:可以监听特定的事件,比如开始拖放、正在拖放和停止拖放等事件,以及元素的当前位置信息
□ 拖放区域的范围:可以现在元素在特定的区域内拖放,这对创建滚动条是非有效
□ 自定义坐标系统:如果不太喜欢CSS坐标系统,则可以任意组合x/y坐标体系
□ 自定x/y坐标的映射:可以让拖放元素使用非传统方式进行移动
使用DOM-Drag库比较简单
1. 链接DOM-Drag库
<script src="domdrag.js" type="text/javascript"></script>
2. 添加要拖放的代码块
<div id="root" style="left:50px; top:100px;"> <div id="handle">Handle</div> Some text </div>
3. 为要拖放的元素增加样式
<style> #root { position:absolute; height:300px; width:300px; background-color:#F4F4F4; border:1px solid #333; } #handle { margin:2px; padding:2px; width: 98%; color:white; background-color: navy; font-weight: bold; } </style>
4. 调用DOM-Drag库的init函数实现拖放操作
<script language="javascript"> var theHandle = document.getElementById("handle"); var theRoot = document.getElementById("root"); Drag.init(theHandle, theRoot); </script>
完整的代码如下:
<html> <head> <title>DOM-Drag Draggable Window Demo</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <script src="domdrag.js" type="text/javascript"></script> <style> #root { position:absolute; height:300px; width:300px; background-color:#F4F4F4; border:1px solid #333; } #handle { margin:2px; padding:2px; width: 98%; color:white; background-color: navy; font-weight: bold; } </style> </head> <body> <h1>Draggable Window Demo</h1> <div id="root" style="left:50px; top:100px;"> <div id="handle">Handle</div> Some text </div> <script language="javascript"> var theHandle = document.getElementById("handle"); var theRoot = document.getElementById("root"); Drag.init(theHandle, theRoot); </script> </body> </html>
DOM-Drag库的完整代码如下:
var Drag = { // 当前拖放的元素 obj: null, // 拖放对象的初始化函数 // o = 拖放的元素 // oRoot = 拖放的根元素 // minX, maxX, minY, maxY = 拖放的范围 // bSwapHorzRef = 切换水平坐标系统 // bSwapVertRef = 切换垂直坐标系统 // fxMapper, fyMapper = 映射x和y坐标的函数 init: function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) { // 监听拖放事件的开始 o.onmousedown = Drag.start; // 获取坐标系统 o.hmode = bSwapHorzRef ? false : true ; o.vmode = bSwapVertRef ? false : true ; // 作为拖放把手的元素 o.root = oRoot && oRoot != null ? oRoot : o ; // 初始化坐标系统 if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px"; if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px"; if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px"; if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px"; // 检查拖放范围 o.minX = typeof minX != 'undefined' ? minX : null; o.minY = typeof minY != 'undefined' ? minY : null; o.maxX = typeof maxX != 'undefined' ? maxX : null; o.maxY = typeof maxY != 'undefined' ? maxY : null; // 检查坐标映射范围 o.xMapper = fXMapper ? fXMapper : null; o.yMapper = fYMapper ? fYMapper : null; // 添加事件监听 o.root.onDragStart = new Function(); o.root.onDragEnd = new Function(); o.root.onDrag = new Function(); }, start: function(e) { // 获取拖放对象 var o = Drag.obj = this; // 标准化事件对象 e = Drag.fixE(e); // 获取当前的x和y坐标 var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); // 调用开始拖放函数 o.root.onDragStart(x, y); // 鼠标的开始位置 o.lastMouseX = e.clientX; o.lastMouseY = e.clientY; // 如果使用了CSS坐标系统 if (o.hmode) { // 设置水平范围 if (o.minX != null) o.minMouseX = e.clientX - x + o.minX; if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX; // 如果使用传统的坐标系统 } else { if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x; if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x; } // 如果使用了CSS坐标系统 if (o.vmode) { // 设置垂直范围 if (o.minY != null) o.minMouseY = e.clientY - y + o.minY; if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY; // 如果使用传统的坐标系统 } else { if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y; if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y; } // 检查拖放中和拖放结束事件 document.onmousemove = Drag.drag; document.onmouseup = Drag.end; return false; }, // 在拖放过程中监听所有鼠标移动的函数 drag: function(e) { // 标准化事件对象 e = Drag.fixE(e); // 获取拖放对象 var o = Drag.obj; // 获取鼠标在窗口内的位置 var ey = e.clientY; var ex = e.clientX; // 获取当前的x和y坐标 var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); var nx, ny; // 检查水平范围 if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX); if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX); // 检查垂直范围 if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY); if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY); // 经过转换的x和y坐标 nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); // 如果提供映射函数,则映射x和y坐标 if (o.xMapper) nx = o.xMapper(y) else if (o.yMapper) ny = o.yMapper(x) // 为元素设置新的x和y坐标 Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; // 保存鼠标的最后位置 Drag.obj.lastMouseX = ex; Drag.obj.lastMouseY = ey; // 以转换后的坐标为参数调用onDrag函数 Drag.obj.root.onDrag(nx, ny); return false; }, // 处理拖放结束事件 end: function() { // 取消鼠标监听事件 document.onmousemove = null; document.onmouseup = null; // 以拖放的结束坐标为参数,调用onDragEnd函数 Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"])); // 取消拖放对象 Drag.obj = null; }, // 标准化事件对象的函数 fixE: function(e) { // 如果不存在事件对象,则为IE浏览器 if (typeof e == 'undefined') e = window.event; // 如果没有设置 layerX 和 layerY 属性,则获取等效的 offsetX 和 offsetY 属性的值 if (typeof e.layerX == 'undefined') e.layerX = e.offsetX; if (typeof e.layerY == 'undefined') e.layerY = e.offsetY; return e; } };
转载请注明:陈童的博客 » JavaScript与CSS — 拖放