Vue中用canvas对图片上传前压缩

图片压缩上传

场景:如用户头像等

对于大尺寸图片的上传,在前端进行压缩除了省流量外,最大的意义是极大的提高了用户体验。

两方面:

  1. 由于上传图片尺寸比较小,因此上传速度会比较快,交互会更加流畅,同时大大降低了网络异常导致上传失败风险。
  2. 很多网站的图片上传功能都会对图片的大小进行限制,尤其是头像上传,限制5M或者2M以内是非常常见的(但是我用单反拍了个头像,照片超过2M很正常,要对图片进行处理才能上传)。如果可以在前端进行压缩,则理论上对图片尺寸的限制是没有必要的。

在这里插入图片描述

示例:

主要技术:使用canvasdrawImage()方法。(附:canvas.toDataURL()或者canvas.toBlob()

ctx.drawImage(image, dx, dy);
ctx.drawImage(image, dx, dy, dWidth, dHeight);
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

示例:

// 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);    
    }
});

注意

移动端会出现图片变形,需要根据设备的dpr对canvas进行放大,再用css进行强制恢复

// 获取设备dpr
getPixelRatio: function(context) {
    let backingStore = context.backingStorePixelRatio ||
    context.webkitBackingStorePixelRatio ||
    context.mozBackingStorePixelRatio ||
    context.msBackingStorePixelRatio ||
    context.oBackingStorePixelRatio ||
    context.backingStorePixelRatio || 1;
    return (window.devicePixelRatio || 1) / backingStore;
}

// 大概这样
const ctx = this.canvas.getContext("2d");
const dpr = this.getPixelRatio(ctx);
this.$refs.postImg.crossOrigin = "Anonymous";
var oldWidth = this.canvas.width;
var oldHeight = this.canvas.height;
this.canvas.style.width = oldWidth + 'px'; 
this.canvas.style.height = oldHeight + 'px';
this.canvas.width = oldWidth * dpr;
this.canvas.height = oldHeight * dpr;
ctx.scale(dpr, dpr);

//进行正常的操作
ctx.drawImage(this.$refs.cropImg, 0, 0, 250, 400);

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用一些库或工具来压缩图片大小,然后再进行文件上传。以下是一种常见的方法: 1. 首先,您可以使用`HTML5 Canvas`来进行图片的压缩。您可以将图像绘制到一个临时的Canvas中,然后在导出之调整其尺寸。这可以通过以下步骤实现: ```javascript function compressImage(file, maxWidth, maxHeight, quality) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = function (event) { const img = new Image(); img.src = event.target.result; img.onload = function () { const canvas = document.createElement('canvas'); let width = img.width; let height = img.height; if (width > height) { if (width > maxWidth) { height *= maxWidth / width; width = maxWidth; } } else { if (height > maxHeight) { width *= maxHeight / height; height = maxHeight; } } canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, width, height); canvas.toBlob(function (blob) { resolve(blob); }, file.type, quality); }; }; reader.onerror = function (error) { reject(error); }; reader.readAsDataURL(file); }); } ``` 上述函数`compressImage`接受四个参数:`file`为要压缩的图片文件,`maxWidth`和`maxHeight`为期望的最大宽度和高度,`quality`为压缩质量(0-1之间的值,1表示最高质量)。 2. 然后,您可以使用`axios`或其他网络请求库将压缩后的图片文件上传到服务器。 ```javascript const formData = new FormData(); formData.append('file', compressedImageFile); axios.post('/upload', formData) .then(response => { console.log('上传成功'); }) .catch(error => { console.error('上传失败', error); }); ``` 上述代码将压缩后的图片文件添加到`FormData`对象中,然后使用`axios.post`方法将其上传到服务器的`/upload`接口。 请注意,以上代码仅为示例,您可能需要根据您的具体需求进行适当调整。另外,您还可以使用其他基于Canvas的图片处理库或基于HTML5 File API的库来完成相同的任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值