uniapp --- 实现图片压缩(兼容H5)

embedded/2024/9/23 14:26:15/

目录

创建组件

在 template 中添加组件

方法说明:

compress() 方法参数:

progress 方法回调对象属性详细说明:

源码示例: 

 thank


Canvas 是 HTML5 提供的一个用于在网页上绘制图形的元素,它可以实现图片压缩的功能。而结和UnoApp是一种基于Canvas的图形编辑工具库,它提供了丰富的API和功能,可以帮助开发者在网页上实现各种图形编辑和处理操作。

实现图片压缩的原理在结和UnoApp中也是类似的,主要是通过Canvas的绘图功能来重新绘制图片并调整尺寸和质量。下面将详细介绍结和UnoApp实现图片压缩的步骤:

创建组件
<template><view class="compress" v-if="canvasId"><canvas :canvas-id="canvasId" :style="{ width: canvasSize.width, height: canvasSize.height }"></canvas></view>
</template><script>
export default {data() {return {pic: '',canvasSize: {width: 0,height: 0},canvasId: ''};},mounted() {// 创建 canvasIdif (!uni || !uni._helang_compress_canvas) {uni._helang_compress_canvas = 1;} else {uni._helang_compress_canvas++;}this.canvasId = `compress-canvas${uni._helang_compress_canvas}`;},methods: {// 压缩compressFun(params) {return new Promise(async (resolve, reject) => {// 等待图片信息let info = await this.getImageInfo(params.src).then((info) => info).catch(() => null);if (!info) {reject('获取图片信息异常');return;}// 设置最大 & 最小 尺寸const maxSize = params.maxSize || 1080;const minSize = params.minSize || 640;// 当前图片尺寸let { width, height } = info;// 非 H5 平台进行最小尺寸校验// #ifndef H5if (width <= minSize && height <= minSize) {resolve(params.src);return;}// #endif// 最大尺寸计算//(图像的宽度和高度是否超过最大尺寸。如果其中任一维度超过最大尺寸,代码将对图像进行调整,以使其适应最大尺寸并保持其宽高比。)// 这样可以确保图像在调整大小后仍保持原始比例,并且不会超过指定的最大尺寸if (width > maxSize || height > maxSize) {if (width > height) {height = Math.floor(height / (width / maxSize));width = maxSize;} else {width = Math.floor(width / (height / maxSize));height = maxSize;}}// 设置画布尺寸this.$set(this, 'canvasSize', {width: `${width}px`,height: `${height}px`});// Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新setTimeout(() => {// 创建 canvas 绘图上下文(指定 canvasId)。在自定义组件下,第二个参数传入组件实例this,以操作组件内 <canvas/> 组件// Tip: 需要指定 canvasId,该绘图上下文只作用于对应的 <canvas/>const ctx = uni.createCanvasContext(this.canvasId, this);// 清除画布上在该矩形区域内的内容。(x,y,宽,高)ctx.clearRect(0, 0, width, height);// 绘制图像到画布。(所要绘制的图片资源,x,y,宽,高)ctx.drawImage(info.path, 0, 0, width, height);// 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。// 本次绘制是否接着上一次绘制,即reserve参数为false,则在本次调用drawCanvas绘制之前native层应先清空画布再继续绘制;若reserver参数为true,则保留当前画布上的内容,本次调用drawCanvas绘制的内容覆盖在上面,默认 false// 绘制完成后回调ctx.draw(false, () => {// 把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径。在自定义组件下,第二个参数传入自定义组件实例,以操作组件内 <canvas> 组件。uni.canvasToTempFilePath({x: 0, //画布x轴起点(默认0)y: 0, //画布y轴起点(默认0)width: width, //画布宽度(默认为canvas宽度-x)height: height, //画布高度(默认为canvas高度-ydestWidth: width, //图片宽度(默认为 width * 屏幕像素密度)destHeight: height, //输出图片高度(默认为 height * 屏幕像素密度)canvasId: this.canvasId, //画布标识,传入 <canvas/> 的 canvas-id(支付宝小程序是id、其他平台是canvas-id)fileType: params.fileType || 'png', //目标文件的类型,只支持 'jpg' 或 'png'。默认为 'png'quality: params.quality || 0.9, //图片的质量,取值范围为 (0, 1],不在范围内时当作1.0处理success: (res) => {// 在H5平台下,tempFilePath 为 base64resolve(res.tempFilePath);},fail: (err) => {reject(null);}},this);});}, 300);});},// 获取图片信息getImageInfo(src) {return new Promise((resolve, reject) => {uni.getImageInfo({src,success: (info) => {resolve(info);},fail: (err) => {console.log(err, 'err===获取图片信息');reject(null);}});});},// 批量压缩async compress(params) {// 初始化状态变量let [index, done, fail] = [0, 0, 0];let paths = [];// 处理待压缩图片列表let waitList = Array.isArray(params.src) ? params.src : [params.src];// 批量压缩方法let batch = async () => {while (index < waitList.length) {try {const path = await next();done++;paths.push(path);params.progress?.({ done, fail, count: waitList.length });} catch (error) {fail++;params.progress?.({ done, fail, count: waitList.length });}index++;}};// 单个图片压缩方法let next = () => {const currentSrc = waitList[index];return this.compressFun({src: currentSrc,maxSize: params.maxSize,fileType: params.fileType,quality: params.quality,minSize: params.minSize});};// 返回Promise并处理结果return new Promise((resolve, reject) => {try {batch().then(() => {if (typeof params.src === 'string') {resolve(paths[0]);} else {resolve(paths);}}).catch((error) => {reject(error);});} catch (error) {reject(error);}});}}
};
</script><style lang="scss" scoped>
.compress {position: fixed;width: 12px;height: 12px;overflow: hidden;top: -99999px;left: 0;
}
</style>

在 script 中引用组件

import helangCompress from '../../components/helang-compress/helang-compress';export default {components: {helangCompress}
}
在 template 中添加组件
<helang-compress ref="helangCompress"></helang-compress>
方法说明:
方法名可传参数必填说明
compress()Object【单张压缩】设置压缩的图片及压缩尺寸和压缩质量,参数详情请阅读下方 compress()方法参数
compress() 方法参数:
参数名类型必填默认值说明
srcString / Array-待压缩的图片地址,由相册选择或拍照获取。注意:若src的值为String压缩成功后则返回String,若为Array,压缩成功后则返回Array
maxSizeNumber1080压缩后的最大尺寸
fileTypeString'png'压缩后的文件类型,可选值 jpg、png
qualityNumber0.9压缩后的质量(仅jpg类型有效,原因可自行阅读官方canvas文档),可选值 0 ~ 1,值越大越清晰(图片也越大)
minSizeNumber640最小压缩尺寸,图片尺寸小于该时值不压缩,非H5平台有效。若想忽略该设置可以将该值设置为一个极小的值,比如一个负数(不能是0)

为使插件在 H5 平台统一返回 base64 数据,则故意取消 H5 平台对 minSize 的设置。H5平台压缩后的图片路径是 base64 格式,有跨平台需求须注意

progress 方法回调对象属性详细说明:
参数名类型说明
doneNumber已完成压缩的数量
failNumber压缩失败的数量
countNumber总共需要压缩的数量
源码示例: 

// 单张压缩
this.$refs.helangCompress.compressFun({src:this.paths[0],maxSize:800,fileType:'jpg',quality:0.85,minSize:640 //最小压缩尺寸,图片尺寸小于该时值不压缩,非H5平台有效。若需要忽略该设置,可设置为一个极小的值,比如负数。
}).then((res)=>{// 压缩成功回调
}).catch((err)=>{// 压缩失败回调
})// 批量压缩
this.$refs.helangCompress.compress({src:this.paths,maxSize:800,fileType:'jpg',quality:0.85,progress:(res)=>{console.log('压缩进度');console.log(res);}
}).then((res)=>{// 压缩成功回调
}).catch((err)=>{// 压缩成功回调
})
 thank

图片压缩 - 可以自定义压缩尺寸和压缩质量 - DCloud 插件市场


http://www.ppmy.cn/embedded/4883.html

相关文章

【前端】1. HTML【万字长文】

HTML 基础 HTML 结构 认识 HTML 标签 HTML 代码是由 “标签” 构成的. 形如: <body>hello</body>标签名 (body) 放到 < > 中大部分标签成对出现. <body> 为开始标签, </body> 为结束标签.少数标签只有开始标签, 称为 “单标签”.开始标签和…

ElementPlus el-form多选框校验默认触发问题

multiple自动触发了change事件 <el-form-item label"代码路径" prop"path_id"><el-selectv-model"editform.path_id"clearablefilterablemultipleplaceholder"代码路径"><el-optionv-for"item in (selectsData?.…

国产化里程碑:明道云HAP私有部署版获信创评估证书,荣登会员单位

近期&#xff0c;明道云HAP私有部署版荣获信创产品评估证书&#xff0c;这一成就不仅标志着我们在信创领域的深入布局和持续努力获得了行业的广泛认可&#xff0c;也是对我们积极拥抱和推动国产化技术发展的肯定。更值得一提的是&#xff0c;我们还被授予“成员单位”的称号&am…

部署ELFK+zookeeper+kafka架构

目录 前言 一、环境部署 二、部署ELFK 1、ELFK ElasticSearch 集群部署 1.1 配置本地hosts文件 1.2 安装 elasticsearch-rpm 包并加载系统服务 1.3 修改 elasticsearch 主配置文件 1.4 创建数据存放路径并授权 1.5 启动elasticsearch是否成功开启 1.6 查看节点信息 …

【Linux】提升Linux命令行效率:光标移动和文本操作的键盘快捷键

Just 那么年少 还那么骄傲 两眼带刀 不肯求饶 即使越来越少 即使全部都输掉 也要没心没肺地笑 Just 那么年少 我向你招手 让你看到 我混账到老 天涯海角 天荒地老 只等你摔杯为号 &#x1f3b5; 朴树《Forever Young》 Linux命令行界面&#xff08;CLI&am…

探索设计模式的魅力:融合AI大模型与函数式编程、开启智能编程新纪元

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索AI大模型与函数式编程模式融合之旅✨ 在编程世界的广阔疆域里&#xff0c;两大…

JVM常见面试题

1. 什么是JVM JVM指的是Java虚拟机&#xff0c;本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件&#xff0c;作用是为了支持跨平台特性JVM的功能有三项&#xff1a;第一是解释执行字节码指令&#xff1b;第二是管理内存中对象的分配&#xff0c;完…

C++智能指针(二十)

一.RAII&#xff08;Resource Acquisition Is Initialization&#xff09; RAII资源获取即初始化&#xff0c;RAII的思想就是在构造时初始化资源&#xff0c;或者托管已经构造的资源。在析构的时候释放资源。一般不允许复制或赋值&#xff0c;并且提供若干的资源访问的方法。比…