拖动缩放[转]

 

<!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(event));
 }
}
function Event(e){
 var oEvent = isIE ? window.event : e;
 if (isIE) {
  oEvent.target = oEvent.srcElement;
  oEvent.pageX = oEvent.clientX + document.documentElement.scrollLeft;
  oEvent.pageY = oEvent.clientY + document.documentElement.scrollTop;
  oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
  oEvent.preventDefault = function () { this.returnValue = false; };
  oEvent.detail = oEvent.wheelDelta / (-40);
  oEvent.stopPropagation = function(){ this.cancelBubble = true; }; 
  if(oEvent.type == "mouseout") {
   oEvent.relatedTarget = oEvent.toElement;
  }
  else if(oEvent.type == "mouseover") {
   oEvent.relatedTarget = oEvent.fromElement;
  }
 }
 return oEvent;
}
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)";
   }
  }
  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; }
  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");
  }
  //记录鼠标相对拖放对象的位置
  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();
 },
 //拖动
 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();
 }
};
//缩放程序
var Resize = Class.create();
Resize.prototype = {
 //缩放对象
 initialize: function(obj, options) {
  this._obj = $(obj);//缩放对象
  this._right = this._down = this._left = this._up = 0;//坐标参数
  this._scale = 1;//比例参数
  this._touch = null;//当前触发对象
  //
  var _style = CurrentStyle(this._obj);
  this._xBorder = (parseInt(_style.borderLeftWidth) || 0) + (parseInt(_style.borderRightWidth) || 0);
  this._yBorder = (parseInt(_style.borderTopWidth) || 0) + (parseInt(_style.borderBottomWidth) || 0);
  //事件对象(用于移除事件)
  this._fR = BindAsEventListener(this, this.Resize);
  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.minWidth = parseInt(this.options.minWidth);
  this.minHeight = parseInt(this.options.minHeight);
  this.Scale = !!this.options.Scale;
  this.onResize = this.options.onResize;
  this._obj.style.position = "absolute";
 },
 //设置默认属性
 SetOptions: function(options) {
  this.options = {//默认值
   Limit:false,//是否设置限制(为true时下面mx参数有用)
   mxLeft:0,//左边限制
   mxRight:9999,//右边限制
   mxTop:0,//上边限制
   mxBottom:9999,//下边限制
   //为减少难度设置最小宽高
   minWidth:50,//最小宽度
   minHeight:50,//最小高度
   Scale:false,//是否按比例缩放
   onResize:function(){}//缩放时执行
  };
  Extend(this.options, options || {});
 },
 //设置触发对象
 Set: function(resize, side) {
  var resize = $(resize), _fun;
  if(!resize) return;
  //根据方向设置 _fun是缩放时执行的程序
  switch (side.toLowerCase()) {
   case "up" :
   _fun = this.Up;
   break;
   case "down" :
   _fun = this.Down;
   break;
   case "left" :
   _fun = this.Left;
   break;
   case "right" :
   _fun = this.Right;
   break;
   case "left-up" :
   _fun = this.LeftUp;
   break;
   case "right-up" :
   _fun = this.RightUp;
   break;
   case "left-down" :
   _fun = this.LeftDown;
   break;
   case "right-down" :
   default :
   _fun = this.RightDown;
  };
  //设置触发对象
  //resize.style.cursor = _cursor;
  addEventHandler(resize, "mousedown", BindAsEventListener(this, function(e){
   this._fun = _fun; this._touch = resize; this.Start(e);
  }));
 },
 //准备缩放
 Start: function(oEvent, o) {
  //防止冒泡
  if(isIE){ oEvent.cancelBubble = true; } else { oEvent.stopPropagation(); }
  //计算样式初始值
  /////////////////////
  //计算样式初始值
  this.style_width = this._obj.offsetWidth;
  this.style_height = this._obj.offsetHeight;
  this.style_left = this._obj.offsetLeft;
  this.style_top = this._obj.offsetTop;
  this.style_left_width = this.style_width + this.style_left;
  this.style_top_height = this.style_height + this.style_top;
  //计算当前边的对应另一条边的坐标 例如右边缩放时需要左边界坐标
  this._left = oEvent.clientX - this.style_width;
  this._right = oEvent.clientX + this.style_width;
  this._up = oEvent.clientY - this.style_height;
  this._down = oEvent.clientY + this.style_height;
  //设置缩放比例
  if(this.Scale){
   this._scale = this.style_width / this.style_height;
   this._x = this.style_left + this.style_width / 2;
   this._y = this.style_top + this.style_height / 2;
   if(this.Limit){
    this._mxScaleWidth = Math.min((this._x - this.mxLeft), (this.mxRight - this._x)) * 2;
    this._mxScaleHeight = Math.min((this._y - this.mxTop), (this.mxBottom - this._y)) * 2;
   }
  }
  //如果有范围 先计算好范围内最大宽度和高度
  if(this.Limit){
   this._mxRightWidth = this.mxRight - this.style_left;
   this._mxDownHeight = this.mxBottom - this.style_top;
   this.style_top_heightHeight = this.style_height + this.style_top - this.mxTop;
   this.style_left_widthWidth = this.style_width + this.style_left - this.mxLeft;
  };
  //mousemove时缩放 mouseup时停止
  addEventHandler(document, "mousemove", this._fR);
  addEventHandler(document, "mouseup", this._fS);
  if(isIE){
   //焦点丢失
   addEventHandler(this._touch, "losecapture", this._fS);
   //设置鼠标捕获
   this._touch.setCapture();
  }
  else{
   //焦点丢失
   addEventHandler(window, "blur", this._fS);
   //阻止默认动作
   oEvent.preventDefault();
  };
 },  
 //缩放
 Resize: function(e) {
  //没有触发对象的话返回
  if(!this._touch) return;
  //清除选择
  window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  //执行缩放程序
  this._fun(window.event || e);
  //设置样式
  //因为计算用的offset是把边框算进去的所以要减去
  this._obj.style.width = this.style_width - this._xBorder + "px";
  this._obj.style.height = this.style_height - this._yBorder + "px";
  this._obj.style.top = this.style_top + "px";
  this._obj.style.left = this.style_left + "px";
  //附加程序
  this.onResize();
 },
  
  ///////////////////////////////////////////
  
 //绑定程序
 //上边
 Up: function(oEvent) {
  this.RepairY(this._down - oEvent.clientY, this.style_top_heightHeight);
  this.style_top = this.style_top_height - this.style_height;
 },
 //下边
 Down: function(oEvent) {
  this.RepairY(oEvent.clientY - this._up, this._mxDownHeight);
 },   
 //右边
 Right: function(oEvent) {
  this.RepairX(oEvent.clientX - this._left, this._mxRightWidth);
 },
 //左边
 Left: function(oEvent) {
  this.RepairX(this._right - oEvent.clientX, this.style_left_widthWidth);
  this.style_left = this.style_left_width - this.style_width;
 },  
  
 //右边
 RepairY: function(iHeight,mxHeight) {
  iHeight = Math.max(Math.min(iHeight, this.Limit ? mxHeight : iHeight), this.minHeight);
  if(this.Scale){
   var iWidth = parseInt(iHeight * this._scale);
   if(iWidth < this.minWidth || (this.Limit && iWidth > this._mxScaleWidth)){
    iWidth = Math.max(Math.min(iWidth, this.Limit ? this._mxScaleWidth : iWidth), this.minWidth);
    iHeight = parseInt(iWidth / this._scale);
   }
   this.style_width = iWidth;
   this.style_left = this._x - iWidth / 2;
  }
  this.style_height = iHeight;
 },
  
 //右边
 RepairX: function(iWidth,mxWidth) {
  iWidth = Math.max(Math.min(iWidth, this.Limit ? mxWidth : iWidth), this.minWidth);
  if(this.Scale){
   var iHeight = parseInt(iWidth / this._scale);
   if(iHeight < this.minHeight || (this.Limit && iHeight > this._mxScaleHeight)){
    iHeight = Math.max(Math.min(iHeight, this.Limit ? this._mxScaleHeight : iHeight), this.minHeight);
    iWidth = parseInt(iHeight * this._scale);
   }
   this.style_height = iHeight;
   this.style_top = this._y - iHeight / 2;
  }
  this.style_width = iWidth;
 },
  
 //右边
 RightDown: function(oEvent) {
  this.RepairAngle(
   oEvent.clientX - this._left, this._mxRightWidth,
   oEvent.clientY - this._up, this._mxDownHeight
  );
 },
 //右边
 RightUp: function(oEvent) {
  this.RepairAngle(
   oEvent.clientX - this._left, this._mxRightWidth,
   this._down - oEvent.clientY, this.style_top_heightHeight
  );
  this.style_top = this.style_top_height - this.style_height;
 },
  
 //右边
 LeftDown: function(oEvent) {
  this.RepairAngle(
   this._right - oEvent.clientX, this.style_left_widthWidth,
   oEvent.clientY - this._up, this._mxDownHeight
  );
  this.style_left = this.style_left_width - this.style_width;
 },
  
  
 //右边
 LeftUp: function(oEvent) {
  this.RepairAngle(
   this._right - oEvent.clientX, this.style_left_widthWidth,
   this._down - oEvent.clientY, this.style_top_heightHeight
  );
  this.style_top = this.style_top_height - this.style_height;
  this.style_left = this.style_left_width - this.style_width;
 },
  
 //右边
 RepairAngle: function(iWidth,mxWidth,iHeight,mxHeight) {
   iWidth = Math.max(Math.min(iWidth, this.Limit ? mxWidth : iWidth), this.minWidth);
   iHeight = this.Scale ? parseInt(iWidth / this._scale) : iHeight;
   if(iHeight < this.minHeight || (this.Limit && iHeight > mxHeight)){
   iHeight = Math.max(Math.min(iHeight, this.Limit ? mxHeight : iHeight), this.minHeight);
   this.Scale && (iWidth = parseInt(iHeight * this._scale));
  }
  this.style_width = iWidth;
  this.style_height = iHeight;
 },
  
  
  //////////////////////////////////////////
  ////////////////////////////////////////////////
  
 //停止缩放
 Stop: function() {
  //移除事件
  removeEventHandler(document, "mousemove", this._fR);
  removeEventHandler(document, "mouseup", this._fS);
  if(isIE){
   removeEventHandler(this._touch, "losecapture", this._fS);
   this._touch.releaseCapture();
  }
  else{
   removeEventHandler(window, "blur", this._fS);
  }
  this._touch = null;
 }
};
</script>
<style type="text/css">
#rRightDown,#rLeftDown,#rLeftUp,#rRightUp,#rRight,#rLeft,#rUp,#rDown{position:absolute;background:#F00;10px; height:10px; z-index:500; font-size:0;}
#rRightDown{cursor:nw-resize;}
#rLeftDown{cursor:ne-resize;}
#rLeftUp{cursor:nw-resize;}
#rRightUp{cursor:ne-resize;}
#rRight,#rLeft{cursor:e-resize;}
#rUp,#rDown{cursor:n-resize;}
#dragDiv{border:1px solid #000000; 100px; height:60px; top:50px; left:50px; background:#fff;}
</style>
<div id="bgDiv" style="600px; height:300px; border:10px solid #666666; position:relative;">
        <div id="dragDiv">
          <div id="rRightDown" style="right:0; bottom:0;"> </div>
          <div id="rLeftDown" style="left:0; bottom:0;"> </div>
          <div id="rRightUp" style="right:0; top:0;"> </div>
          <div id="rLeftUp" style="left:0; top:0;"> </div>
          <div id="rRight" style="right:0; top:50%;margin-top:-5px;"> </div>
          <div id="rLeft" style="left:0; top:50%;margin-top:-5px;"> </div>
          <div id="rUp" style="top:0; left:50%;margin-left:-5px;"> </div>
          <div id="rDown" style="bottom:0;left:50%;margin-left:-5px;"></div>
        </div>
      </div>
      <input id="idScale" type="button" value="设置比例" />
<div id="aa"></div>
<script>
var _resize = new Resize("dragDiv", { Limit: true });
_resize.Set("rRightDown", "right-down");
_resize.Set("rLeftDown", "left-down");
_resize.Set("rRightUp", "right-up");
_resize.Set("rLeftUp", "left-up");
_resize.Set("rRight", "right");
_resize.Set("rLeft", "left");
_resize.Set("rUp", "up");
_resize.Set("rDown", "down");
_resize.mxRight = 600;
_resize.mxBottom = 300;
$("idScale").onclick = function(){
if(_resize.Scale){
this.value = "设置比例";
_resize.Scale = false;
}else{
this.value = "取消比例";
_resize.Scale = true;
}
}
var drag = new Drag("dragDiv", {mxContainer: "bgDiv", Limit: true});
</script>
</body>
</html>
原文地址:https://www.cnblogs.com/duanxz/p/2932192.html