前端JS利用canvas的drawImage()对图片进行压缩

HTML5 file API加canvas实现图片前端JS压缩

要想使用JS实现图片的压缩效果,原理其实很简单,核心API就是使用canvas的drawImage()方法;
canvas的drawImage()方法API如下:

context.drawImage(img, dx, dy);
context.drawImage(img, dx, dy, dWidth, dHeight);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

后面最复杂的语法虽然看上去有9大参数,但不用慌,实际上可以看出就3个参数:

img
  就是图片对象,可以是页面上获取的DOM对象,也可以是虚拟DOM中的图片对象。
  dx, dy, dWidth, dHeight
  表示在canvas画布上规划处一片区域用来放置图片,dx, dy为canvas元素的左上角坐标,dWidth, dHeight指canvas元素上用在显示图片的区域大小。如果没有指定sx,sy,sWidth,sHeight这4个参数,则图片会被拉伸或缩放在这片区域内。
  sx,sy,swidth,sheight
  这4个坐标是针对图片元素的,表示图片在canvas画布上显示的大小和位置。sx,sy表示图片上sx,sy这个坐标作为左上角,然后往右下角的swidth,sheight尺寸范围图片作为最终在canvas上显示的图片内容。
  drawImage()方法有一个非常怪异的地方,大家一定要注意,那就是5参数和9参数里面参数位置是不一样的,这个和一般的API有所不同。一般API可选参数是放在后面。但是,这里的drawImage()9个参数时候,可选参数sx,sy,swidth,sheight是在前面的。如果不注意这一点,有些表现会让你无法理解。
在这里插入图片描述
 对于本文的图片压缩,需要用的是是5个参数语法。举个例子,一张图片(假设图片对象是img)的原始尺寸是40003000,现在需要把尺寸限制为400300大小,很简单,原理如下代码示意:

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 300;
// 核心JS就这个
context.drawImage(img,0,0,400,300);

1、如何把系统中图片呈现在浏览器中?

var reader = new FileReader(), img = new Image();
// 读文件成功的回调
reader.onload = function(e) {
    
    
  // e.target.result就是图片的base64地址信息
  img.src = e.target.result;
};
eleFile.addEventListener('change', function (event) {
    
    
    reader.readAsDataURL(event.target.files[0]);
});
复制代码

2、如何把canvas画布转换成img图像
canvas.toDataURL()方法

canvas.toDataURL(mimeType, qualityArgument)

可以把图片转换成base64格式信息,纯字符的图片表示法。

其中:
mimeType表示canvas导出来的base64图片的类型,默认是png格式,也即是默认值是’image/png’,我们也可以指定为jpg格式’image/jpeg’或者webp等格式。

file对象中的file.type就是文件的mimeType类型,在转换时候正好可以直接拿来用(如果有file对象)。
qualityArgument表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92,是一个比较合理的图片质量输出参数,通常情况下,我们无需再设定。

canvas.toBlob()方法

canvas.toBlob(callback, mimeType, qualityArgument)

可以把canvas转换成Blob文件,通常用在文件上传中,因为是二进制的,对后端更加友好。

和toDataURL()方法相比,toBlob()方法是异步的,因此多了个callback参数,这个callback回调方法默认的第一个参数就是转换好的blob文件信息。

将canvas图片转换成二进制的blob文件,然后再ajax上传的,代码如下:

// canvas转为blob并上传
canvas.toBlob(function (blob) {
    
    
  // 图片ajax上传
  var xhr = new XMLHttpRequest();
  // 开始上传
  xhr.open("POST", 'upload.php', true);
  xhr.send(blob);    
});

//HTML代码:
<input id="file" type="file">

//JS代码:
var eleFile = document.querySelector('#file');
// 压缩图片需要的一些元素和对象
var reader = new FileReader(), img = new Image();
// 选择的文件对象
var file = null;
// 缩放图片需要的canvas
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');

// base64地址图片加载完毕后
img.onload = function () {
    
    
    // 图片原始尺寸
    var originWidth = this.width;
    var originHeight = this.height;
    // 最大尺寸限制
    var maxWidth = 400, maxHeight = 400;
    // 目标尺寸
    var targetWidth = originWidth, targetHeight = originHeight;
    // 图片尺寸超过400x400的限制
    if (originWidth > maxWidth || originHeight > maxHeight) {
    
    
        if (originWidth / originHeight > maxWidth / maxHeight) {
    
    
            // 更宽,按照宽度限定尺寸
            targetWidth = maxWidth;
            targetHeight = Math.round(maxWidth * (originHeight / originWidth));
        } else {
    
    
            targetHeight = maxHeight;
            targetWidth = Math.round(maxHeight * (originWidth / originHeight));
        }
    }
        
    // canvas对图片进行缩放
    canvas.width = targetWidth;
    canvas.height = targetHeight;
    // 清除画布
    context.clearRect(0, 0, targetWidth, targetHeight);
    // 图片压缩
    context.drawImage(img, 0, 0, targetWidth, targetHeight);
    // canvas转为blob并上传
    canvas.toBlob(function (blob) {
    
    
        // 图片ajax上传
        var xhr = new XMLHttpRequest();
        // 文件上传成功
        xhr.onreadystatechange = function() {
    
    
            if (xhr.status == 200) {
    
    
                // xhr.responseText就是返回的数据
            }
        };
        // 开始上传
        xhr.open("POST", 'upload.php', true);
        xhr.send(blob);    
    }, file.type || 'image/png');
};

// 文件base64化,以便获知图片原始尺寸
reader.onload = function(e) {
    
    
    img.src = e.target.result;
};
eleFile.addEventListener('change', function (event) {
    
    
    file = event.target.files[0];
    // 选择的文件是图片
    if (file.type.indexOf("image") == 0) {
    
    
        reader.readAsDataURL(file);    
    }
});

上传前还可以预览:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="jquery-1.11.3.min.js"></script>
<script language="javascript"> 
window.onload=function(){
    
    
    var eleFile = document.querySelector('#jjfxSoft_iconPath');
    // 压缩图片需要的一些元素和对象
    var reader = new FileReader(), 
        img = new Image();
    // 选择的文件对象
    var file = null;
    // 缩放图片需要的canvas
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');
    // base64地址图片加载完毕后
    img.onload = function () {
    
    
        debugger
        // 图片原始尺寸
        var originWidth = this.width;
        var originHeight = this.height;
        // 最大尺寸限制
        var maxWidth = 300, maxHeight = 300;
        // 目标尺寸
        var targetWidth = originWidth, targetHeight = originHeight;
        // 图片尺寸超过300x300的限制
        if (originWidth > maxWidth || originHeight > maxHeight) {
    
    
            if (originWidth / originHeight > maxWidth / maxHeight) {
    
    
                targetWidth = maxWidth;
                targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
    
    
                targetHeight = maxHeight;
                targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
        }
            
        // canvas对图片进行缩放
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // 清除画布
        context.clearRect(0, 0, targetWidth, targetHeight);
        // 图片压缩
        context.drawImage(img, 0, 0, targetWidth, targetHeight);
        var type = 'image/jpeg';
        //将canvas元素中的图像转变为DataURL
        var dataurl = canvas.toDataURL(type);
        $("#ceshi1").attr("src",dataurl);
        //抽取DataURL中的数据部分,从Base64格式转换为二进制格式
        var bin = atob(dataurl.split(',')[1]);
        //创建空的Uint8Array
        var buffer = new Uint8Array(bin.length);
        //将图像数据逐字节放入Uint8Array中
        for (var i = 0; i < bin.length; i++) {
    
    
            buffer[i] = bin.charCodeAt(i);
        }
        //利用Uint8Array创建Blob对象
        var blob = new Blob([buffer.buffer], {
    
    type: type});
        var url = window.URL.createObjectURL(blob);
        $("#ceshi").attr("src",url);
    };

    // 文件base64化,以便获知图片原始尺寸
    reader.onload = function(e) {
    
    
        img.src = e.target.result;
    };
    eleFile.addEventListener('change', function (event) {
    
    
        file = event.target.files[0];
        // 选择的文件是图片
        if (file.type.indexOf("image") == 0) {
    
    
            reader.readAsDataURL(file);    
        }
    });
}
</script>
</head>
<body>
<img id="ceshi">
<img id="ceshi1">
<input name="file" type="file" id="jjfxSoft_iconPath">
</body>
</html>

猜你喜欢

转载自blog.csdn.net/qq_38942978/article/details/110549185