
现在的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() 获取当前位置。获取是一个对象,分别是左上角点的坐标和右下角点的坐标。
测试 完整功能
我只写了前端部分的代码,如果要完成圈人或者截图的功能,是需要后台来支持的。前台把当前框选的位置和大小传给后台,后台再来处理剩下的事。
