Adinnet-Web Adinnet-Web
首页
  • 技术沉淀

    • 技术沉淀
  • 前端文章

    • JavaScript
  • 前端笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 实用技巧
收藏
  • 分类
  • 标签
  • 归档
首页
  • 技术沉淀

    • 技术沉淀
  • 前端文章

    • JavaScript
  • 前端笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 实用技巧
收藏
  • 分类
  • 标签
  • 归档
  • JavaScript文章

  • 学习笔记

  • 技术沉淀

    • CSS矩形绘制
    • 仿微信通讯录
    • 微信小程序订阅消息
    • 保存海报
    • 微信小程序页面弹框
    • 微信小程序在指定距离范围内签到
    • h5嵌套u3d,使用iframe进行交互
    • 前端主导文件处理方法
    • 图片压缩方法封装
      • 金额大写函数
      • 前端主导的小程序一键导航功能
      • uniapp富文本组件(只支持H5)
      • uniapp二次确认弹框组件(依赖于uview)
      • 无缝滚动插件(vue3)
      • H5与unity通信(只针对unity嵌套H5)
      • 辅助触控
      • 关系图
      • h5&svg点赞动效
      • iframe高精地图文件预览
      • 自适应横向瀑布流布局
      • 考试功能
      • 仿小说翻页
      • 富文本
      • h5唤醒App
      • vue3 Count-to数字翻动
      • 小程序图片转base64
      • 第三方应用跳转微信小程序
      • 圆角TabBar
      • 大屏Header
      • Echarts中国地图
      • 使用computed拦截v-model
      • 消息订阅与发布
      • Html相对路径页面跳转
      • Vite打包本地访问
      • H5主题切换
      • 移动端列表分页
      • 每次进入页面都触发的功能(v3)
      • 智能导诊
      • js中几个优雅的运算符使用技巧
      • 其他CSS伪元素
      • 微信浏览器保存canvas海报
      • uniappH5手动拖拽缩放自定义绘制海报
      • uniapp小程序盒子拖拽排序
      • 微信小程序地图的使用
      • css静态漏斗绘制
      • 微信小程序图片流处理
      • ios时间问题
      • 文字围绕效果
      • 表格树动态计算
      • React中useEffect用法
      • React Hooks 陷阱
      • Naive UI修改默认样式
      • vue 根据div id 滚动到指定view到可视视图中
      • js将[1,2,3]排列组合成[1.12.123]
      • 移动端如何加载vite导出dist包
      • TS探索接口、泛型和自定义类型
      • WebSocket中加入Token
      • 幂方程指数衰减
      • pageSpy
      • 表格多条件搜索
      • axios get 请求 url 转码 空格转成+,导致请求失败
      • NaiveUI使用Message组件遇到的问题记录
      • 小程序多盒子拖拽排序
      • 对象快速筛key方法
      • 倒计时
      • nuxt3中的useAsyncData使用详解
      • nuxt3文件式路由
      • 播放amr格式音频
      • echarts瀑布图
      • vue中使用vueuse进行文件导出
      • 分享一个数据整理方法
      • naiveui表格shift多选
      • 数组递归转tree
      • 自定义指令图片懒加载
      • 将数组里面的对象转换成我们需要的键值对
      • 亚马逊云s3上传
      • 上拉加载更多封装
      • JS设计模式总结笔记
      • 适配移动端页面顶部安全区域
      • 【CryptoJS】使用介绍
      • 微信小程序富文本图片点击放大
      • 微信小程序省市区级联选择
      • uniapp拖动排序插件
      • element ui 的树形结构懒加载,局部更新
      • 表单搜索过滤空值
      • 判断设备类型
      • tsconfig配置打包问题
      • vant-uploader上传组件添加长按保存图片
      • BroadcastChannel跨页面通信
      • pnpm安装问题
      • echart阶梯图形绘制
      • js根据对象拼接参数
      • 集成免密登录
      • 输入框输入数字限制
      • js控制全局css变量
      • 流程图
      • 修改npm包
      • tsx在vue3中的应用
      • 109video播放视频流
      • echart默认展示某个点的tooltip
      • 大屏适配几种方案
      • 表单低代码自定义列表页
      • 表单低代码列表页配置端代码
      • 低代码平台使用的一些好用的js方法
      • vue3cookie的使用
      • 原生js下载文件
      • stompjs 创建socket,断线重连机制
      • iframe作为内嵌网页cookie设置
      • 前端对文件内容解析生成特定算法哈希值方法
      • vue3中前端自定义命名文件名称下载文件的方法
      • 前端项目中权限判断的方法配合路由守卫使用
      • 原生table:表格table中thead固定,tbody超出高度出现滚动条
      • vue中使用原生的方法
      • vue3中amchart的初步使用
      • base64图片加水印
      • 手写签名
      • base64转doc文件
    • 前端
    • 技术沉淀
    黄梨梨
    2023-07-05
    目录

    图片压缩方法封装

    # 1.应用场景

    # 对图片上传的一种优化处理方法 因公司项目数据涉及到的各类封面实景等图片,原始图片有的几兆甚至几十兆大小,故给系统上传图片组件增加了可设置质量、宽度、高度三个维度的参数,来校准合适的图片大小和效果。

    先封装一下压缩图片的方法compressImg(),接收一个参数对象,对象有五个属性分别为fileObj图片、quality质量、width宽度、height高度、callback回调函数, 先实例化一个image对象,然后设置src属性,监听其加载成功或失败事件。

    function compressImg (res = {}) {
        try {
            // 定义默认输出图片类型
            let type = 'image/png'
            // 创建image对象
            const image = new Image()
            // 这里做了个判断,可以直接传入图片地址。
            if (typeof(res.fileObj) === "object") {
              image.src = window.URL.createObjectURL(res.fileObj)
              if (res.fileObj.type) {
                  type = res.fileObj.type
              } // 携带原类型
            } else {
              image.src = res.fileObj
            }: res.fileObj
            image.onload = function() {
                // ...
            }
            image.onerror = function() {
              res.callback(false) // 失败
            }
        } catch () {
            res.callback(false) // 失败
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25

    当图片加载完成后,先保存图片的原始宽高,如果有分别指定宽和高,直接使用参数覆盖。 如果只设置了宽,那么则以指定的宽度为基准,乘原始宽高的比例,获取等比例的高度,反之亦然。

     image.onload = function() {
            let w = this.width // 当前图片宽
            let h = this.height // 当前图片高
            if (res.width && res.height) { // 如果宽高都指定
                w = res.width
                h = res.height
            } else if (res.width || res.height) { // 如果指定其一
                if (res.width > res.height) {
                  h = res.width * (h / w)
                  w = res.width
                } else {
                  w = res.height * (w / h)
                  h = res.height
                }
            }
            // ...
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    图片宽高确定后,通过document.createElement('canvas')创建一个canvas画布,getContext()获取绘图环境,setAttributeNode()设置绘图区域宽高属性,然后使用drawImage()方法将图片插入到canvas画布中,最后通过toDataURL()方法将canvas转换为base64编码,到这里拿到base64基本已经完成功能了,可根据个人需求将其转换成不同的文件流格式

     image.onload = function() {
            // ...
            const canvas = document.createElement('canvas') // 创建一个canvas
            const ctx = canvas.getContext('2d')  // 获取绘图环境
            // 创建属性节点
            const anw = document.createAttribute('width')
            anw.nodeValue = w
            const anh = document.createAttribute('height')
            anh.nodeValue = h
            canvas.setAttributeNode(anw)
            canvas.setAttributeNode(anh)
            // 设置图片
            ctx.drawImage(this, 0, 0, w, h)
            // canvas转换字节流并设置质量
            const data = canvas.toDataURL(type, parseFloat(res.quality))
            // base64转换为Blob对象
            const newFile = convertBase64UrlToBlob(data)
            // 执行回调
            res.callback(newFile)
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20

    我们要将图片转换成文件对象上传到服务器,封装了convertBase64UrlToBlob()方法将base64转换为Blob对象,Blob对象可以通过new window.File()转换为file文件对象,方便以fromData格式提交。

     function convertBase64UrlToBlob(dataurl) {
        const bytes = window.atob(dataurl.split(',')[1]) // 去掉url的头,并转换为byte
        // 处理异常,将ascii码小于0的转换为大于0
        const ab = new ArrayBuffer(bytes.length)
        const ia = new Uint8Array(ab)
        for (let i = 0; i < bytes.length; i++) {
            ia[i] = bytes.charCodeAt(i)
        }
        return new Blob([ab], { type: 'image/png' })
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    方法封装完成后可以开始调用了,先准备几个要使用的HTML标签。 通过input.file标签选择图片,监听change事件在获取到图片后使用window.URL.createObjectURL()将图片对象转为浏览器临时路径,先把原图展示出来,并保存原图对象。

    <html>
        <div id="fileList">
        </div>
    </html>
    <script>
        // 压缩图片
        compressImg({
            fileObj: file, // 图片对象
            width: widthNode.value, // 图片宽度
            height: heightNode.value, // 图片高度
            quality: qualityNode.value, // 图片质量
            callback: function (val) {
                if (val) {
                    // 裁剪成功,将Blob转换为file对象
                    let newfile = new window.File([val], file.name, { type: file.type })
                    // 插入到页面上
                    fileList.innerHTML =  `
                        <div class="list-item">
                          <div class="list-img">
                            <img src="${window.URL.createObjectURL(newfile)}">
                          </div>
                          <div class="list-tips">
                            <div>图片名称:${newfile.name}</div>
                            <div>图片大小:${sizeInit(newfile.size) }</div>
                          </div>
                        </div>` + fileList.innerHTML
                } else {
                  // 裁剪失败
                  alert("裁剪失败!")
                }
            }
        })
    </script>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

    # 非dom方法也是同理,非常好用

    上次更新: 2023/07/06, 09:51:30
    前端主导文件处理方法
    金额大写函数

    ← 前端主导文件处理方法 金额大写函数→

    最近更新
    01
    base64转doc文件
    01-03
    02
    手写签名
    01-03
    03
    base64图片加水印
    01-03
    更多文章>
    Theme by Vdoing | Copyright © 2023-2025 Adinnet
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式