现在的SNS网站相册都拥有圈人的功能,也就是在图片上指定的地方画一个框,然后指定该框里是谁。这和裁剪图片的原理是一样的。也就是拖拽功能和resize功能合理的配合。由于jQuery UI 里这两个功能都有比较好的实现,而且效率很不错,所以,我就用jQuery UI 整合实现了一个。

1.准备工作

   该功能既然基于jQuery UI 功能,当然需要引入相关的js组件。在这里使用的是jQuery-1.3.3 、jQuery UI 1.7.1中的ui.core.js、ui.dragdrop.js、ui.resize.js

2.DOM结构与样式的编写

   上图所示,虚线框和8个小的拖拽按钮如何实现?我采用的是绝对定位的方式。虚线由于有一点动画效果,我用一个小的gif图片来实现的,这里要注意的是,由于使用的是jQuery UI 的组件来实现,在resize 组件中,resize拖拽的按钮的DOM结构已经固定写在了JS里面,所以,只能在依照其规则来写。具体的DOM结构如下:

其中,<span>标签表示的是四条虚线。后面的8个div表示的是8个拖拽按钮。全部采用绝对定位,这样在改变大小了之后,能够确保样式正确。其中<div class="frame">标签是为了解决IE里面绝对bottom无法正常显示加的hack。

另外,由于拖拽和resize都要求不能超过图片的范围,所以,我将图片和marker标签使用的DOM放在同一个父容器下,父容器的高度和宽度根据图片的大小自动适应,所以,父容器要采用浮动定位或者绝对定位,具体需要考虑整体的需求。另外,Dom是JS生成的。

测试 DOM 结构

3.js的编写

    js我还是按照以往的风格,写成了一个类以方便调用和扩展。其中关键的是jQuery UI 中的两个组件(drag、resize)的调用,的代码如下:

            var _this = this;
            this.$marker.draggable({
                containment:"parent",
                drag:function(){
                     _this._resize();
                  if($.isFunction(_this.opts.drag)){
                     _this.opts.drag.call(_this);
                  }
               },
               stop:function(){
                     _this._resize();
                  if($.isFunction(_this.opts.dragStop)){
                     _this.opts.dragStop.call(_this);
                  }
                 
               }
            });
            this.$marker.resizable({
                handles:"n,e,s,w,se,sw,ne,nw",
                minHeight:30,
                minWidth:30,
                resize:function(event,ui) {
                    _this._resize();
                    if($.isFunction(_this.opts.resize)){
                        _this.opts.resize.call(_this);
                    }
                },
                stop:function(){
                    _this._resize();
                    if($.isFunction(_this.opts.risizeStop)){
                     _this.opts.risizeStop.call(_this);
                    }
                }
            });

其中containment:"parent",是为了控制其多拽范围。也就是只能在父容器中拖拽。 handles:"n,e,s,w,se,sw,ne,nw"是对其拖拽方向的控制,这里表示可以在8个方向上任意拖拽。我写了4个回调函数:drag,resize,dragStop, resizeStrop分别在拖拽中、大小缩放时、拖拽结束时、大小缩放结束时调用。通常可以用来实时获取当前截取框的位置。

我有一个公开的方法:getPosition() 获取当前位置。获取是一个对象,分别是左上角点的坐标和右下角点的坐标。

测试 完整功能

我只写了前端部分的代码,如果要完成圈人或者截图的功能,是需要后台来支持的。前台把当前框选的位置和大小传给后台,后台再来处理剩下的事。