基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)


Posted in Javascript onSeptember 02, 2011

正文:
为了使层次分明及便于阅读,  整个解决方案如下:
基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

其中BitmapCutter.Core是图片的服务器端处理程序, 类图为:

基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS) 

简单说明下, 更多说明可查看源码注释 :

Cutter为裁剪对象, 用于存储客户端通过AJAX提交的数据.

Helper为图片处理类, 包括图片翻转(RotateImage()), 图片裁剪(GenerateBitmap()).

Callback为服务器端图片处理类, 通过使用Cutter封装客户端AJAX提交的数据, 然后调用Helper中的方法来完成图片处理.

BitmapScissors是一个HttpHandler, 通过客户端返回的 'action' 来调用Callback中的方法:

基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
注: 此处用了反射来根据'action'值动态调用Callback中的方法, 如不习惯或认为不妥的请自行更改...

客户端AJAX提交的Url为"scissors.axd", 实际为BitmapScissors类(如修改了服务器端处理程序, 请在Web.config中根据实际进行httpHandler节点配置), 本例为:

基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

Ok, 下面开始介绍重点, $.fn.bitmapcutter插件的实现:

先来上张效果图,标记下bitmapcutter中的Dom对象, 额, 喜欢刚大木的漫迷比较多, 就来张洛克昂的吧:

基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

说明: 

holder为原图承载容器, 当原图过大时可只显示部分, 通过平移来查看未显示区域的图象, holder为div, 设置position样式为relative, 这样原图img(同为img对象)的position样式为absolute时, 即可通过控制其left, top 值来进行图片的平移显示, 注意holder的overflow必须设置成hidden, 这样img将会被包裹在holder中,超出holder边界的img将会被隐藏.

cutter为截取框, 可进行拖拽以选择自己敢兴趣的截取区域, 拖拽区域在holder容器内,  同时会在thumbimg(原理与holder+img相同)内生成缩略图.

opts - 功能区域, 提供所有可用的功能按钮, 包括: 放大, 缩小, 左移, 右移, 上移, 下移, 还原, 左旋转, 右旋转.

info - 图片相素, 用于显示当前待截取图片的宽高比.

原理:

熟悉css的话应该很容易看出来, 利用相对定位的灵活性和js对css的控制.

插件说明:

由于插件的代码比较多, 这里就拣重点的讲了:

1. 全局变量:

基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

  由于在整个裁剪过程中会频繁的使用一些数据和jQuery对象, 所以定义了一个全局变量用来存储.

  $originalSize: 原图的相素, 在首次加载原图时获取, 不可改变, 主要是为放大, 缩小和还原提供一对基础数据(长,宽). 
  $zoomValue: 当前缩放比, 在执行放大或缩小时同步.
  $thumbimg: 裁剪区域缩略图的jQuery对象, 在该dom被创建时赋值.
  $img: 原图jQuery对象, 在该dom被创建时获取.
  $cutter: 裁剪区域, 同样在dom被创建时获取.

2. 插件:

  为了方便图象的控制, 同样编写了几个附加插件, 如果同学们在使用中有重名的请设法避免 ;-)

  $.fn.f: 用于获取jQuery对象的样式值, 例如width, height, left, top等.
  $.fn.loadBitmap: 用于预载入图片以获取正确的相素.
  $.fn.scaleBitmap: 用于缩放图片..缩放比率来自全局变量$zoomValue.
  $.fn.dragndrop: 我的上一个插件$.fn.Drags的定制版, 主要是为了实现某一dom对象在特定元素内的拖拽.

3. API:

  $.fn.bitmapCutter的API包括:

  src(String): 待裁剪图片的路径(相对于程序主目录), 默认为空, 必须,
  renderTo(String(Selector)|jQuery Object): bitmapCutter插件容器, jQuery对象或选择器, 默认为$(document.body),
  holderSize(Object): holder对象的大小, 包括width和height两个值, 默认为{ width: 300, height: 400 },
  cutterSize(Object): cutter对象的大小(生成头像大小), 包括width和height两个值, 默认为{ width: 70, height: 70 },
  zoomStep(Float): 每次缩放的比率更改幅度, 默认为0.2,
  zoomIn(Float): 放大时与原图的最大比, 默认为2.0,
  zoomOut(Float): 缩小时于原图的最大比, 默认为0.1,
  rotateAngle(Int): 图片翻转角度, 可取值为 90, 180, -90, -180, 默认为 90,
  moveStep(Int): 原图平移时的平移象素, 默认为100,
  onGenerated(Function): 成功生成头像时触发事件数, bitmapCutter向此方法传递一个参数 'src', 表示新裁剪生成的头像路径. 此属性的默认值为 function(src) { },
  lang(Object): 功能区域各按钮的Tooltip, lang的API为:

                zoomout(String): 放大, 默认值 'Zoom out',
                zoomin(String): 缩小, 默认值'Zoom in',
                original(String): 原始大小, 默认值'Original size',
                clockwise(String): 顺时针旋转, 默认值'Clockwise rotation({0} degrees)', 需包含 {0} 以便格式化时使用rotateAngle值填充,
                counterclockwise(String): 逆时针旋转, 默认值'Counterclockwise rotation({0} degrees)', 需包含 {0} 以便格式化时使用rotateAngle值填充,
                generate(String): 生成头像, 默认值'Generate!',
                process(String): 生成头像时的提示语, 默认值为'Please wait, transaction is processing......',
                left(String): 左平移, 默认值'Left',
                right(String): 右平移, 默认值'Right',
                up(String): 上移, 默认值'Up',
                down(String): 下移, 默认值'Down'

   API原型为:

   基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS) 

4. 开发技巧:

   为了便于代码管理及功能优化, 将功能进行了归纳, 大致可分为:

   缩放(zoom): 细分为放大和缩小, 
   翻转(rotate): 细分为顺时针和逆时针, 
   移动(move): 细分为上|右|下|左平移.

   所以直接编写三个 '基类' (具体实现看源码):
   izoom(zv): 提供图片放大或缩小功能, zv为当前缩放比,
   irotate(angle): 提供图片旋转功能, angle为当前旋转角度,
   imove(direction): 提供原图平移功能, direction为移动方向, 包括'left','up','right','down'.

   那么现在需要的就是细分各个功能:
   基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
   这里我使用了一个对象scissors来封装这些操作, 使用call来 '继承', 当然你也可以使用 '冒充' 或者 '原型链' 这些手段来实现. 这样的话在绑定这些方法的时候使用eval和json就可以很轻松的完成:
   基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
   看不明白?那么贴上Html树呢?
   基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

5. 自问自答

  Q: 为什么要在服务器端来实现旋转效果?
  A: 为了实现大众化和浏览器兼容, 所以我放弃了滤镜和Canvas.

  Q: Photoshop等图片处理软件在裁剪时都是实现反相效果的, 为什么不实现?
  A: 我想一个程序兼顾UI的时候也要考虑效率, 如果实现反相的话, cutter对象内同样需要内置一个img来与thumbimg同步, 那么当旋转图象时内存的累积是非常恐怖的.

  Q: 相比Flash, Siverlight而言这么一个东西有什么好处?
  A: 额, 其实我最初是打算用Flash做的, 不过考虑到大众化的问题(多少.Net开发人员会as?), jQuery+HttpHandler是一个不错的选择, 开放的API, 开放的源码, 我想远比让大家去改一个.fla来的轻松愉快.

  Q: 那么坏处?
  A: 大家都知道, 浏览器的缓存是把双刃剑, 在bitmapCutter里他就很烦人, 为了实现图片旋转后刷新, 只能为img的src加上一个戳(随机数?时间?whatever..), 但是这样会带来一个必然的结果 - 浏览器内存累积(目前已将此威胁降至最低 ;-)),   额..!@#$%

6. 注

  未对gif类型图片作特殊处理, 所以仅会取回第一桢处理, 生成头像格式为Png, 如果需要的话自己修改源码.
  jquery.bitmapcutter.js 尾部方法为模拟  c# string.format, 必须的.
  支持键盘操作, 方向键控制平移, +-控制放大缩小, 不喜可从源码删除.

7. demo中的简单示例

  使用一张C.C的图来截取头像, 设置截取框长宽为120:120, 容器为id为container的div, 每次旋转角度为90, 顺时针旋转功能按钮的提示为 '顺时针旋转{0}度.'
  基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
  效果:
  基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)

8. 源码包(测试图片多):

/201109/yuanma/BitmapCutter_3water.rar
Javascript 相关文章推荐
用户注册常用javascript代码
Aug 29 Javascript
读jQuery之六 缓存数据功能介绍
Jun 21 Javascript
jQuery实现响应浏览器缩放大小并改变背景颜色
Oct 31 Javascript
在Mac OS下使用Node.js的简单教程
Jun 24 Javascript
JavaScript仿支付宝密码输入框
Dec 29 Javascript
Kindeditor在线文本编辑器如何过滤HTML
Apr 14 Javascript
jquery div模态窗口的简单实例
May 28 Javascript
JavaScript基础知识点归纳(推荐)
Jul 09 Javascript
20个最常见的jQuery面试问题及答案
May 23 jQuery
vue2实现搜索结果中的搜索关键字高亮的代码
Aug 29 Javascript
bootstrap 日期控件 datepicker被弹出框dialog覆盖的解决办法
Jul 09 Javascript
vue的hash值原理也是table切换实例代码
Dec 14 Vue.js
基于jquery的loading 加载提示效果实现代码
Sep 01 #Javascript
jQuery1.6 类型判断实现代码
Sep 01 #Javascript
jquery 简短几句代码实现给元素动态添加及获取提示信息
Sep 01 #Javascript
用javascript作一个通用向导说明
Aug 30 #Javascript
JS 无限级 Select效果实现代码(json格式)
Aug 30 #Javascript
javascript 原型继承介绍
Aug 30 #Javascript
dojo学习第二天 ajax异步请求之绑定列表
Aug 29 #Javascript
You might like
Php中使用Select 查询语句的实例
2014/02/19 PHP
Destoon实现多表查询示例
2014/08/21 PHP
JavaScript Prototype对象
2009/01/07 Javascript
利用JQuery为搜索栏增加tag提示
2009/06/22 Javascript
使用Microsoft Ajax Minifier减小JavaScript文件大小的方法
2010/04/01 Javascript
浅析js中取绝对值的2种方法
2013/07/09 Javascript
解决js中window.open弹出的是上次的缓存页面问题
2013/12/29 Javascript
JavaScript中的console.profile()函数详细介绍
2014/12/29 Javascript
JS输入用户名自动显示邮箱后缀列表的方法
2015/01/27 Javascript
javascript与jquery中的this关键字用法实例分析
2015/12/24 Javascript
理解JavaScript中worker事件api
2015/12/25 Javascript
Struts2+jquery.form.js实现图片与文件上传的方法
2016/05/05 Javascript
JS实现简单的二元方程计算器功能示例
2017/01/03 Javascript
javascript基本数据类型和转换
2017/03/17 Javascript
详解AngularJS之$window窗口对象
2018/01/17 Javascript
JS实现图片旋转动画效果封装与使用示例
2018/07/09 Javascript
基于vue-cli 路由 实现类似tab切换效果(vue 2.0)
2019/05/08 Javascript
[13:40]TI3青蛙君全程回顾 DOTA2我们为梦想再战
2013/09/13 DOTA
[49:35]KG vs SECRET 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/19 DOTA
python从入门到精通(DAY 3)
2015/12/20 Python
python Pygame的具体使用讲解
2017/11/03 Python
PyQt QCombobox设置行高的方法
2019/06/20 Python
python issubclass 和 isinstance函数
2019/07/25 Python
美国开幕式潮店:Opening Ceremony
2018/02/10 全球购物
西班牙最大的婴儿用品网上商店:Bebitus
2019/05/30 全球购物
方法名是否可以与构造器的名字相同
2012/06/04 面试题
预备党员表决心书
2014/03/11 职场文书
家教广告词
2014/03/19 职场文书
电脑售后服务承诺书
2014/03/27 职场文书
股权转让协议书范本
2014/04/12 职场文书
就业协议书样本
2014/08/20 职场文书
红色经典观后感
2015/06/18 职场文书
pycharm代码删除恢复的方法
2021/06/26 Python
Spring Boot 启动、停止、重启、状态脚本
2021/06/26 Java/Android
python实现会员管理系统
2022/03/18 Python