JavaScript实现的多种鼠标拖放效果


Posted in Javascript onNovember 03, 2015

本文实例讲述了JavaScript实现的多种鼠标拖放效果。分享给大家供大家参考,具体如下:

这是一款JavaScript鼠标拖放效果代码,通过本示例了解触发对象,设置范围限制,指定容器大小水平及垂直锁定,还包括获取和释放焦点等。

运行效果截图如下:

JavaScript实现的多种鼠标拖放效果

在线演示地址如下:

具体代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>拖放效果</title>
</head>
<body>
<script> 
var isIE = (document.all) ? true : false;
var $ = function (id) {
 return "string" == typeof id ? document.getElementById(id) : id;
};
var Class = {
 create: function() {
  return function() { this.initialize.apply(this, arguments); }
 }
}
var Extend = function(destination, source) {
 for (var property in source) {
  destination[property] = source[property];
 }
}
var Bind = function(object, fun) {
 return function() {
  return fun.apply(object, arguments);
 }
}
var BindAsEventListener = function(object, fun) {
 return function(event) {
  return fun.call(object, (event || window.event));
 }
}
var CurrentStyle = function(element){
 return element.currentStyle || document.defaultView.getComputedStyle(element, null);
}
function addEventHandler(oTarget, sEventType, fnHandler) {
 if (oTarget.addEventListener) {
  oTarget.addEventListener(sEventType, fnHandler, false);
 } else if (oTarget.attachEvent) {
  oTarget.attachEvent("on" + sEventType, fnHandler);
 } else {
  oTarget["on" + sEventType] = fnHandler;
 }
};
function removeEventHandler(oTarget, sEventType, fnHandler) {
 if (oTarget.removeEventListener) {
 oTarget.removeEventListener(sEventType, fnHandler, false);
 } else if (oTarget.detachEvent) {
 oTarget.detachEvent("on" + sEventType, fnHandler);
 } else { 
 oTarget["on" + sEventType] = null;
 }
};
//拖放程序
var Drag = Class.create();
Drag.prototype = {
//拖放对象
 initialize: function(drag, options) {
 this.Drag = $(drag);//拖放对象
 this._x = this._y = 0;//记录鼠标相对拖放对象的位置
 this._marginLeft = this._marginTop = 0;//记录margin
 //事件对象(用于绑定移除事件)
 this._fM = BindAsEventListener(this, this.Move);
 this._fS = Bind(this, this.Stop);
 this.SetOptions(options);
 this.Limit = !!this.options.Limit;
 this.mxLeft = parseInt(this.options.mxLeft);
 this.mxRight = parseInt(this.options.mxRight);
 this.mxTop = parseInt(this.options.mxTop);
 this.mxBottom = parseInt(this.options.mxBottom);
 this.LockX = !!this.options.LockX;
 this.LockY = !!this.options.LockY;
 this.Lock = !!this.options.Lock;
 this.onStart = this.options.onStart;
 this.onMove = this.options.onMove;
 this.onStop = this.options.onStop;
 this._Handle = $(this.options.Handle) || this.Drag;
 this._mxContainer = $(this.options.mxContainer) || null;
 this.Drag.style.position = "absolute";
 //透明
 if(isIE && !!this.options.Transparent){
  //填充拖放对象
  with(this._Handle.appendChild(document.createElement("div")).style){
   width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)";
  }
 }
 //修正范围
 this.Repair();
 addEventHandler(this._Handle, "mousedown", BindAsEventListener(this, this.Start));
 },
 //设置默认属性
 SetOptions: function(options) {
 this.options = {//默认值
  Handle:   "",//设置触发对象(不设置则使用拖放对象)
  Limit:   false,//是否设置范围限制(为true时下面参数有用,可以是负数)
  mxLeft:   0,//左边限制
  mxRight:  9999,//右边限制
  mxTop:   0,//上边限制
  mxBottom:  9999,//下边限制
  mxContainer: "",//指定限制在容器内
  LockX:   false,//是否锁定水平方向拖放
  LockY:   false,//是否锁定垂直方向拖放
  Lock:   false,//是否锁定
  Transparent: false,//是否透明
  onStart:  function(){},//开始移动时执行
  onMove:   function(){},//移动时执行
  onStop:   function(){}//结束移动时执行
 };
 Extend(this.options, options || {});
 },
 //准备拖动
 Start: function(oEvent) {
 if(this.Lock){ return; }
 this.Repair();
 //记录鼠标相对拖放对象的位置
 this._x = oEvent.clientX - this.Drag.offsetLeft;
 this._y = oEvent.clientY - this.Drag.offsetTop;
 //记录margin
 this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
 this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
 //mousemove时移动 mouseup时停止
 addEventHandler(document, "mousemove", this._fM);
 addEventHandler(document, "mouseup", this._fS);
 if(isIE){
  //焦点丢失
  addEventHandler(this._Handle, "losecapture", this._fS);
  //设置鼠标捕获
  this._Handle.setCapture();
 }else{
  //焦点丢失
  addEventHandler(window, "blur", this._fS);
  //阻止默认动作
  oEvent.preventDefault();
 };
 //附加程序
 this.onStart();
 },
 //修正范围
 Repair: function() {
 if(this.Limit){
  //修正错误范围参数
  this.mxRight = Math.max(this.mxRight, this.mxLeft + this.Drag.offsetWidth);
  this.mxBottom = Math.max(this.mxBottom, this.mxTop + this.Drag.offsetHeight);
  //如果有容器必须设置position为relative来相对定位,并在获取offset之前设置
  !this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
 }
 },
 //拖动
 Move: function(oEvent) {
 //判断是否锁定
 if(this.Lock){ this.Stop(); return; };
 //清除选择
 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
 //设置移动参数
 var iLeft = oEvent.clientX - this._x, iTop = oEvent.clientY - this._y;
 //设置范围限制
 if(this.Limit){
  //设置范围参数
  var mxLeft = this.mxLeft, mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
  //如果设置了容器,再修正范围参数
  if(!!this._mxContainer){
   mxLeft = Math.max(mxLeft, 0);
   mxTop = Math.max(mxTop, 0);
   mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
   mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
  };
  //修正移动参数
  iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
  iTop = Math.max(Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
 }
 //设置位置,并修正margin
 if(!this.LockX){ this.Drag.style.left = iLeft - this._marginLeft + "px"; }
 if(!this.LockY){ this.Drag.style.top = iTop - this._marginTop + "px"; }
 //附加程序
 this.onMove();
 },
 //停止拖动
 Stop: function() {
 //移除事件
 removeEventHandler(document, "mousemove", this._fM);
 removeEventHandler(document, "mouseup", this._fS);
 if(isIE){
  removeEventHandler(this._Handle, "losecapture", this._fS);
  this._Handle.releaseCapture();
 }else{
  removeEventHandler(window, "blur", this._fS);
 };
 //附加程序
 this.onStop();
 }
};
</script>
<style> 
#idContainer{ border:10px solid #990000; width:600px; height:300px;}
#idDrag{ border:5px solid #C4E3FD; background:#C4E3FD; width:50px; height:50px; top:50px; left:50px;}
#idHandle{cursor:move; height:25px; background:#0000FF; overflow:hidden;}
</style>
<div id="idContainer">
<div id="idDrag"><div id="idHandle"></div></div>
</div>
<input id="idReset" type="button" value="复位" />
<input id="idLock" type="button" value="锁定" />
<input id="idLockX" type="button" value="锁定水平" />
<input id="idLockY" type="button" value="锁定垂直" />
<input id="idLimit" type="button" value="范围锁定" />
<input id="idLimitOff" type="button" value="取消范围锁定" />
<br />拖放状态:<span id="idShow">未开始</span>
<script> 
var drag = new Drag("idDrag", { mxContainer: "idContainer", Handle: "idHandle", Limit: true,
 onStart: function(){ $("idShow").innerHTML = "开始拖放"; },
 onMove: function(){ $("idShow").innerHTML = "left:"+this.Drag.offsetLeft+";top:"+this.Drag.offsetTop; },
 onStop: function(){ $("idShow").innerHTML = "结束拖放"; }
});
$("idReset").onclick = function(){
 drag.Limit = true;
 drag.mxLeft = drag.mxTop = 0;
 drag.mxRight = drag.mxBottom = 9999;
 drag.LockX = drag.LockY = drag.Lock = false;
}
$("idLock").onclick = function(){ drag.Lock = true; }
$("idLockX").onclick = function(){ drag.LockX = true; }
$("idLockY").onclick = function(){ drag.LockY = true; }
$("idLimit").onclick = function(){  drag.mxRight = drag.mxBottom = 200;drag.Limit = true; }
$("idLimitOff").onclick = function(){ drag.Limit = false; }
</script>
</body>
</html>

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
实现变速回到顶部的JavaScript代码
May 09 Javascript
前端开发过程中浏览器版本的两种判定方法
Oct 30 Javascript
MyEclipse取消验证Js的两种方法
Nov 14 Javascript
教你用AngularJS框架一行JS代码实现控件验证效果
Jun 23 Javascript
jquery实现简单的二级导航下拉菜单效果
Sep 07 Javascript
JS日期格式化之javascript Date format
Oct 01 Javascript
JS判断日期格式是否合法的简单实例
Jul 11 Javascript
JS简单设置下拉选择框默认值的方法
Aug 20 Javascript
详解如何较好的使用js
Dec 16 Javascript
React性能优化系列之减少props改变的实现方法
Jan 17 Javascript
JavaScript中工厂函数与构造函数示例详解
May 06 Javascript
JavaScript分页组件使用方法详解
Jul 26 Javascript
JavaScript实现的Tween算法及缓冲特效实例代码
Nov 03 #Javascript
jQuery实现Email邮箱地址自动补全功能代码
Nov 03 #Javascript
jQuery实现仿QQ头像闪烁效果的文字闪动提示代码
Nov 03 #Javascript
基于JavaScript怎么实现让歌词滚动播放
Nov 03 #Javascript
ECMA5数组的新增方法有哪些及forEach()模仿实现
Nov 03 #Javascript
Javascript设计模式理论与编程实战之简单工厂模式
Nov 03 #Javascript
JS实现网页标题随机显示名人名言的方法
Nov 03 #Javascript
You might like
Yii rules常用规则示例
2016/03/15 PHP
php使用文本统计访问量的方法
2016/05/12 PHP
php 数组处理函数extract详解及实例代码
2016/11/23 PHP
多个jquery.datatable共存,checkbox全选异常的快速解决方法
2013/12/10 Javascript
javascript中不等于的代码是什么怎么写
2013/12/29 Javascript
Extjs的FileUploadField文件上传出现了两个上传按钮
2014/04/29 Javascript
js怎么判断flash swf文件是否加载完毕
2014/08/14 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
2015/08/24 Javascript
jQuery实现带有洗牌效果的动画分页实例
2015/08/31 Javascript
详解express与koa中间件模式对比
2017/08/07 Javascript
JavaScript实现删除数组重复元素的5种常用高效算法总结
2018/01/18 Javascript
JS实现的邮箱提示补全效果示例
2018/01/30 Javascript
Vuepress 搭建带评论功能的静态博客的实现
2019/02/17 Javascript
js实现聊天对话框
2020/02/08 Javascript
Python实现的tab文件操作类分享
2014/11/20 Python
在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程
2015/04/25 Python
Python中Random和Math模块学习笔记
2015/05/18 Python
Python编程实现及时获取新邮件的方法示例
2017/08/10 Python
Python图像处理之gif动态图的解析与合成操作详解
2018/12/30 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
python 字典操作提取key,value的方法
2019/06/26 Python
python 随机森林算法及其优化详解
2019/07/11 Python
Django REST Framework之频率限制的使用
2019/09/29 Python
OpenCV模板匹配matchTemplate的实现
2019/10/18 Python
开普敦通行证:Cape Town Pass
2019/07/18 全球购物
芭比波朗加拿大官方网站:Bobbi Brown Cosmetics CA
2020/11/05 全球购物
后勤副校长自我鉴定
2013/10/13 职场文书
《雾凇》教学反思
2014/02/17 职场文书
《蒲公英》教学反思
2014/02/28 职场文书
洗发露广告词
2014/03/14 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
反对四风自我剖析材料
2014/10/07 职场文书
长征观后感
2015/06/09 职场文书
Vue提供的三种调试方式你知道吗
2022/01/18 Vue.js
你需要掌握的20个Python常用技巧
2022/02/28 Python
SQL Server数据库基本概念、组成、常用对象与约束
2022/03/20 SQL Server