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 相关文章推荐
初窥JQuery(二)事件机制(2)
Dec 06 Javascript
JavaScript高级程序设计 DOM学习笔记
Sep 10 Javascript
js固定DIV高度,超出部分自动添加滚动条的简单方法
Jul 10 Javascript
javascript禁制后退键(Backspace)实例代码
Nov 15 Javascript
基于Arcgis for javascript实现百度地图ABCD marker的效果
Sep 12 Javascript
JQuery Mobile 弹出式登录框的实现方法
May 28 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
Jun 24 Javascript
利用JS提交表单的几种方法和验证(必看篇)
Sep 17 Javascript
js实现登录与注册界面
Nov 01 Javascript
使用webpack打包koa2 框架app
Feb 02 Javascript
vue两组件间值传递 $router.push实现方法
May 15 Javascript
简单了解前端渐进式框架VUE
Jul 20 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分页显示制作详细讲解
2008/11/19 PHP
PHP实现的限制IP投票程序IP来源分析
2016/05/04 PHP
基于PHP实现栈数据结构和括号匹配算法示例
2017/08/10 PHP
PHP使用GD库制作验证码的方法(点击验证码或看不清会刷新验证码)
2017/08/15 PHP
Thinkphp 在api开发中异常返回依然是html的解决方式
2019/10/16 PHP
php下的原生ajax请求用法实例分析
2020/02/28 PHP
Thinkphp 框架扩展之驱动扩展实例分析
2020/04/27 PHP
JQuery 绑定事件时传递参数的实现方法
2009/10/13 Javascript
JavaScript(JS) 压缩 / 混淆 / 格式化 批处理工具
2010/12/10 Javascript
jquery下checked取值问题的解决方法
2012/08/09 Javascript
jQuery实现点击文本框弹出热门标签的提示效果
2013/11/17 Javascript
JQuery教学之性能优化
2014/05/14 Javascript
用简洁的jQuery方法toggleClass实现隔行换色
2014/10/22 Javascript
AngularJS中取消对HTML片段转义的方法例子
2015/01/04 Javascript
jQuery实现“扫码阅读”功能
2015/01/21 Javascript
JavaScript 匿名函数和闭包介绍
2015/04/13 Javascript
基于JavaScript实现文字超出部分隐藏
2016/02/29 Javascript
ES2015 Symbol 一种绝不重复的值
2016/12/25 Javascript
web.js.字符串与正则表达式操作
2017/05/13 Javascript
nuxt+axios解决前后端分离SSR的示例代码
2017/10/24 Javascript
Vue2.0 slot分发内容与props验证的方法
2017/12/12 Javascript
element-ui table组件如何使用render属性的实现
2019/11/04 Javascript
微信小程序如何获取地址
2019/12/24 Javascript
jQuery HTML获取内容和属性操作实例分析
2020/05/20 jQuery
vue项目使用$router.go(-1)返回时刷新原来的界面操作
2020/07/26 Javascript
VUE : vue-cli中去掉路由中的井号#操作
2020/09/04 Javascript
[47:18]完美世界DOTA2联赛循环赛 IO vs FTD BO2第一场 11.05
2020/11/06 DOTA
通过mod_python配置运行在Apache上的Django框架
2015/07/22 Python
Python结合ImageMagick实现多张图片合并为一个pdf文件的方法
2018/04/24 Python
Django rest framework工具包简单用法示例
2018/07/20 Python
python pytest进阶之xunit fixture详解
2019/06/27 Python
python内打印变量之%和f的实例
2020/02/19 Python
业务部主管岗位职责
2014/01/29 职场文书
中学教师请假制度
2014/02/03 职场文书
优秀电子工程系毕业生求职信
2014/05/24 职场文书
pytorch 中nn.Dropout的使用说明
2021/05/20 Python