JavaScript 拖拉缩放效果
拖拉缩放效果,实现通过鼠标拖动来调整层的面积(宽高)大小。例如选框效果。 这里的拖拉缩放比一般的选框复杂一点,能设置八个方位(方向)的固定触发点,能设置最小范围,最大范围和比例缩放。 跟拖放效果一样,程序的原型也是在做图片切割效果的时候做出来的。但这个效果的参考少的多,基本上靠自己摸索,走了不少弯路,现在总算把自己想要的效果做出来了,程序跟上一个版本比较也已经“面目全非”,还是觉得有很多需要改进的地方,就像永远没有最完美的土耳其地毯。 这里也有一个简化版的SimpleResize,方便学习。 效果预览 程序说明 其中用到的鼠标捕获、清除选择等,在拖放效果中有说明的这里就略过。下面以SimpleResize为例说一下基本原理。 【程序原理】 程序需要用Set来添加触发对象(就是用来拖拉的对象,详细看使用说明),主要是设置mousedown事件来触发Start程序开始缩放。 Start程序主要用来设置缩放程序_fun和缩放需要的参数,最后设置mousemove事件触发Resize程序进行缩放,mouseup事件中执行取消缩放Stop程序。 Resize程序的任务是执行缩放程序_fun和设置整理后的样式,这里为了简化程序样式是全部一起设置的,这样程序的注意流程就完成了。 ps:设置样式的值必须是大于0的数,否则ie会报错。 下面说说缩放的原理,先以右边拖拉为例,右边拖拉一般是以左边为固定点,右边进行缩放。 首先记录左边定位参数_sideLeft: this._sideLeft = e.clientX - this._styleWidth; 在拖拉时,就可以根据这个参照值计算拖拉后要设置的样式参数_styleWidth: this._styleWidth = Math.max(e.clientX - this._sideLeft, 0); 上面的程序能保证样式是大于等于0的数。 至于左边就麻烦一点,因为左边拖拉是以右边为固定点,这就必须在设置宽度的同时设置left才能,保证右边固定。 首先记录右边定位参数_sideRight: this._sideRight = e.clientX + this._styleWidth; 还有left的定位参数_fixLeft: this._fixLeft = this._styleWidth + this._styleLeft; 在拖拉时,计算_styleWidth: this._styleWidth = Math.max(this._sideRight - e.clientX, 0); 在根据_styleWidth设置_styleLeft: this._styleLeft = this._fixLeft - this._styleWidth; 上下同理,至于斜角的四个方向只是同时执行两个方向,例如右下就是同时执行右边和下边: this.Right(e); this.Down(e); 【程序结构】 在更详细的程序说明之前,先了解一下程序结构。 当点击触发点,就会根据设置给缩放程序_fun设置为八个方向的缩放程序的其中一个。 八个缩放程序分别是:Up(上)、Down(下)、Right(右)、Left(左)、RightDown(右下)、RightUp(右上)、LeftDown(左下)和LeftUp(左上)。 在这些缩放程序,首先会进行宽和高的设置,由于宽和高的设置还需要经过范围限制和比例缩放的修正,而这些会在修正程序中处理。 修正程序包括几个部分: RepairX:水平方向修正(左右方向); RepairY:垂直方向修正(上下方向); RepairAngle:对角方向修正(右下、右上、左下、左上); RepairTop:top修正(用于以右边为固定点定位); RepairLeft:left修正(用于以下边为固定点定位); RepairHeight:高度修正; RepairWidth:宽度修正。 如果没有设置最小范围限制,当缩放超过定位边时就会自动转向,例如右边缩放,左边定位,当拖动到左边定位的左边时,就会切换成左边缩放,右边定位,而这个切换是在转向程序中进行的。 转向程序包括几个部分: TurnRight:右转程序; TurnLeft:左转程序; TurnUp:上转程序; TurnDown:下转程序。 基本结构了解后,下面就开始介绍程序细节。 【最小范围限制】 最小范围限制就是限制缩放的宽和高,程序中把Min设为true,就可以通过minWidth和minHeight属性进行限制。 单是限制很简单,只要超过限制就把值设成限制值就行了,这个主要是在修正程序RepairHeight和RepairWidth中修正: 例如RepairWidth中: iWidth = Math.max(this.Min ? this.minWidth : iWidth, iWidth, 0); 注意这里带了个0,保证最小值大于等于0。 【最大范围限制】 最大范围限制,复杂一点,是固定一个(矩形)范围,然后把缩放限制在范围内。 这个范围限制跟拖放效果的类似,有四个范围属性:上(mxTop)、下(mxBottom)、左(mxLeft)、右(mxRight)。 程序中把Max设为true就可以设置。 然后根据这四个范围属性设置四个范围参数,_mxRightWidth、_mxDownHeight、_mxUpHeight和_mxLeftWidth。 这四个围参数代表的是相对于定位边的最大宽度或高度,例如_mxRightWidth就是当右边缩放时(左边固定),宽度可以设置的最大值: this._mxRightWidth = Math.max(mxRight - this._styleLeft - this._borderX, this.Min ? this.minWidth : 0); 这里要小心的是不要把边框忽略了。 然后在Right缩放程序中,把这个参数传递给RepairX,而RepairX把参数传递给RepairWidth并在里面修正宽度: iWidth = Math.min(this.Max ? mxWidth : iWidth, iWidth); 还有容器范围限制,这个跟拖放效果的差不多,这里就不重复了。此外在Start程序中还会对异常的范围参数进行修正,不过这里考虑的不多,估计并不很完善,最好还是不要设一些奇怪的参数。 【比例缩放】 比例缩放就是缩放的时候同时设置宽和高,使用宽和高按照一定的比例显示。 程序中把Scale设为true就可以启用,并且Ratio可以设置比例大小(宽/高),如果不设置的话就会自动取当前的宽/高比例。 对于对角方向,在比例缩放的情况下宽和高就不能同时设置,而必须有一个优先另一个参照比例设置了。 这个要注意,否则很容易进入死胡同。RepairAngle修正程序中就是宽度优先的,高度再按比例修正(参考代码)。 而左右上下四个方向,是以缩放对象对称轴为中心缩放的。 以左右方向为例,要实现这个效果,首先在Start程序中设置中心定位坐标_scaleTop: this._scaleTop = this._styleTop + this._styleHeight / 2; 当修正好高之后,再用这个坐标设置_styleTop值: this._styleTop = this._scaleTop - iHeight / 2; 其实就是设置高之后再修正top,使缩放之后的缩放对象中心的水平坐标保持不变,就做出以缩放对象的水平对称轴为中心的缩放了。 还有两个比例设置程序RepairScaleHeight和RepairScaleWidth,在这两个程序分别按比例设置高和宽。 这里必须留意一个问题,程序在计算样式参数的时候,是不计算边框的,但比例计算时应该把边框算进去。 例如RepairScaleHeight程序中: return Math.max(Math.round((iWidth + this._borderX) / this.Ratio - this._borderY), 0); 注意,因为这样计算的结果可能会小于0,所以用Math.max保证结果大于0(上面已经说了样式值必须大于0)。 【范围限制下的比例缩放】 一般的比例缩放很简单,在宽或高取值之后,按比例设置另一个值就行了。 但如果有了范围限制有可能按比例缩放后,就超过范围限制了。 如果只考虑最大范围限制的话,可以再修正,每次修正的范围会越来越小,没有问题。 但加上最小范围限制,就可能这边已经到了最小范围了,但另一边还在最大范围限制之外了。 这个时候就必须小心细心处理了,当两个范围限制发生冲突时,要放弃其中一个,程序中是优先考虑最大范围限制,放弃最小范围限制,这个看起来没什么但如果思想转不过来,就很容易钻入死胡同去了(经验教训T_T)。 例如用宽度和RepairScaleHeight程序已经获得了高的值iHeight,可以这样设置宽和高: Code 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; } } 说明一下这段代码: 首先判断iHeight是否超过最大值,是的话就根据最大值设置宽和高,由于优先考虑最大范围所以宽是否超过最小范围就不用再考虑了; 如果没有超过最大值,再判断是否小于最小值,是的话用高度最小值和RepairScaleWidth程序取要设置的宽赋给一个临时变量tWidth,然后判断tWidth是否超过最大范围,不是的话就可以进行赋值,否则就放弃修改。 【自动转向】 如果没有设置最小范围限制,当超过改方向能设置宽高的范围就会自动转向。 转向程序中需要一个参数表示转向后要执行的缩放程序,并重新设置几个属性。 以左转程序TurnLeft为例: _fun:设置为转向后要执行的缩放程序; _sideRigh:设置为当前的_sideLeft,即以把右边定位左边设置成原来的左边定位坐标(形象点说就是原来是左边不动,改成右边不动); _fixLeft:左转后的定位需要_fixLeft,设置为_styleLeft,本来是left加width的,由于左转时width是0,所以只要left就够了。 如果设置了最大范围限制,还需要设置一下范围参数,为了方便,程序使用了一个_mxSet方法重新设置范围参数。 程序如下: Code if(!(this.Min || this._styleWidth)){ this._fun = fun; this._sideRight = this._sideLeft; this._fixLeft = this._styleLeft; this.Max && this._mxSet(); return true; } 如果发生了转向就返回true,这个主要是用在对角方向的转向。 对于对角方向,可能会转向两个方向,但同一时间最多只能设置一个转向(同时转两个可能会造成混乱), 而且在按比例缩放时,程序规定只进行水平方向的转向(比例缩放中已说明)。 例如对于RightDown转向,可以这样满足这两个需求: this.TurnLeft(this.LeftDown) || this.Scale || this.TurnUp(this.RightUp); 【样式修正】 由于offset获取的值跟style设置的值并不是一样的,例如offsetWidth包括padding、border和width。 所以在获取和设置时必须做一些修正,例如用offsetWidth获取宽度,要设置width时必须减去padding和border等等。 程序中有_borderX和_borderY属性分别是缩放对象的左右和上下边框宽度: Code 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); 程序中主要是修正了border,对于padding、margin都没有考虑,如果设置了这些属性的要注意一下哦。 【样式设置】 首先缩放对象必须是绝对定位,如果有范围限制容器就必须把容器设置成相对定位: Code this._obj.style.position = "absolute"; !this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative"); 推荐根据拖拉的方向设置拖拉对象的鼠标样式,其中右下和左上是nw-resize,左下和右上是ne-resize,上和下是n-resize,左和右是e-resiz。 至于拖拉对象的定位就有技巧一点,绝对定位到四个角比较简单,适当设置top,left,right和height到为0就行了,例如右上角是right和top为0。 四个边就难一点,参考这里的居中显示效果,利用定位样式和margin就能做到居中了。 例如右边设置top为50%,margin-top为高度的负的一半就能在右边上下居中了。 程序说明就到这里了,还有一些结构上的东西以我的能力还是比较难写出来,还是看代码来领会吧。 程序有很多相似的结构,总感觉可以整理得更好,等以后自己的编写水平高点的时候再来看拉。 使用说明 首先实例化一个拖拉缩放对象: var rs = new Resize("dragDiv"); 有以下这些可选参数和属性: 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(){}//缩放时执行 然后使用Set程序添加拖拉对象,Set程序需要两个参数,第一格是拖拉对象,第二个是缩放参数。 其中缩放参数可以是"right-down"、"left-down"、"right-up"、"left-up"、"right"、"left"、"up"和"down"其中之一。 像这样添加就行了: rs.Set("rDown", "down"); ps:如果跟跟拖放效果配合使用时,要禁止冒泡,否则一点拖拉对象就冒泡到拖放了。
- 1
- 粉丝: 222
- 资源: 35
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助