IE下及标准浏览器下的图片旋转(一)——滤镜,CSS3
关于图片的旋转,一般来说有3种解决方案:(1)滤镜 (2)css3 (3)canvas。接下来逐一讲解。
为了方便理解,我们主要以90度整倍数讲解,兼顾其他角度。
1. 滤镜(IE专属)
1.1 旋转滤镜
语法如下:
filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=i);
rotation取值0(0或360度),1(90度),2(180度),3(270度)。取其他数无效。
旋转90度示例:
css:
#box {
width: 100px;
height: 200px;
background: #e678cc;
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
}
html:
<div id="box">我倒了</div>
效果如图:
1.2 矩阵滤镜Matrix
语法如下:
filter: progid:DXImageTransform.Microsoft.Matrix( enabled= bEnabled , SizingMethod= sMethod , FilterType= sType , Dx= fDx , Dy= fDy , M11= fM11 , M12= fM12 , M21= fM21 , M22= fM22 )
以上是完整参数,我们只要关注其中几个就可以了,简化下:
filter:progid:DXImageTransform.Microsoft.Matrix(M11=cos(roation),M12=-sin(roation),M21=sin(roation),M22=cos(roation),SizingMethod='auto expand');
SizingMethod取值有两个:clip to original(默认,容器不改变尺寸,超出裁切)和auto expand(容器改变尺寸以适应目标图像),一般我们会使用auto expand。
M11,M12,M21,M22 组成一个2×2的矩阵,通过计算着四个值可以进行任意角度旋转,并且旋转放大都由这四个参数控制。当然不用纠结到底是怎么回事,因为我也不懂,数学没学 好,呵呵,我们要做的就是用旋转角度替换roation就可以了,需要注意的是,这个旋转角度不是角度数,而是弧度数,所以我们需要将旋转的角度度数乘以 0.017453293 (2PI/360)再套进去。例如旋转45度,M11=cos(45*0.017453293),M12=-sin(45*0.017453293),M21=sin(45*0.017453293,M22=cos(45*0.017453293)。
示例:
css:
#box {
width: 100px;
height: 200px;
background: #e678cc;
filter:progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067659112366,M12=-0.7071067964618581,M21=0.7071067964618581,M22=0.7071067659112366,SizingMethod='auto expand');
}
html:
<div id="box">我倒了</div>
效果如图:
如果我们去掉SizingMethod属性,也就是使用默认clip to original,超出的部分会被裁切掉,如下图:
如 果我们想要在原基础上放大一倍,只需要将M11,M12,M21,M22的值乘以2(M11=1.414,M12=- 1.414,M21=1.414,M22=1.414),反之除以2(M11=0.354,M12=- 0.354,M21=0.354,M22=0.354)即可。
滤镜的特性:
1. 旋转贴着原轮廓的上边和左边,如下图:
能不能围绕中心旋转呢?当然可以,我们看到完整的Matrix参数中有Dx= fDx , Dy= fDy这两项,这两个值描述了一个点,图形围绕这个点进行旋转。理论上我们可以指定任一点为原点,不过考虑到实际需要和大多数同学数学都不大好,我们只要知道围绕中心点旋转就好了。公式如下:
dx=-width/2*cos(roation)+height/2*sin(roation)+width/2,
dy=-width/2*sin(roation)-height/2*cos(roation)+height/2
滤镜写法如下:
filter: progid:DXImageTransform.Microsoft.Matrix( Dx= fDx , Dy= fDy , M11= fM11 , M12= fM12 , M21= fM21 , M22= fM22 );
m11,m12,m21,m22的算法与前面说的一样。
注:我们看到没有设置SizingMethod值,因为微软官方说明当SizingMethod值为auto expand时Dx Dy失效。并且旋转后超出的原大小的部分会被隐藏掉,如果想要全部显示,我们需要对旋转后的图像进行缩放,或者留出足够的空间。
比如我们对一个图像进行90旋转:
(1) 将90度转化为弧度
90 * (2 * Math.PI / 360) = 1.5707963267948966
(2) 计算cos(roation)和sin(roation)的值
cos(1.5707963267948966)= 6.123233995736766e-17
sin(1.5707963267948966)= 6.123233995736766e-17
(3) 计算Dx和Dy的值
假定我们的图片宽300px,高200px,带入公式:
dx=-width/2*cos(roation)+height/2*sin(roation)+width/2
dx= -300/2*6.123233995736766e-17 + 200 / 2 * 6.123233995736766e-17 + 300/2=250
dy=-width/2*sin(roation)-height/2*cos(roation)+height/2
dy=-200/2*6.123233995736766e-17-200/2*6.123233995736766e-17+200/2=-50
(4) 将以上值带入滤镜公式:
filter: progid:DXImageTransform.Microsoft.Matrix( Dx= fDx , Dy= fDy , M11= fM11 , M12= fM12 , M21= fM21 , M22= fM22 );
得到:
filter: progid:DXImageTransform.Microsoft.Matrix( Dx= 250 , Dy= -50 , M11= 6.123233995736766e-17 , M12= -6.123233995736766e-17 , M21= 6.123233995736766e-17 , M22= 6.123233995736766e-17 );
效果如图:
仔细看看,是不是旋转后有点不对劲?旋转后图片好像被裁切了,所以这里有必要说下原因。先看图:
明白了么?我们设置了围绕中心点旋转90度,滤镜旋转是在原图片所占空间中进行旋转,旋转后超出的部分默认是不显示的,如果设置了auto expand属性,容器会跟随图片变换而变换,以适应其大小,但是前面我们已经知道,使用这个属性,会导致Dx和Dy无效,有两种解决方案:一种是进行缩放。另一种是给它足够的空间(网上看到好像是padding)。我个人倾向于前一种,所以针对前一种进行讲解。
我们需要做的就是讲旋转后的图像等比例缩小,使得旋转后看上去的高度与原图片所占空间的宽度一致即可,所以我们需要计算下这个比例:r = height/width,然后用这个比例分别与M11,M12,M21,M22相乘进行缩放。
(1)将宽高带入获得比例: r= 200 / 300 = 2 / 3
(2)将M11,M12,M21,M22分别乘以2/3带入滤镜:
filter: progid:DXImageTransform.Microsoft.Matrix( Dx= 250 , Dy= -50 , M11= 4.082155997157844e-17 , M12= -4.082155997157844e-17 , M21= 4.082155997157844e-17 , M22= 4.082155997157844e-17 );
OK,大功告成,看效果:
2.旋转后对元素进行了实际改变(IE6和7,IE8和9不改变)
注:IE高版本模拟低版本以及IETester并不准确,需要在实际环境或者独立版中测试才能发现差别。
两篇参考文章:
IE矩阵滤镜Matrix旋转与缩放及结合transform的拓展
2. css3旋转属性
语法: transform: rotate(Xdeg)
比 如我们需要旋转90度,可以这样写transform: rotate(90deg),支持负数,整数是顺时针旋转,负数时逆时针旋转,比如我们需要旋转 315度,可以这样写transform: rotate(315deg),也可以这样写transform: rotate(-45deg)。以及旋转 90度为例,效果如图:
我们可以看到,这个属性是以中心点为原点进行旋转,并且超出部分不会像ie滤镜中心旋转那样被裁掉,保持了原大小,并且旋转不改变元素实际大小。
这个属性是css3属性,所以需要浏览器对css3支持才有效。大多数标准浏览器以其私有属性方式支持了这个属性,所以我们依然可以使用,如下:
-moz-transform: rotate(0deg); //Firefox
-webkit-transform: rotate(0deg); //Chrome and Safari
-o-transform: rotate(0deg); //Oprea
-ms-transform: rotate(0deg); //IE9
针 对支持css3的浏览器使用transform: rotate,针对不支持css3的IE系列使用滤镜,我们就可以做出一个兼容绝大多数浏览器的图片旋 转,当然这是作为我的下个插件弹出层的一部分,所以我们可以精简一下,去掉弹出层做的demo,以90度整倍数为参数旋转。
示例:
javascript:
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript">
$(function () {
/*自动计算水平垂直居中*/
function reset () {
$("#img_box").css({
"position": "absolute",
"top": "50%",
"left": "50%",
"z-index": "10000",
"margin-top": function() {return -($(this).height()) / 2},
"margin-left": function() {return -($(this).width()) / 2}
});
}
reset();
/*左右旋转计数器*/
var deg = 0;
$("#turn_r").click(function () {
deg++;
deg = deg > 3 ? 0 : deg;
rotate(deg);
return false
});
$("#turn_l").click(function () {
deg--;
deg = deg < 0 ? 3 : deg;
rotate(deg);
return false
});
/*动态增加旋转属性*/
function rotate(i) {
switch (i) {
case 0:
$("#img_box").attr('style', 'filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0); zoom: 1;-moz-transform: rotate(0deg); -webkit-transform: rotate(0deg); -o-transform: rotate(0deg);');
break;
case 1:
$("#img_box").attr('style', 'filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1); zoom: 1;-moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg);');
break;
case 2:
$("#img_box").attr('style', 'filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2); zoom: 1;-moz-transform: rotate(180deg); -webkit-transform: rotate(180deg); -o-transform: rotate(180deg);');
break;
case 3:
$("#img_box").attr('style', 'filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3); zoom: 1;-moz-transform: rotate(270deg); -webkit-transform: rotate(270deg); -o-transform: rotate(270deg);');
break;
}
reset();
}
})
</script>
css:
#box {
width: 300px;
height: 200px;
background: #f2f2f2;
position: relative;
text-align: center;
}
#img_box img {
padding: 3px;
border: 1px solid #cccccc;
background: #fff;
}
#turn_l,
#turn_r {
display: inline-block;
margin: 0 20px;
}
html:
<div id="box">
<div id="img_box"><img src="aa.jpg" alt=""></div>
<a href="/" id="turn_l">向左旋转</a>
<a href="/" id="turn_r">向右旋转</a>
</div>
兼容IE6-9,Firefox等,效果如图:
3. canvas
文章过长,一篇无法保存。