当前位置:首页 > 网站技术 > 前端技术 > 正文内容

使用Javascript对图片进行定宽或定高压缩处理

小彬2021-01-13前端技术106

使用Javascript对图片进行定宽或定高压缩处理

本文参考了以下链接

https://www.jb51.net/article/182078.htm 

https://www.cnblogs.com/xzybk/p/11593269.html

的思路和代码,在此对作者表示感谢

主要思路:

  • 通过原生的input标签拿到要上传的图片文件

  • 将图片文件转化成img元素标签

  • 在canvas上压缩绘制该HTMLImageElement

  • 将canvas绘制的图像转成blob文件

  • 最后将该blob文件传到服务端


1、通过原生的input标签拿到要上传的图片文件

<input class="file" type="file" accept="image">
<script>
        // 第一步
    var file=document.querySelector('.file');
    file.addEventListener('change',function(){
        console.log(file.files[0],'拿到上传的图片全部属性')
    })
</script>

使用Javascript对图片进行定宽或定高压缩处理


2、将图片文件转化成img元素标签

拿到图片文件后,先将其转成HTMLImageElement,也就是普通的img标签,具体要使用 FileReader构造函数。

先new出来一个img和fileReader的实例,通过fileReader的 readAsDataURL这个api,来读取图片文件,其返回值是一个编码后的base64的字符串,然后将这个字符串赋值给img的src属性上,这样就完成了图片文件到 HTMLImageElement的转化。

<input class="file" type="file" accept="image">

<script>
    var file=document.querySelector('.file');
    file.addEventListener('change',function(){
        console.log(file.files[0],'拿到上传的图片全部属性')
        
        // 第二步
        if(window.FileReader) {
            var reader=new FileReader()
            console.log(reader,'FileReader构造函数')
            // 这个地方 必须是file.files[0],否则会报错
            reader.readAsDataURL(file.files[0])
            reader.onloadend =function (e){
                image.src=e.target.result;
                console.log(img,'拿到图片路径是base64的图片')
            }
        }
    })
</script>

使用Javascript对图片进行定宽或定高压缩处理



3、在canvas上压缩绘制该HTMLImageElement

拿到转化后的img元素后,先取出该元素的宽高度,这个宽高度就是实际图片文件的宽高度。

然后定义一个最大限度的宽高度,如果超过这个限制宽高度,则进行等比例的缩放

计算好将要压缩的尺寸后,创建canvas实例,设置canvas的宽高度为压缩计算后的尺寸,并将img绘制到上面

<input class="file" type="file" accept="image">
<img class="image" src="" alt="">
<div class="canvas-div"></div>

<script>
    var file=document.querySelector('.file');
    var image=document.querySelector(".image")  //注意别和后面的new的image混淆了。此处是我获取文档定义的image标签
    file.addEventListener('change',function(){
        // 第一步
        console.log(file.files[0],'拿到上传的图片全部属性')

        // 第二步
        var img=new Image() //创建一个Image对象:
        if(window.FileReader) {
            var reader=new FileReader()
            console.log(reader,'FileReader构造函数')
            // 这个地方 必须是file.files[0],否则会报错
            reader.readAsDataURL(file.files[0])
            reader.onloadend =function (e){
                img.src=e.target.result;
                console.log(e.target.result,'拿到图片路径是base64的图片')

                // 第三步
                var { width: originWidth,height:originHeight} = img
                console.log(originWidth,originHeight)
                // 最大尺寸限制  此处看个人需求设置
                const maxWidth = 400,maxHeight = 400
                // 需要压缩的目标尺寸
                let targetWidth = originWidth, targetHeight = originHeight
                if(originWidth>maxWidth || originHeight>maxHeight){
                    console.log(originWidth /originHeight >1,'宽高比')
                    if(originWidth / originHeight >1){
                        targetWidth=maxWidth
                        targetHeight=Math.round(maxWidth /(originWidth /originHeight))
                        console.log(targetWidth,targetHeight,maxWidth /(originWidth /originHeight),'根据定宽')
                    }else{
                        targetHeight=maxHeight
                        targetWidth=Math.round(maxHeight *(originWidth /originHeight))
                        console.log(targetWidth,targetHeight,maxHeight *(originWidth /originHeight),'根据定高')
                    }
                    // 计算好将要压缩的尺寸后,创建canvas实例,设置canvas的宽高度为压缩计算后的尺寸,并将img绘制到上面
                    // 创建画布
                    var canvas=document.createElement('canvas');
                    var context=canvas.getContext('2d');
                    var wrap=document.querySelector('.canvas-div');
                    // 设置宽高度为等同于要压缩图片的尺寸
                    canvas.width=targetWidth;
                    canvas.height=targetHeight;
                    context.clearRect(0, 0, targetWidth, targetHeight)
                    
                    //将img绘制到画布上 此处使用离屏canvas技术(提高性能的一种技术方法)
                    context.drawImage(img, 0, 0, targetWidth, targetHeight)
                    
                    // 展现在demo页面中,查看压缩过后的效果
                    wrap.appendChild(canvas)


                }
            }
        }

        
    })
</script>

使用Javascript对图片进行定宽或定高压缩处理


4、将canvas绘制的图像转成blob文件

canvas.toBlob(function(blob) { console.log(blob)}, 'image/png')

使用Javascript对图片进行定宽或定高压缩处理


5、最后将该blob文件传到服务端

最后对代码进行优化封装

    <input class="file" type="file" accept="image">
    <img class="image" src="" alt="">
    <div class="canvas-div"></div>
    
    <script>
        var file=document.querySelector('.file');
        var image=document.querySelector(".image")
        file.addEventListener('change',function(){
            // 第一步
            console.log(file.files[0],'拿到上传的图片全部属性')
            upload(file.files[0]).catch(e => console.log(e))

            
        })
        async function upload(file){
            // 第二步
            const img = await readImg(file)
            // 第三步
            const blob = await compressImg(img,file.type,500,500)
             // 输出压缩图片大小
            console.log(blob,byteKB(blob.size)+'KB',byteKB(file.size)+'KB','blob')
            
            
        }
       
        // 压缩前将file转换成img对象
        function readImg(file) {
            return new Promise((resolve, reject) => {
                const img = new Image()
                if(window.FileReader) {
                    const reader = new FileReader()
                    reader.onload = function(e) {
                        img.src = e.target.result
                    }
                    reader.onerror = function(e) {
                        reject(e)
                    }
                    reader.readAsDataURL(file)
                        img.onload = function() {
                            console.log(img,'拿到图片路径是base64的图片')
                        resolve(img)
                    }
                    img.onerror = function(e) {
                        reject(e)
                    }
                }
            })
        }
        
        // 自定义封装的根据定宽或定高压缩图片  
        function compressImg(imgAttr,type,mxW,mxH){
            return new Promise((resolve, reject) => {
            var { width: originWidth,height:originHeight} = imgAttr
            console.log(originWidth,originHeight,'宽高')
            // 最大尺寸限制
            const maxWidth = mxW,maxHeight = mxH
            // 需要压缩的目标尺寸
            let targetWidth = originWidth, targetHeight = originHeight
            if(originWidth>maxWidth || originHeight>maxHeight){
                console.log(originWidth /originHeight >1,'宽高比')
                if(originWidth / originHeight >1){
                    targetWidth=maxWidth
                    targetHeight=Math.round(maxWidth /(originWidth /originHeight))
                    console.log(targetWidth,targetHeight,maxWidth /(originWidth /originHeight),'根据定宽')
                }else{
                    targetHeight=maxHeight
                    targetWidth=Math.round(maxHeight *(originWidth /originHeight))
                    console.log(targetWidth,targetHeight,maxHeight *(originWidth /originHeight),'根据定高')
                }
                // 计算好将要压缩的尺寸后,创建canvas实例,设置canvas的宽高度为压缩计算后的尺寸,并将img绘制到上面
                // 创建画布
                var canvas=document.createElement('canvas');
                var context=canvas.getContext('2d');
                var wrap=document.querySelector('.canvas-div');
                // 设置宽高度为等同于要压缩图片的尺寸
                canvas.width=targetWidth;
                canvas.height=targetHeight;
                // context.clearRect(0, 0, targetWidth, targetHeight)
                //将img绘制到画布上
                context.drawImage(imgAttr, 0, 0, targetWidth, targetHeight)

                // 展现在demo页面中,查看压缩过后的效果
                wrap.appendChild(canvas)
                // canvas转为blob并上传
                                 canvas.toBlob(function (blob) {
                                      // 图片ajax上传
                                      var xhr = new XMLHttpRequest();
                                      // 开始上传
                                      xhr.open("POST", 'action.php', true);  
                                      //可以自己配置一下action.php文件,接收到该页面发送的file文件
                                      // <?php
                                      //     $action = $_GET['file'];
                                      //      echo $action
                                      // ?>
                                      xhr.send(blob);
                                 }, type || 'image/png');                
                                 
                                
                //canvas.toBlob(function(blob) { 
                //    resolve(blob)
                //}, type || 'image/jpg')
             }
            })
        }

         //对size取kb的两位小数
        function byteKB(size){
            return (size/1024).toFixed(2)
        }
    </script>


最后总结:

我发现压缩大图结果确实比原来内存小了,但是压缩小的图片(50kb以下)就反而比原来文件大。

所以使用的话,建议去压缩上百kb的文件,可以加个判断验证,小的就不用压缩。

最后一点,就是目前是根据定宽或定高来进行图片压缩,最好的压缩应该是根据设定的图片大小压缩图片至最优。

目前已经有成功的插件( https://github.com/WangYuLue/image-conversion),后面我会抽时间自己研究写一个出来


标签: javascript
分享给朋友:

相关文章

meta标签功能之兼容主流浏览器

meta标签功能之兼容主流浏览器

其实一般新手估计都不会注意这个问题,新手大多都会迫不及待的为了实现网页而去重视代码,往往忽视最重要的meta标签,我就是这样,我也是做了两年的前端才算发现这个里面有很大的学问我最近在一个人独自开发一个...

HTTP之功能追加协议以及升级http2.0

HTTP之功能追加协议以及升级http2.0

1、影响http网络请求的因素带宽 延迟2、http协议的瓶颈一条连接上只可发送一个请求请求只能从客户端开始,客户端不可以接受除响应以外的指令请求/响应头部冗余,不经压缩就发送每次互相发送相...

使用rem做手机端网页自适应

使用rem做手机端网页自适应

利用原生js做手机端网页自适应解决方案rem布局刚开始我用的是下面这段代码,然后js通过外部链接引入,最后每次用手机刷新网页的时候都会出现缩略图function getRem(pwidth,...

Vue.js 框架最为核心的 Virtual DOM 是如何实现的?

Vue.js 框架最为核心的 Virtual DOM 是如何实现的?

1、虚拟DOMVirtual DOM :由普通的js对象来描述DOM对象,因为不是真实的DOM对象,所以叫虚拟DOMSnabbdom 就是Vue使用的虚拟DOM框架1)真实DOM成员 let...

Webpack原理与实践从零到掌握

Webpack原理与实践从零到掌握

 Webpack 以模块化思想为核心,帮助开发者更好的管理整个前端工程。1、快速上手webpack1、初始化package.json,并安装webpacknpm init ...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

分享:

支付宝

微信