• 无通信的图像旋转


    图像的旋转是目前的 web 应用程序中比较常见的一种操作。曾经在做这样的程序时,思路比较狭窄,总是认为扔给服务器端处理比较稳妥。这种方法大致的过程是这样的:当用户点击一种旋 转方向,立即发出一个 Ajax 请求,告诉后端要旋转的图像和旋转的角度,再由后端通过一定的工具(如 PHP 的 GD 库)生成新的图像再进行存储并向浏览器返回新的图像地址,这时使用 JavaScript 对图像的 src 属性进行更新即可。这个过程对于前端来说非常的简单,它大概像下面这样:

    $.ajax({
    	url : 'url.php',
    	type : 'GET',
    	data : {
    		degree : 90,
    		imageId : id
    	},
    	success : function(src){
    		image.src = src;
    	}
    });
    

    尽管可以在前端缓存每个已经旋转过的角度的图像地址,但是当旋转到新的角度时,仍然需要发出 Ajax 请求,用户需要一个等待的过程,服务器也需要对图像进行处理和存储,还要考虑才适当的时候删除掉这些“过程中”的图像,非常的麻烦。事实上,利用 canvas 就可以轻易的实现这样的功能,而对于不支持 canvas 的 IE ,则可以使用滤镜来达到同样的目的,对于这个操作而言,IE 的滤镜甚至较 canvas 更为简单。最重要的是,由于是纯前端的行为,用户几乎无需等待就可以看到效果,也没有建立任何 HTTP 请求,不会对服务器端产生任何影响。

    下面我们就来一步步实现纯前端方式的图像旋转,首先是 IE,在 IE 中通过 BasicImage 滤镜 的 rotate 属性值来设置图像的旋转角度,根据微软的文档,这个值只能设置为 0、1、2、3,分别表示 0度,90度,180度和270度四个角度的旋转,假定我们已经获取到了图像对象为 image,旋转的角度为 degree,那么具体的代码就非常简单了:

    image.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+degree/90+')';
    

    其他浏览器中的情况要稍微复杂一点,需要借助于 Canvas,使用其 rotate 方法旋转 Canvas,使用其 drawImage 方法在 Canvas 上绘制图像。rotate 方法非常简单,它接受一个参数,即旋转的弧度数,注意这里是弧度而不是角度,如果还记得高中数学的话,弧度与角度的转换公式应该并不陌生:

    var radian = degree * Math.PI / 180;
    /** 弧度 = 角度 * π / 180 **/
    

    drawImage 方法的参数比较多,但我们这里指使用其中前三个参数:图像对象,绘制起点的 x 坐标,绘制起点的 y 坐标。在调用这些方法之前,我们需要为 img 元素 追加一个 canvas:

    <img src="img_rotate.jpg" alt="football" id="rotate_demo" />
    <canvas id="image_canvas"></canvas>
    

    接下来在 JavaScript 中获取到这两个元素,然后使用刚才介绍的两个方法根据不同的角度对图像和 canvas 进行处理:

    var image = document.getElementById("rotate_demo");
    var canvas = document.getElementById("image_canvas");
    var ctx = canvas.getContext('2d');
    var width = image.width, height = image.height, x = 0, y = 0;
    switch(degree){
         case 90:
              width = image.height;
              height = image.width;
              y = image.height * (-1);
              break;
         case 180:
              x = image.width * (-1);
              y = image.height * (-1);
              break;
         case 270:
              width = image.height;
              height = image.width;
              x = image.width * (-1);
              break;
    }
    
    canvas.setAttribute('width', width);
    canvas.setAttribute('height', height);
    ctx.rotate(degree * Math.PI / 180);
    ctx.drawImage(image, x, y);
    image.style.display = "none";
    

    上面的代码看起来比较多,实际上核心方法只有刚才讲到的 rotate 和 drawImage,但是需要注意的,当画布旋转的时候,画布的宽高可能会发生反转,绘制的坐标也可能会反转,所以我们对 degree 进行了 switch ,具体处理在不同的角度下的反转情况,最后将原始图像隐藏,使用绘制好的 canvas 来显示。

    纯前端旋转图像的主要过程就是这样的,剩下的问题是通过下面的函数来判断具体让浏览器使用 canvas 还是使用滤镜:

    function supportCanvas(){
    	return !!document.createElement('canvas').getContext;
    }
    

    将上面的代码套在一个函数中,并稍加改造,在外面加上一个按钮,即可循环旋转图像,下面是本文 Demo 的完整代码。html:

    <p><input type="button" value="旋转" id="rorate_button"/></p>
    <img src="img_rotate.jpg" alt="football" id="rotate_demo"/>
    <canvas id="image_canvas"></canvas>
    

    JavaScript:

    // canvas 能力检测
    var supportCanvas = !!document.createElement('canvas').getContext;
    
    // 主函数
    function imageRotate(degree,image,canvasId){
    	if(!supportCanvas){
    		image.style.filter = 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+degree/90+')';
    	}else{
    		var canvas = document.getElementById(canvasId);
    		var ctx = canvas.getContext('2d');
    		var width = image.width, height = image.height, x = 0, y = 0;
    		switch(degree){
    		     case 90:
    		          width = image.height;
    		          height = image.width;
    		          y = image.height * (-1);
    		          break;
    		     case 180:
    		          x = image.width * (-1);
    		          y = image.height * (-1);
    		          break;
    		     case 270:
    		          width = image.height;
    		          height = image.width;
    		          x = image.width * (-1);
    		          break;
    		}
    		canvas.setAttribute('width', width);
    		canvas.setAttribute('height', height);
    		ctx.rotate(degree * Math.PI / 180);
    		ctx.drawImage(image, x, y);
    		image.style.display = "none";
    	}
    }
    
    // 初始角度与事件绑定
    var degree = 0;
    var image = document.getElementById("rotate_demo");
    document.getElementById("rorate_button").onclick = function(){
    	degree += 90;
    	degree = degree === 360 ? 0 : degree;
    	imageRotate(degree,image,'image_canvas');
    };
    

    参考资料:

    转自:http://www.jsmix.com/javascript/image-rotate-without-correspondence.html

  • 相关阅读:
    Docker
    Docker
    log4j日志类的使用
    &times被转义成x的解决方法
    java通用的jdbc数据库操作类
    java一个调用webapi的工具类
    Java 开发杂记
    J2EE名词解释
    C# 进程之间的通讯
    如何捕获全局异常
  • 原文地址:https://www.cnblogs.com/myphoebe/p/2226266.html
Copyright © 2020-2023  润新知