JavaScript与CSS — 拖放

前端技术 everyinch 3999℃ 0评论

拖放应该是浏览器中最流行的用户方式之一。为探索拖放,选择了由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 — 拖放

喜欢 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
'; } if( dopt('d_footcode_b') ) echo dopt('d_footcode'); ?>