图片局部裁剪

背景:

很久之前就在marry5.com看到这个效果,也叫图片裁剪、图片剪切,当时觉得很神奇,碍于水平有限,没做出来。
前些日子突然想做一个透镜效果,就突然想到了这个效果,于是找出当年“珍藏”的代码决定一尝所愿。

前言:

这个程序主要分三部分:层的拖放、层的缩放、图片切割(包括预览)。
其中层的拖放是很常见的效果,层的缩放有点难度,图片切割看着炫其实原理也很简单。
不过在实现的过程中也学习到很多以前不知道的东西,下面都会说明,希望大家从中也能学到东西。

效果:






 

原理:

【拖放程序】

详细请参考JavaScript 拖放效果


【缩放程序】

原理也很简单,根据鼠标的坐标来设置缩放对象样式。
除了设置width和height外,对于上边和左边的缩放还要设置left和top,详细可参考代码。

程序更重要的是结构设计,因为有八个方向又分普通和比例缩放,
要尽量抓出能重用的部分,不然程序的复杂度可想而知。
为了提高程序内函数重用度减低复杂度我做了以下设计:
1.设一个_fun程序存放缩放过程中要执行的程序(有点像委托);
2.计算四个样式初始值,缩放函数修改这些初始值,最后重新设置全部样式(为了减低复杂度不是按需修改);
3.对于普通缩放只需要四个方向的程序就够,像右下方向可以用执行右边和下边程序代替;
4.根据比例缩放程序和普通缩放程序可重用的部分抽出了四个修正程序(用了部分程序效率来换取);

下面是程序中比较有用的部分:

【边宽获取】

由于涉及到高度和宽度的修改,边框宽度的获取必不可少。
因为用offset取得的宽度或高度是包括了边框宽度的,style中的宽度和高度是不包括边框宽度的,
所以设置样式的时候必须在offset取得的宽度或高度的基础上减去边框宽度。

那怎么取得边框宽度呢?
直观的方法是通过parseInt(object.style.borderBottomWidth)来获取,但这是错误的,
因为这样只能获取style中设置的样式,而不能获取class中设置的样式。

要取得最终样式(实际的样式),在ie中可使用currentStyle取得,在ff中使用document.defaultView.getComputedStyle(object, null),
那么用下面的程序就可以获取边框宽度了:

Code

【比例缩放】

比例缩放原理也很简单,在原有缩放的基础上,再按比例设置一次高和宽。
例如右下的比例缩放是先设置一次右边的普通缩放取得宽度,
根据比例取得高度后执行一次下边的修正程序,
由于此时高度经过修正可能已经改变了,最后需要再执行一次右边的修正程序。

Code

这样的缩放是以宽度优先的,对于上下两个点以高度优先会有更好的体验,
例如对于上面的点可以:
Code

对于上下左右四个点,更好的体验当然是以该点为中心缩放,
各位有兴趣的话可以把这个也做出来,写多四个修正程序对应这几个点就行。

而最小限制,范围限制可参照修正程序中的代码。
程序中也使用了跟拖放差不多的释放选择和鼠标捕获。

【图片切割】

关于图片切割的设计,有三个方法:
1.把图片设为背景图,通过设置背景图的位置来实现,但这样的缺点是只能按图片的正常比例实现,不够灵活;
2.把图片放到切割对象里面,通过设置图片的top和left实现,这个方法是可行,但下面有更简单的方法实现;
3.通过设置图片的clip来实现。

这个方法是从当年“珍藏”的代码中看到的,虽然以前接触过clip,但都忘了。
clip的作用是“检索或设置对象的可视区域。可视区域外的部分是透明的。”
依据上-右-下-左的顺序提供自对象左上角为(0,0)坐标计算的四个偏移数值来剪切。
例如:

div { position:absolute; width:60px; height:60px; clip:rect(0 20 50 10); }

注意position:absolute的设置是必须的(详细看手册)。

下面说说具体实现原理:
首先需要一个容器,拖放对象,图片地址,显示宽度和高度,
还要插入三个层:
底图层:那个半透明的图片,
显示层:拖放对象中正常显示的那个部分,
拖动层:就是拖放对象,
其中为了底图层和显示层能完美的重叠,我两个层都用了绝对定位,定在左上角。
zIndex也要设置一下,保证三个层的顺序。

下面是很简单但最重要设置切割函数SetPos(),按拖放对象的参数进行切割:

Code

只要把SetPos()放到Drag的onMove和Resize的onResize中就行。
onMove和onResize分别是拖放和缩放时附加执行的程序。

程序中有一个Init()函数,它的作用是初始化一些设置,
特别分出来的原因是为了在用户修改了属性后执行一次,就可以根据修改过的属性重新初始化一次。
更好的做法是根据不同的属性修改修改需要修改的设置,这里我是偷懒了。

【切割预览】

至于预览效果也不难,根据预览高度宽度和拖放对象(显示层)的参数,计算出图片和预览图的比例scale:

Code

通过这个比例就可以计算出预览图的width、height、top、left了:

Code

最好根据这些参数切割预览图:

styleView.clip = "rect(" + pt + "px " + (pl + w) + "px " + (pt + h) + "px " + pl + "px)";

预览图效果就做好了。


源码:

拖放程序:

Code

缩放程序:

Code

图片切割程序:

Code



使用说明:

首先需要5个参数,分别是:容器对象、拖放对象、图片地址、图片宽度、图片高度。
可选设置:
Opacity:透明度(0到100),
dragTop:拖放对象top,
dragLeft:拖放对象left,
dragWidth:拖放对象宽度,
dragHeight:拖放对象高度,
缩放触发对象:
Right,Left,Up,Down,RightDown,LeftDown,RightUp,LeftUp,
Scale:是否按比例缩放,
View:预览对象,
viewWidth:预览宽度,
viewHeight:预览高度,

实例化对象:

Code

可以根据需要扩展,例如:

Code


补充:

里面的Drag拖放程序和Resize缩放程序是可以独立出来用的,
ImgCropper图片切割程序只是在内部实例化了这两个对象。

下载完整实例


要真实的切割图片保存图片请参考:js + .Net 图片切割系统

posted @ 2008-11-20 04:54  hannover  阅读(1184)  评论(0编辑  收藏  举报