基于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 相关文章推荐
Jquery实战_读书笔记2 选择器
Jan 22 Javascript
用javascript替换URL中的参数值示例代码
Jan 27 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
jQuery设置和获取select、checkbox、radio的选中值方法
Jan 01 Javascript
一个例子轻松学会Vue.js
Jan 02 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
Mar 09 Javascript
es6的数字处理的方法(5个)
Mar 16 Javascript
vue 中自定义指令改变data中的值
Jun 02 Javascript
利用JQuery操作iframe父页面、子页面的元素和方法汇总
Sep 10 jQuery
JS库之ParticlesJS使用简介
Sep 12 Javascript
基于Vue制作组织架构树组件
Dec 06 Javascript
如何构建一个Vue插件并生成npm包
Oct 26 Javascript
基于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的ob_start() 控制您的浏览器cache
2009/08/03 PHP
PHP 利用AJAX获取网页并输出的实现代码(Zjmainstay)
2012/08/31 PHP
对于ThinkPHP框架早期版本的一个SQL注入漏洞详细分析
2014/07/04 PHP
PHP中浮点数计算比较及取整不准确的解决方法
2015/01/09 PHP
ThinkPHP开发框架函数详解:C方法
2015/08/14 PHP
PHP基于单例模式实现的mysql类
2016/01/09 PHP
PHP 中提示undefined index如何解决(多种方法)
2016/03/16 PHP
Yii数据模型中rules类验证器用法分析
2016/07/15 PHP
理清PHP在Linxu下执行时的文件权限方法
2017/06/07 PHP
JS将秒换成时分秒实现代码
2013/09/03 Javascript
简单的两种Extjs formpanel加载数据的方式
2013/11/09 Javascript
js判断字符长度以及中英文数字等
2013/12/31 Javascript
jQuery中change事件用法实例
2014/12/26 Javascript
自定义函数实现IE7与IE8不兼容js中trim函数的问题
2015/02/03 Javascript
基于jquery实现图片上传本地预览功能
2016/01/08 Javascript
jquery按回车键实现表单提交的简单实例
2016/05/25 Javascript
js querySelector() 使用方法
2016/12/21 Javascript
JavaScript获取当前时间向前推三个月的方法示例
2017/02/04 Javascript
Angular 5.0 来了! 有这些大变化
2017/11/15 Javascript
Typescript 中的 interface 和 type 到底有什么区别详解
2019/06/18 Javascript
python中pylint使用方法(pylint代码检查)
2018/04/06 Python
详解Python 切片语法
2019/06/10 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
2020/04/01 Python
在Keras中实现保存和加载权重及模型结构
2020/06/15 Python
python中return不返回值的问题解析
2020/07/22 Python
如何将无状态会话Bean发布为WEB服务,只有无状态会话Bean可以发布为WEB服务?
2015/12/03 面试题
求职信内容考虑哪几点
2013/10/05 职场文书
秘书英文求职信
2014/04/16 职场文书
团日活动总结模板
2014/06/25 职场文书
2014年测量员工作总结
2014/12/12 职场文书
离婚协议书范文2015
2015/01/26 职场文书
课外活动总结
2015/02/04 职场文书
2015应届毕业生自荐信范文
2015/03/05 职场文书
学困生帮扶工作总结
2015/08/13 职场文书
python将图片转为矢量图的方法步骤
2021/03/30 Python
SpringBoot工程下使用OpenFeign的坑及解决
2021/07/02 Java/Android