背景:很久之前就在marry5.com看到这个效果,当时觉得很神奇,碍于水平有限,没做出来。
前些日子突然想做一个透镜效果,就突然想到了这个效果,于是找出当年“珍藏”的代码决定一尝所愿。
前言:
这个程序主要分三部分:层的拖放、层的缩放、图片切割(包括预览)。
其中层的拖放是很常见的效果,层的缩放有点难度,图片切割看着炫其实原理也很简单。
不过在实现的过程中也学习到很多以前不知道的东西,下面都会说明,希望大家从中也能学到东西。
原理:
【拖放程序】
基本原理很简单,不知道的看代码就明白,其中参考了越兔和BlueDestiny的相关文章。
下面说一下比较有用的地方:
【范围限制】
首先当然是有拖放范围参数,分别是mxLeft(左边的left最小值)、mxRight(右边的left最大值)、mxTop(上边的top最小值)、mxBottom(下边的top最大值)。
然后在拖动程序Move()中看有没有超过,超过的话设回极限值就行:
复制代码 代码如下:
【缩放程序】
原理也很简单,根据鼠标的坐标来设置缩放对象样式。
除了设置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),
那么用下面的程序就可以获取边框宽度了:
复制代码 代码如下:
【图片切割】
关于图片切割的设计,有三个方法:
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(),按拖放对象的参数进行切割:
复制代码 代码如下:
首先需要5个参数,分别是:容器对象、拖放对象、图片地址、图片宽度、图片高度。
可选设置:
Opacity:透明度(0到100),
dragTop:拖放对象top,
dragLeft:拖放对象left,
dragWidth:拖放对象宽度,
dragHeight:拖放对象高度,
缩放触发对象:
Right,Left,Up,Down,RightDown,LeftDown,RightUp,LeftUp,
Scale:是否按比例缩放,
View:预览对象,
viewWidth:预览宽度,
viewHeight:预览高度,
实例化对象:
Code
var ic = new ImgCropper("bgDiv", "dragDiv", "1.jpg", 400, 500, {
dragTop: 50, dragLeft: 50,
Right: "rRight", Left: "rLeft", Up: "rUp", Down: "rDown",
RightDown: "rRightDown", LeftDown: "rLeftDown", RightUp: "rRightUp", LeftUp: "rLeftUp",
View: "viewDiv", viewWidth: 200, viewHeight: 200
})
可以根据需要扩展,例如:
Code
//设置图片大小
function Size(w, h){
ic.Width = w;
ic.Height = h;
ic.Init();
}
//换图片
function Pic(url){
ic.Url = url;
ic.Init();
}
//设置透明度
function Opacity(i){
ic.Opacity = i;
ic.Init();
}
//是否使用比例
function Scale(b){
ic.Scale = b;
ic.Init();
}
补充:
里面的Drag拖放程序和Resize缩放程序是可以独立出来用的,
ImgCropper图片切割程序只是在内部实例化了这两个对象。