Javascript Resize和Drag类,基于jQuery

  前一段时间写了一个 "在线图片切割"的小程序,现在将其中的Resize和Drag动作作为单独的类分离出来,与大家分享。这两个类都须要jQuery支持,但应该可以很轻松的改写出非jQuery的版本出来。另外,Resize类与Drag类的代码很相似,如果想的话,应该可容易的整合为一个类。有心的朋友可以试一下。欢迎拍砖和提出建议:)

使用

  点击这里查看演示效果。

Use Resize and Drag
$(
function(){
    
var sa = document.getElementById('selectArea'
);
    $(
'#selectArea span').mousedown(function
(e){
        
new Resize(sa).start(e, this.className.replace('-resize'''
));
    });
    $(
'#selectArea').mousedown(function
(e){
        
new
 Drag(sa).start(e);
    });
});

  

  下面是HTML部分:

Demo HTML

 

 Resize类说明

   该类使用向量代表方向,西方(x = -1),北方(y = -1),东方(x = 1)和南方(y = 1),,没有方向用0表示。这样,就可以用这些值组成的向量代表八个方向。而实现时,用一个点oPos表示调整对象的左上角的点,iPos表示调整对象的右下角的点。因此,在调整大小时,如果方向为西南(x = -1,y = 1),则只须调整oPos.x和iPos.y。

  下面是Resize类的属性和选项:

Properties And Options

 

  下面是setDirection方法:

method -- setDirection
    setDirection : function(direction) {
        
switch
(direction) {
        
case 'west' :this.vector = {x:-1,y: 0};break
;
        
case 'east' :this.vector = {x: 1,y: 0};break
;
        
case 'north':this.vector = {x: 0,y:-1};break
;
        
case 'south':this.vector = {x: 0,y: 1};break
;
        
case 'north-west':this.vector = {x:-1,y:-1};break

        
case 'south-west':this.vector = {x:-1,y: 1};break

        
case 'north-east':this.vector = {x: 1,y:-1};break

        
case 'south-east':this.vector = {x: 1,y: 1};break
;
        
default:return false
;
        }
        
return true
;
    }

 

  下面是onResizing事件:

onResizing Event

    onResizing: 
function(e){
        
// 修正X,Y

        var x = Math.max(Math.min(e.pageX, this.option.boundRight), this.option.boundLeft);
        
var y = Math.max(Math.min(e.pageY, this.option.boundBottom), this
.option.boundTop); 
         
// 依次为向西,东,北,南方向调整

        if(this.vector.x === -1this.oPos.x = Math.min(x, this.iPos.x - this.option.minWidth);
        
if(this.vector.x ===  1this.iPos.x = Math.max(x, this.oPos.x + this
.option.minWidth);
        
if(this.vector.y === -1this.oPos.y = Math.min(y, this.iPos.y - this
.option.minHeight);
        
if(this.vector.y ===  1this.iPos.y = Math.max(y, this.oPos.y + this
.option.minHeight);
        
this.resize(this.oPos.x - this.parentOffset.left, this.oPos.y-this.parentOffset.top, this.iPos.x - this.oPos.x, this.iPos.y - this
.oPos.y);
        
return false
;
    }

 

Drag类说明

  Drag与Resize类非常相似,它们的属性,方法都差不多。

  由于拖动对象时,对象上所有的点都会移动相同的偏移量。所以将对象旧的左上角的点,鼠标现在所在的点,鼠标原来所在的点作向量运算,就可以得到对象左上角的点现在所在的位置(pointLeftTopNew = pointLeftTopOld + pointMouseNew - pointMouseOld)。

  下面是onDragging 事件:

onDragging Event
    onDragging: function(e) {
        
// 调整元素相对于当前视口的偏移

        // this.oPos 为鼠标原来所在的点
        // e.page 为鼠标现在所在的点
        // 将它们作向量运算(e.page - this.oPos) 就得到了target的移动的向量,
        // 用target左上角的点加上它就得到了this.info.pageLeft 和 this.info.pageTop
        this.info.pageLeft = Math.max(Math.min(this.info.pageLeft + e.pageX - this.oPos.x, this.option.boundRight  - this.info.width), this.option.boundLeft);
        
this.info.pageTop  = Math.max(Math.min(this.info.pageTop  + e.pageY - this.oPos.y, this.option.boundBottom - this.info.height), this
.option.boundTop);
        
this.oPos =
 {x : e.pageX,y : e.pageY};
        
this.drag(this.info.pageLeft - this.parentOffset.left, this.info.pageTop - this
.parentOffset.top);
        
return false
;
    }

 

 下载 

  因为可能有多个实例,属性写在prototype里会引起错误,所以在这里我犯了严重的错误。

  如果需要请使用DragResize类

posted @ 2009-02-26 18:02 czy1121 阅读(3440) 评论(9) 编辑 收藏

 回复 引用 查看   
#1楼2009-02-26 20:11 | cloudgamer      
 回复 引用 查看   
#2楼[楼主]2009-02-26 20:36 | czy1121      
@cloudgamer
呵呵,你的那个我看过的,我就是看了你的那个程序才想到将resize与drag分离出来的
你的BLOG我去过多次,有不少关于JS的好文章呢:)

 回复 引用 查看   
#3楼2009-02-27 08:18 | 戒焦戒躁      
网上有现成的jQuery插件呀,代码非常精简:
(function($){
$.fn.jqDrag=function(h){return i(this,h,'d');};
$.fn.jqResize=function(h){return i(this,h,'r');};
$.jqDnR={dnr:{},e:0,
drag:function(v){
if(M.k == 'd')E.css({left:M.X+v.pageX-M.pX,top:M.Y+v.pageY-M.pY});
else E.css({width:Math.max(v.pageX-M.pX+M.W,0),height:Math.max(v.pageY-M.pY+M.H,0)});
return false;},
stop:function(){E.css('opacity',M.o);$().unbind('mousemove',J.drag).unbind('mouseup',J.stop);}
};
var J=$.jqDnR,M=J.dnr,E=J.e,
i=function(e,h,k){return e.each(function(){h=(h)?$(h,e):e;
h.bind('mousedown',{e:e,k:k},function(v){var d=v.data,p={};E=d.e;
// attempt utilization of dimensions plugin to fix IE issues
if(E.css('position') != 'relative'){try{E.position(p);}catch(e){}}
M={X:p.left||f('left')||0,Y:p.top||f('top')||0,W:f('width')||E[0].scrollWidth||0,H:f('height')||E[0].scrollHeight||0,pX:v.pageX,pY:v.pageY,k:d.k,o:E.css('opacity')};
E.css({opacity:0.8});$().mousemove($.jqDnR.drag).mouseup($.jqDnR.stop);
return false;
});
});},
f=function(k){return parseInt(E.css(k))||false;};
})(jQuery);

 回复 引用 查看   
#4楼[楼主]2009-02-27 11:55 | czy1121      
@戒焦戒躁
到这个插件的官网去看了下.却实很不错啊.
不过它实现的是元素最基本拖动和缩放功能,所以才能够如此精简,
虽然很多时候用它就能满足需求,但是我做的"在线图片切割", 用它是不行的.

 回复 引用 查看   
#5楼2009-02-27 13:25 | skyaspnet      
您好,请问校内网的图片圈人功能可以使用您做的这个程序修改得到吗?谢谢!
 回复 引用 查看   
#6楼[楼主]2009-02-27 15:34 | czy1121      
@skyaspnet
我去校内网查看了一下这个"图片圈人"功能,
它就是先获取所圈区域的左上角相对图片的坐标和高宽,
再传给服务器保存,然后当鼠标移动到所圈人的名字上时,从数据库取出数据,再显示所圈的区域.
其中"获取所圈区域"的过程就是使用的Resize,Drag之类我功能实现的.

 回复 引用 查看   
#7楼2009-02-28 18:57 | skyaspnet      
感谢您的回复, 请问是否有相关的例子, 想学习一下, 谢谢!
 回复 引用 查看   
#8楼2010-09-06 18:05 | 梦.夜帝      
这个插件的地址是什么呢?
 回复 引用 查看   
#9楼2010-09-06 18:05 | 梦.夜帝      
@戒焦戒躁
请问你说的插件地址是什么?