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的拓展

       IE下利用Matrix滤镜实现绕中心点旋转

 

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

      文章过长,一篇无法保存。

      IE下及标准浏览器下的图片旋转(二)—— Canvas

 

posted @ 2014-12-03 11:11  K13  阅读(2717)  评论(0编辑  收藏  举报