JavaScript实现选择框按比例拖拉缩放的方法


Posted in Javascript onAugust 04, 2015

本文实例讲述了JavaScript实现选择框按比例拖拉缩放的方法。分享给大家供大家参考。具体如下:

这里通过javascript实现可以像PS一样拉出一个选择框的效果。里面的很多方法都是我们值得学习的。

运行效果如下图所示:

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>JavaScript拖拉缩放效果</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) {
  var args = Array.prototype.slice.call(arguments).slice(2);
  return function(event) {
    return fun.apply(object, [event || window.event].concat(args));
  }
}
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 Resize = Class.create();
Resize.prototype = {
//缩放对象
initialize: function(obj, options) {
  this._obj = $(obj);//缩放对象  
  this._styleWidth = this._styleHeight = this._styleLeft = this._styleTop = 0;//样式参数
  this._sideRight = this._sideDown = this._sideLeft = this._sideUp = 0;//坐标参数
  this._fixLeft = this._fixTop = 0;//定位参数
  this._scaleLeft = this._scaleTop = 0;//定位坐标
  this._mxSet = function(){};//范围设置程序
  this._mxRightWidth = this._mxDownHeight = this._mxUpHeight = this._mxLeftWidth = 0;//范围参数
  this._mxScaleWidth = this._mxScaleHeight = 0;//比例范围参数
  this._fun = function(){};//缩放执行程序
  //获取边框宽度
  var _style = CurrentStyle(this._obj);
  this._borderX = (parseInt(_style.borderLeftWidth) || 0) + (parseInt(_style.borderRightWidth) || 0);
  this._borderY = (parseInt(_style.borderTopWidth) || 0) + (parseInt(_style.borderBottomWidth) || 0);
  //事件对象(用于绑定移除事件)
  this._fR = BindAsEventListener(this, this.Resize);
  this._fS = Bind(this, this.Stop);
  this.SetOptions(options);
  //范围限制
  this.Max = !!this.options.Max;
  this._mxContainer = $(this.options.mxContainer) || null;
  this.mxLeft = Math.round(this.options.mxLeft);
  this.mxRight = Math.round(this.options.mxRight);
  this.mxTop = Math.round(this.options.mxTop);
  this.mxBottom = Math.round(this.options.mxBottom);
  //宽高限制
  this.Min = !!this.options.Min;
  this.minWidth = Math.round(this.options.minWidth);
  this.minHeight = Math.round(this.options.minHeight);
  //按比例缩放
  this.Scale = !!this.options.Scale;
  this.Ratio = Math.max(this.options.Ratio, 0);
  this.onResize = this.options.onResize;
  this._obj.style.position = "absolute";
  !this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
 },
 //设置默认属性
 SetOptions: function(options) {
 this.options = {//默认值
    Max:    false,//是否设置范围限制(为true时下面mx参数有用)
    mxContainer:"",//指定限制在容器内
    mxLeft:    0,//左边限制
    mxRight:  9999,//右边限制
    mxTop:    0,//上边限制
    mxBottom:  9999,//下边限制
    Min:    false,//是否最小宽高限制(为true时下面min参数有用)
    minWidth:  50,//最小宽度
    minHeight:  50,//最小高度
    Scale:    false,//是否按比例缩放
    Ratio:    0,//缩放比例(宽/高)
    onResize:  function(){}//缩放时执行
 };
 Extend(this.options, options || {});
 },
 //设置触发对象
 Set: function(resize, side) {
  var resize = $(resize), fun;
  if(!resize) return;
  //根据方向设置
  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;
  };
  //设置触发对象
  addEventHandler(resize, "mousedown", BindAsEventListener(this, this.Start, fun));
 },
 //准备缩放
 Start: function(e, fun, touch) {  
  //防止冒泡(跟拖放配合时设置)
  e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true);
  //设置执行程序
  this._fun = fun;
  //样式参数值
  this._styleWidth = this._obj.clientWidth;
  this._styleHeight = this._obj.clientHeight;
  this._styleLeft = this._obj.offsetLeft;
  this._styleTop = this._obj.offsetTop;
  //四条边定位坐标
  this._sideLeft = e.clientX - this._styleWidth;
  this._sideRight = e.clientX + this._styleWidth;
  this._sideUp = e.clientY - this._styleHeight;
  this._sideDown = e.clientY + this._styleHeight;
  //top和left定位参数
  this._fixLeft = this._styleLeft + this._styleWidth;
  this._fixTop = this._styleTop + this._styleHeight;
  //缩放比例
  if(this.Scale){
    //设置比例
    this.Ratio = Math.max(this.Ratio, 0) || this._styleWidth / this._styleHeight;
    //left和top的定位坐标
    this._scaleLeft = this._styleLeft + this._styleWidth / 2;
    this._scaleTop = this._styleTop + this._styleHeight / 2;
  };
  //范围限制
  if(this.Max){
    //设置范围参数
    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);
    };
    //根据最小值再修正
    mxRight = Math.max(mxRight, mxLeft + (this.Min ? this.minWidth : 0) + this._borderX);
    mxBottom = Math.max(mxBottom, mxTop + (this.Min ? this.minHeight : 0) + this._borderY);
    //由于转向时要重新设置所以写成function形式
    this._mxSet = function(){
      this._mxRightWidth = mxRight - this._styleLeft - this._borderX;
      this._mxDownHeight = mxBottom - this._styleTop - this._borderY;
      this._mxUpHeight = Math.max(this._fixTop - mxTop, this.Min ? this.minHeight : 0);
      this._mxLeftWidth = Math.max(this._fixLeft - mxLeft, this.Min ? this.minWidth : 0);
    };
    this._mxSet();
    //有缩放比例下的范围限制
    if(this.Scale){
      this._mxScaleWidth = Math.min(this._scaleLeft - mxLeft, mxRight - this._scaleLeft - this._borderX) * 2;
      this._mxScaleHeight = Math.min(this._scaleTop - mxTop, mxBottom - this._scaleTop - this._borderY) * 2;
    };
  };
  //mousemove时缩放 mouseup时停止
  addEventHandler(document, "mousemove", this._fR);
  addEventHandler(document, "mouseup", this._fS);
  if(isIE){
    addEventHandler(this._obj, "losecapture", this._fS);
    this._obj.setCapture();
  }else{
    addEventHandler(window, "blur", this._fS);
    e.preventDefault();
  };
 },
 //缩放
 Resize: function(e) {
  //清除选择
  window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
  //执行缩放程序
  this._fun(e);
  //设置样式,变量必须大于等于0否则ie出错
  with(this._obj.style){
    width = this._styleWidth + "px"; height = this._styleHeight + "px";
    top = this._styleTop + "px"; left = this._styleLeft + "px";
  }
  //附加程序
  this.onResize();
 },
 //缩放程序
 //上
 Up: function(e) {
  this.RepairY(this._sideDown - e.clientY, this._mxUpHeight);
  this.RepairTop();
  this.TurnDown(this.Down);
 },
 //下
 Down: function(e) {
  this.RepairY(e.clientY - this._sideUp, this._mxDownHeight);
  this.TurnUp(this.Up);
 },
 //右
 Right: function(e) {
  this.RepairX(e.clientX - this._sideLeft, this._mxRightWidth);
  this.TurnLeft(this.Left);
 },
 //左
 Left: function(e) {
  this.RepairX(this._sideRight - e.clientX, this._mxLeftWidth);
  this.RepairLeft();
  this.TurnRight(this.Right);
 },
 //右下
 RightDown: function(e) {
  this.RepairAngle(
    e.clientX - this._sideLeft, this._mxRightWidth,
    e.clientY - this._sideUp, this._mxDownHeight
  );
  this.TurnLeft(this.LeftDown) || this.Scale || this.TurnUp(this.RightUp);
 },
 //右上
 RightUp: function(e) {
  this.RepairAngle(
    e.clientX - this._sideLeft, this._mxRightWidth,
    this._sideDown - e.clientY, this._mxUpHeight
  );
  this.RepairTop();
  this.TurnLeft(this.LeftUp) || this.Scale || this.TurnDown(this.RightDown);
 },
 //左下
 LeftDown: function(e) {
  this.RepairAngle(
    this._sideRight - e.clientX, this._mxLeftWidth,
    e.clientY - this._sideUp, this._mxDownHeight
  );
  this.RepairLeft();
  this.TurnRight(this.RightDown) || this.Scale || this.TurnUp(this.LeftUp);
 },
 //左上
 LeftUp: function(e) {
  this.RepairAngle(
    this._sideRight - e.clientX, this._mxLeftWidth,
    this._sideDown - e.clientY, this._mxUpHeight
  );
  this.RepairTop(); this.RepairLeft();
  this.TurnRight(this.RightUp) || this.Scale || this.TurnDown(this.LeftDown);
 },
 //水平方向
 RepairX: function(iWidth, mxWidth) {
  iWidth = this.RepairWidth(iWidth, mxWidth);
  if(this.Scale){
    var iHeight = this.RepairScaleHeight(iWidth);
    if(this.Max && iHeight > this._mxScaleHeight){
      iHeight = this._mxScaleHeight;
      iWidth = this.RepairScaleWidth(iHeight);
    }else if(this.Min && iHeight < this.minHeight){
      var tWidth = this.RepairScaleWidth(this.minHeight);
      if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
    }
    this._styleHeight = iHeight;
    this._styleTop = this._scaleTop - iHeight / 2;
  }
  this._styleWidth = iWidth;
 },
 //垂直方向
 RepairY: function(iHeight, mxHeight) {
  iHeight = this.RepairHeight(iHeight, mxHeight);
  if(this.Scale){
    var iWidth = this.RepairScaleWidth(iHeight);
    if(this.Max && iWidth > this._mxScaleWidth){
      iWidth = this._mxScaleWidth;
      iHeight = this.RepairScaleHeight(iWidth);
    }else if(this.Min && iWidth < this.minWidth){
      var tHeight = this.RepairScaleHeight(this.minWidth);
      if(tHeight < mxHeight){ iWidth = this.minWidth; iHeight = tHeight; }
    }
    this._styleWidth = iWidth;
    this._styleLeft = this._scaleLeft - iWidth / 2;
  }
  this._styleHeight = iHeight;
 },
 //对角方向
 RepairAngle: function(iWidth, mxWidth, iHeight, mxHeight) {
  iWidth = this.RepairWidth(iWidth, mxWidth);  
  if(this.Scale){
    iHeight = this.RepairScaleHeight(iWidth);
    if(this.Max && iHeight > mxHeight){
      iHeight = mxHeight;
      iWidth = this.RepairScaleWidth(iHeight);
    }else if(this.Min && iHeight < this.minHeight){
      var tWidth = this.RepairScaleWidth(this.minHeight);
      if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
    }
  }else{
    iHeight = this.RepairHeight(iHeight, mxHeight);
  }
  this._styleWidth = iWidth;
  this._styleHeight = iHeight;
 },
 //top
 RepairTop: function() {
  this._styleTop = this._fixTop - this._styleHeight;
 },
 //left
 RepairLeft: function() {
  this._styleLeft = this._fixLeft - this._styleWidth;
 },
 //height
 RepairHeight: function(iHeight, mxHeight) {
  iHeight = Math.min(this.Max ? mxHeight : iHeight, iHeight);
  iHeight = Math.max(this.Min ? this.minHeight : iHeight, iHeight, 0);
  return iHeight;
 },
 //width
 RepairWidth: function(iWidth, mxWidth) {
  iWidth = Math.min(this.Max ? mxWidth : iWidth, iWidth);
  iWidth = Math.max(this.Min ? this.minWidth : iWidth, iWidth, 0);
  return iWidth;
 },
 //比例高度
 RepairScaleHeight: function(iWidth) {
  return Math.max(Math.round((iWidth + this._borderX) / this.Ratio - this._borderY), 0);
 },
 //比例宽度
 RepairScaleWidth: function(iHeight) {
  return Math.max(Math.round((iHeight + this._borderY) * this.Ratio - this._borderX), 0);
 },
 //转向程序
 //转右
 TurnRight: function(fun) {
  if(!(this.Min || this._styleWidth)){
    this._fun = fun;
    this._sideLeft = this._sideRight;
    this.Max && this._mxSet();
    return true;
  }
 },
 //转左
 TurnLeft: function(fun) {
  if(!(this.Min || this._styleWidth)){
    this._fun = fun;
    this._sideRight = this._sideLeft;
    this._fixLeft = this._styleLeft;
    this.Max && this._mxSet();
    return true;
  }
 },
 //转上
 TurnUp: function(fun) {
  if(!(this.Min || this._styleHeight)){
    this._fun = fun;
    this._sideDown = this._sideUp;
    this._fixTop = this._styleTop;
    this.Max && this._mxSet();
    return true;
  }
 },
 //转下
 TurnDown: function(fun) {
  if(!(this.Min || this._styleHeight)){
    this._fun = fun;
    this._sideUp = this._sideDown;
    this.Max && this._mxSet();
    return true;
  }
 },
 //停止缩放
 Stop: function() {
  removeEventHandler(document, "mousemove", this._fR);
  removeEventHandler(document, "mouseup", this._fS);
  if(isIE){
    removeEventHandler(this._obj, "losecapture", this._fS);
    this._obj.releaseCapture();
  }else{
    removeEventHandler(window, "blur", this._fS);
  }
 }
};
</script>
<style type="text/css">
#rRightDown,#rLeftDown,#rLeftUp,#rRightUp,#rRight,#rLeft,#rUp,#rDown{
  position:absolute;
  background:#C00;
  width:7px;
  height:7px;
  z-index:5;
  font-size:0;
}
#rLeftDown,#rRightUp{cursor:ne-resize;}
#rRightDown,#rLeftUp{cursor:nw-resize;}
#rRight,#rLeft{cursor:e-resize;}
#rUp,#rDown{cursor:n-resize;}
#rLeftDown{left:-4px;bottom:-4px;}
#rRightUp{right:-4px;top:-4px;}
#rRightDown{right:-4px;bottom:-4px;background-color:#00F;}
#rLeftUp{left:-4px;top:-4px;}
#rRight{right:-4px;top:50%;margin-top:-4px;}
#rLeft{left:-4px;top:50%;margin-top:-4px;}
#rUp{top:-4px;left:50%;margin-left:-4px;}
#rDown{bottom:-4px;left:50%;margin-left:-4px;}
#bgDiv{width:600px; height:300px; border:10px solid #666666; position:relative;}
#dragDiv{border:1px solid #000000; width:100px; height:60px; top:50px; left:50px; background:#fff;}
</style>
<div id="bgDiv">
 <div id="dragDiv">
 <div id="rRightDown"> </div>
 <div id="rLeftDown"> </div>
 <div id="rRightUp"> </div>
 <div id="rLeftUp"> </div>
 <div id="rRight"> </div>
 <div id="rLeft"> </div>
 <div id="rUp"> </div>
 <div id="rDown"></div>
 </div>
</div>
<input id="idScale" type="button" value="设置比例" />
<input id="idMin" type="button" value="设置最小范围" />
<script>
var rs = new Resize("dragDiv", { Max: true, mxContainer: "bgDiv" });
rs.Set("rRightDown", "right-down");
rs.Set("rLeftDown", "left-down");
rs.Set("rRightUp", "right-up");
rs.Set("rLeftUp", "left-up");
rs.Set("rRight", "right");
rs.Set("rLeft", "left");
rs.Set("rUp", "up");
rs.Set("rDown", "down");
$("idScale").onclick = function(){
  if(rs.Scale){
    this.value = "设置比例";
    rs.Scale = false;
  }else{
    this.value = "取消比例";
    rs.Ratio = 0;
    rs.Scale = true;
  }
}
$("idMin").onclick = function(){
  if(rs.Min){
    this.value = "设置最小范围";
    rs.Min = false;
  }else{
    this.value = "取消最小范围";
    rs.Min = true;
  }
}
</script>
</body>
</html>

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

Javascript 相关文章推荐
File文件控件,选中文件(图片,flash,视频)即立即预览显示
Apr 09 Javascript
javascript 一些用法小结
Sep 11 Javascript
BOM与DOM的区别分析
Oct 26 Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
Oct 29 Javascript
js格式化时间的简单实例
Nov 27 Javascript
Bootstrap中data-target 到底是什么
Feb 14 Javascript
js数字计算 误差问题的快速解决方法
Feb 28 Javascript
AngularJS中的拦截器实例详解
Apr 07 Javascript
解决JS外部文件中文注释出现乱码问题
Jul 09 Javascript
基于vue-cli3和element实现登陆页面
Nov 13 Javascript
解决vue项目运行npm run serve报错的问题
Oct 26 Javascript
elementUI同一页面展示多个Dialog的实现
Nov 19 Javascript
Javascript实现可旋转的圆圈实例代码
Aug 04 #Javascript
JavaScript数组各种常见用法实例分析
Aug 04 #Javascript
基于Jquery实现表单验证
Jul 20 #Javascript
javascript+HTML5的canvas实现七夕情人节3D玫瑰花效果代码
Aug 04 #Javascript
jq实现左侧显示图片右侧文字滑动切换效果
Aug 04 #Javascript
javascript控制图片播放的实现代码
Jul 29 #Javascript
两种JS实现屏蔽鼠标右键的方法
Aug 20 #Javascript
You might like
php smarty模版引擎中的缓存应用
2009/12/02 PHP
PHP验证码函数代码(简单实用)
2013/09/29 PHP
Thinkphp 框架基础之入口文件功能、定义与用法分析
2020/04/27 PHP
HTML页面如何象ASP一样接受参数
2007/02/07 Javascript
一个用js实现控制台控件的代码
2007/09/04 Javascript
js类中的公有变量和私有变量
2008/07/24 Javascript
JQuery对id中含有特殊字符的转义处理示例
2013/09/06 Javascript
jquery如何获取复选框的值
2013/12/12 Javascript
Javascript 按位与赋值运算符 (&amp;=)使用介绍
2014/02/04 Javascript
arguments对象验证函数的参数是否合法
2015/06/26 Javascript
详解Node.js模块间共享数据库连接的方法
2016/05/24 Javascript
老生常谈JQuery data方法的使用
2016/09/09 Javascript
jQuery如何防止Ajax重复提交
2016/10/14 Javascript
js阻止冒泡和默认事件(默认行为)详解
2016/10/20 Javascript
loading动画特效小结
2017/01/22 Javascript
JavaScript在form表单中使用button按钮实现submit提交方法
2017/01/23 Javascript
利用C/C++编写node.js原生模块的方法教程
2017/07/07 Javascript
微信小程序如何使用canvas二维码保存至手机相册
2019/07/15 Javascript
[02:38]DOTA2超级联赛专访Loda 认为IG世界最强
2013/05/27 DOTA
[01:30]我们共输赢 完美世界城市挑战赛开启全新赛季
2019/04/19 DOTA
python spyder中读取txt为图片的方法
2018/04/27 Python
Python反爬虫技术之防止IP地址被封杀的讲解
2019/01/09 Python
Python中的random.uniform()函数教程与实例解析
2019/03/02 Python
OpenCV HSV颜色识别及HSV基本颜色分量范围
2019/03/22 Python
keras实现调用自己训练的模型,并去掉全连接层
2020/06/09 Python
详解Python中的编码问题(encoding与decode、str与bytes)
2020/09/30 Python
在线服装零售商:SheIn
2016/07/22 全球购物
Lookfantastic台湾:英国彩妆美发保养购物网
2018/03/26 全球购物
Otticanet意大利:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
中文专业毕业生自荐信
2013/10/28 职场文书
安全生产责任书
2014/03/12 职场文书
抽奖活动主持词
2014/03/31 职场文书
《故都的秋》教学反思
2014/04/15 职场文书
2014银行领导班子群众路线对照检查材料思想汇报
2014/09/17 职场文书
2016年小学感恩节活动总结
2016/04/01 职场文书
在HTML5 localStorage中存储对象的示例代码
2021/04/21 Javascript