赞
踩
目录
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() {
- // 创建 canvasId
- if (!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 H5
- if (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高度-y
- destWidth: 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 为 base64
- resolve(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()方法参数 |
参数名 | 类型 | 必填 | 默认值 | 说明 |
---|---|---|---|---|
src | String / Array | 是 | - | 待压缩的图片地址,由相册选择或拍照获取。注意:若src 的值为String 压缩成功后则返回String ,若为Array ,压缩成功后则返回Array |
maxSize | Number | 否 | 1080 | 压缩后的最大尺寸 |
fileType | String | 否 | 'png' | 压缩后的文件类型,可选值 jpg、png |
quality | Number | 否 | 0.9 | 压缩后的质量(仅jpg类型有效,原因可自行阅读官方canvas文档),可选值 0 ~ 1,值越大越清晰(图片也越大) |
minSize | Number | 否 | 640 | 最小压缩尺寸,图片尺寸小于该时值不压缩,非H5平台有效。若想忽略该设置可以将该值设置为一个极小的值,比如一个负数(不能是0) |
为使插件在 H5 平台统一返回 base64 数据,则故意取消 H5 平台对 minSize 的设置。H5平台压缩后的图片路径是 base64 格式,有跨平台需求须注意
参数名 | 类型 | 说明 |
---|---|---|
done | Number | 已完成压缩的数量 |
fail | Number | 压缩失败的数量 |
count | Number | 总共需要压缩的数量 |
-
- // 单张压缩
- 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)=>{
- // 压缩成功回调
- })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。