uniapp图片裁剪插件开发整理

2023-11-12

工作之余,把工作中需要用的一个小工具封装成uniapp插件分享给大家!!! 

图片裁剪 

使用场景:

  • 头像裁剪、对照片尺寸有特定要求的;

实现思路:

  1. 布局: 做上下两层展示,下层展示一张亮度低一点全图,充当遮住部分(效果可以自定义比如说高斯模糊等);上层展示裁剪部分图片,这里显示原图高亮部分;
  2. 拖拽控制裁剪区域:通过手指拖动来控制裁剪框移动,并动态改变框里的背景图显示位置来做到跟底图同步的效果,放大/缩小框也是同样道理;
  3. 利用canvas绘图功能把需要裁剪的图片绘制到画布上;
  4. 最后保存图片完成裁剪,so easy
插件截图1
插件截图2

实现过程: 

1、首先,把要裁剪的图片渲染到组件里作为底图,并根据视图大小来确定底图的大小和裁剪框可移动的区域范围; 

<view class="image-box" 
    :style="{
        backgroundImage: 'url('+ src +')',
        width: imageBoxWidth + 'px',
        height: imageBoxHeight + 'px',
    }">
        <view class="mask"></view>
    </view>
</view>
windowInfo = uni.getWindowInfo();
uni.getImageInfo({
    src: this.src,
    success: (res) => {
        imageOriginalWidth = res.width;
        imageOriginalHeight = res.height;

        let widthZoomRatio = imageOriginalWidth / windowInfo.windowWidth;
        let heightZoomRatio = imageOriginalHeight / windowInfo.windowHeight;
        imageZoomRatio = widthZoomRatio > heightZoomRatio ? widthZoomRatio : heightZoomRatio;

        this.imageBoxWidth = imageOriginalWidth / imageZoomRatio;
        this.imageBoxHeight = imageOriginalHeight / imageZoomRatio;
        this.setRatio('1:1');
    }
})

2、在底图上方绘制裁剪框(蓝色框),并绑定事件可控制大小和位置,这里为了裁剪框的区域图是高亮的,也需要给裁剪框加一个底图背景;

<view 
    class="cropping-box"
    @touchstart.stop="touchstart"
    @touchmove.stop="touchmove"
    :style="{
        top: cropBoxY + 'px',
        left: cropBoxX + 'px',
        width: cropBoxWidth  + 'px',
        height: cropBoxHeight + 'px',
        backgroundImage: 'url('+ src +')',
        backgroundSize: imageBoxWidth + 'px' + ' ' + imageBoxHeight + 'px',
        backgroundPositionX: (-cropBoxX - 2) + 'px',
        backgroundPositionY: (-cropBoxY - 2) + 'px',
        borderRadius: cropShape == 'rect' ? '' : '50%' 
    }"
    >

常规的通过拖动来调整位置和大小实现:

touchstart(event){
            startX = event.touches[0].clientX;
            startY = event.touches[0].clientY;
            
            if(event.target.dataset.body == "handle"){
                this.mode = 'zoom';
                boxWidth = this.cropBoxWidth;
                boxHeight = this.cropBoxHeight;
            }else {
                this.mode = 'move';
                boxX = this.cropBoxX;
                boxY = this.cropBoxY;
            }
        },
        touchmove(event){
            let distanceX = event.touches[0].clientX - startX;
            let distanceY = event.touches[0].clientY - startY;

            let x = boxX + distanceX;
            let y = boxY + distanceY;
            let width = boxWidth + distanceX;
            let height = boxHeight + distanceY;

            let maxX = this.imageBoxWidth-this.cropBoxWidth;
            let maxY = this.imageBoxHeight-this.cropBoxHeight;
            let maxWidth = this.imageBoxWidth-this.cropBoxX;
            let maxHeight = this.imageBoxHeight-this.cropBoxY;

            switch (this.mode) {
                case 'move':
                    this.cropBoxX = x < 0 ? 0 : (x > maxX ? maxX : x);
                    this.cropBoxY = y < 0 ? 0 : (y > maxY ? maxY : y);
                    break;
                case 'zoom':
                    if(this.cropShape == 'rect'){
                        this.cropBoxWidth = width > maxWidth ? maxWidth : width;
                        this.cropBoxHeight = height > maxHeight ? maxHeight : height;
                    }else{
                        this.cropBoxHeight = height > maxHeight ? maxHeight : height;
                        this.cropBoxWidth = height > maxHeight ? maxHeight : height;
                    }
                    break;
            }
        },

3、再通过用户在界面上操作裁剪框的位置和大小,来确定要裁剪图片的哪个部分;

4、再利用canvas绘制图像并生成base64格式图片;

async cropping(){
            let x = this.cropBoxX * imageZoomRatio;
            let y = this.cropBoxY * imageZoomRatio;
            let w = this.cropBoxWidth * imageZoomRatio;
            let h = this.cropBoxHeight * imageZoomRatio;

            // 方式2: 
            const canvas = uni.createOffscreenCanvas({type: '2d',width: w, height: h});
            const context = canvas.getContext('2d');
            const image = canvas.createImage();
            await new Promise((resolve,reject) => {
                image.onload = resolve
                image.onerror = reject
                image.src = this.src; 
                // image.src = "https://pic4.ntimg.cn/file/20191225/30544261_221404258307_1.jpg"; 
            })
            context.clearRect(0, 0, w, h);
            if(this.cropShape == 'circular'){
                context.beginPath();
                context.arc(w/2,h/2,w/2,0,Math.PI * 2);
                context.fill();
                context.clip();
            }
            context.drawImage(image,x,y,w,h,0, 0, w, h);
            const DataURL = canvas.toDataURL();
            return DataURL;
}

5、最后看一下该插件支持的属性,如果大家有需要可以到uniapp插件库下载使用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uniapp图片裁剪插件开发整理 的相关文章

随机推荐

  • 常见状态码 【最全状态码展示】

    一 什么是状态码 HTTP状态码 HTTP Status Code 是用以表示网页服务器HTTP响应状态的3位数字代码 它由 RFC2616 规范定义的 并得到RFC 2518 RFC 2817 RFC 2295 RFC 2774 RFC
  • C语言 字符指针的定义与初始化

    1 字符指针定义说明 指向字符串的指针称为字符指针 其定义形式为 char 指针名 在定义字符指针的同时为其赋值称为字符指针的初始化 如 void main char p Hello printf s p 定义一个字符指针p 并使指针p得到
  • 如何用最通俗易懂的方式理解假设检验

    https blog csdn net wydyd110 article details 82387653
  • 日本半导体制造商AKM工厂失火停产,市场再次掀起抢货潮!

    数据猿年度重磅活动预告 2020年度金猿策划活动 金猿榜单发布 金猿奖杯颁发 即将推出 尽情咨询期待 大数据产业创新服务媒体 聚焦数据 改变商业 据日本共同社报道 10月20日 旭化成旗下集团公司从事半导体制造的旭化成微电子株式会社 简称
  • C++从0到1(2):数据类型

    目录 1 整型 2 sizeof关键字 3 实型 浮点型 4 字符型 5 转义字符 6 字符串型 7 布尔类型 8 cin 数据的输入 C 规定在创建一个变量或常量时 必须要指定相应的数据类型 否则无法给变量分配内存 数据类型存在的意义 给
  • 富文本编辑器的使用方法

    富文本编辑器又称Rich Text Editor 简称RTE 它不同与文本编辑器 程序员可以到网上下载免费的富文本编辑器嵌于自己设计的网站或者程序里 方便用户编辑文章或者信息 主要用于发新闻类似的东西 它有着和word文档还有网上发论坛插图
  • ssd测试mAP的时候出现tensorflow版本问题,问题 _variable_v2_call() got an unexpected keyword argument ‘collections’

    这个问题是Tensorflow 版本太高导致的 我原来使用的 1 13 1 的版本不行 换成了 1 10 1就可以了
  • 2023年新能源汽车行业研究报告

    第一章 行业概况 新能源汽车 是指采用新型动力系统 完全或者主要依靠新型能源驱动的汽车 包括纯电动汽车 插电式混合动力汽车 增程式混合动力汽车和燃料电池汽车等 国际上 混合动力汽车 含中混 强混 插电式混动 汽车 天然气汽车 纯电动汽车和燃
  • 《一周搞定模电》—基本放大电路

    文章目录 TOC 文章目录 一 三极管放大电路 1 饱和失真和截至失真 2 静态工作点 二 放大电路改进 分压偏置电路 一 三极管放大电路 下图是共发射极放大电路 R8两端的电压值与输入信号是反向关系 仿真图如下所示 1 饱和失真和截至失真
  • MySQL大小写敏感的解决方案

    不同的MySQL版本有不同的默认设定 具体情况需要具体分析 mysql是通过lower case table names参数来控制大小写敏感的 该参数在 mysqld 节点下 具体的含义笔者从官网截了一张图 关于lower case tab
  • 算法:链表数字相加

    算法 链表数字相加 问题 解决 问题 解决 class Solution def mergeNodes self head Optional ListNode gt Optional ListNode init re ListNode 0
  • 项目总结@Repository注解dao层接口扫描不到

    使用 Repository来注解 来注解dao层接口 运行运行项目不能扫描 应该是接触的项目比较少 第一次遇到这种情况 使用 Repository注解mapper接口发现项目运行找不到dao层的东西 我滴个神 以前用着这玩意不是挺好使的嘛
  • hashmap链表转化成红黑树的过程以及红黑树转化成链表的过程

    1 链表转红黑树的实现代码 该方法主要是将单向链表转化成双向链表 为了后面操作 比如在后面将红黑树放到数组上时 以及红黑树转成链表时简化操作 final void treeifyBin Node
  • C语言分别判断大小写英文字母,空格,数字和其他字符的个数

    输入一段字符串 分别判断小写字母 大写字母 数字 空格和其他字符各有几个 ASCII码中空格的ASCII码为32 A为65 a为97 程序代码 include
  • 世纪末的星期

    曾有邪教称1999年12月31日是世界末日 当然该谣言已经不攻自破 还有人称今后的某个世纪末的12月31日 如果是星期一则会 有趣的是 任何一个世纪末的年份的12月31日都不可能是星期一 于是 谣言制造商 又修改为星期日 1999年的12月
  • trap 信号捕获

    trap 信号捕获 命令说明 示例 产生信号 语法 选项说明 命令说明 Trap signals and other events Defines and activates handlers to be run when the shel
  • List去除空元素

    一 Collections singleton 一个用于创建只包含一个元素的不可变集合的方法 创建一个只包含一个值为null的元素的集合 list removeAll Collections singleton null list remo
  • Node.js搭建WEB服务器

    Node js搭建WEB服务器 1 安装Node和nodemon插件 2 引入http模块 3 创建服务监听端口 4 解析接口地址 5 解析get参数 6 解析post参数 1 安装Node和nodemon插件 全局安装nodemon插件
  • 超详细 Springboot 线程池用法一(自用)

    目录 前言 1 EnableAsync 和 Async 很关键 2 Thread 和 Runnable 要谨慎 3 数据类型 线程安全 要牢记 4 Configuration 和 Bean 很方便 5 ThreadPoolExecutor
  • uniapp图片裁剪插件开发整理

    工作之余 把工作中需要用的一个小工具封装成uniapp插件分享给大家 图片裁剪 使用场景 头像裁剪 对照片尺寸有特定要求的 实现思路 布局 做上下两层展示 下层展示一张亮度低一点全图 充当遮住部分 效果可以自定义比如说高斯模糊等 上层展示裁