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 相关文章推荐
关于图片验证码设计的思考
Jan 29 Javascript
js实现iframe动态调整高度的代码
Jan 06 Javascript
extjs 学习笔记 四 带分页的grid
Oct 20 Javascript
JavaScript DOM 学习第三章 内容表格
Feb 19 Javascript
Jquery中的层次选择器与find()的区别示例介绍
Feb 20 Javascript
jquery高级编程的最佳实践详解
Mar 23 Javascript
JS中split()用法(将字符串按指定符号分割成数组)
Oct 24 Javascript
深入理解jQuery.data() 的实现方式
Nov 30 Javascript
js实现做通讯录的索引滑动显示效果和滑动显示锚点效果
Feb 18 Javascript
vue-router重定向和路由别名的使用讲解
Jan 19 Javascript
async/await优雅的错误处理方法总结
Jan 30 Javascript
js+css实现全屏侧边栏
Jun 16 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
咖啡语言
2021/03/03 咖啡文化
利用PHP制作简单的内容采集器的原理分析
2008/10/01 PHP
php实现天干地支计算器示例
2014/03/14 PHP
PHP+jquery实时显示网站在线人数的方法
2015/01/04 PHP
JS控制表格隔行变色
2006/06/26 Javascript
JS location几个方法小姐
2008/07/09 Javascript
JavaScript DOM学习第四章 getElementByTagNames
2010/02/19 Javascript
获取css样式表内样式的js函数currentStyle(IE),defaultView(FF)
2011/02/14 Javascript
分页栏的web标准实现
2011/11/01 Javascript
一个支持任意尺寸的图片上下左右滑动效果
2014/08/24 Javascript
JQuery中ajax方法访问web服务实例
2015/07/18 Javascript
jQuery实现网页抖动的菜单抖动效果
2015/08/07 Javascript
详解Backbone.js框架中的模型Model与其集合collection
2016/05/05 Javascript
基于BootStrap的图片轮播效果展示实例代码
2016/05/23 Javascript
BootStrap智能表单实战系列(三)分块表单配置详解
2016/06/13 Javascript
js date 格式化
2017/02/15 Javascript
详解Webpack实战之构建 Electron 应用
2017/12/25 Javascript
JS原型和原型链原理与用法实例详解
2020/02/05 Javascript
Openlayers学习之加载鹰眼控件
2020/09/28 Javascript
[01:01:51]EG vs VG Supermajor小组赛B组 BO3 第二场 6.2
2018/06/03 DOTA
python定时器(Timer)用法简单实例
2015/06/04 Python
Python实现复杂对象转JSON的方法示例
2017/06/22 Python
Python列表(List)知识点总结
2019/02/18 Python
python 实现二维列表转置
2019/12/02 Python
Python使用turtle库绘制小猪佩奇(实例代码)
2020/01/16 Python
Python实现AES加密,解密的两种方法
2020/10/03 Python
用python写一个带有gui界面的密码生成器
2020/11/06 Python
简单几步用纯CSS3实现3D翻转效果
2019/01/17 HTML / CSS
HTML5的结构和语义(5):内嵌媒体
2008/10/17 HTML / CSS
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
中科方德软件测试面试题
2016/04/21 面试题
网络管理员岗位职责
2015/02/12 职场文书
医学生自荐信范文
2015/03/05 职场文书
想创业成功,需要掌握这些要点
2019/12/06 职场文书
SpringBoot实现quartz定时任务可视化管理功能
2021/08/30 Java/Android
Redis 报错 error:NOAUTH Authentication required
2022/05/15 Redis