自制一个H5图片拖拽、裁剪插件(原生JS)

摘要:
前言如今的H5运营活动中,有很多都是让用户拍照或者上传图片,然后对照片加滤镜、加贴纸、评颜值之类的。博主也做过不少,为了省事就封装了一个简单的图片拖拽、裁剪的插件。索性自己搞一个轻量的,只是不支持缩放功能。·调用uploadImageAPI,将之前得到的localId传入,获得serverId。access_token="+accessToken+"&media_id="+serverId;接下来就可以创建image对象,设置src属性,完成拖拽裁切等操作。cutData用于缓存拖动的位置,用于之后的裁剪。

前言

如今的H5运营活动中,有很多都是让用户拍照或者上传图片,然后对照片加滤镜、加贴纸、评颜值之类的。尤其是一些拍照软件公司的运营活动几乎全部都是这样的。

博主也做过不少,为了省事就封装了一个简单的图片拖拽、裁剪的插件。其实网上也有很多类似的插件,只不过有的功能冗余体积大,有的甚至还依赖jquery。索性自己搞一个轻量的,只是不支持缩放功能。

DEMO(手机上看效果比较好,PC上没有兼容处理),原码

实现

这里简略说下实现过程,只截取部分代码片段,有兴趣的可以看下原码,反正也很简单。

图片上传

这个DEMO里使用的上传方式是HTML5的 File Input,但是很多运营活动需要调用微信的上传&拍照接口,由于以前踩过坑这里就啰嗦两句,帮助新人绕开。

· 在 wx.config 中的 jsApiList 属性中添加chooseImage 和uploadImage API。

· 调用 chooseImage API,获得 localId。

wx.chooseImage({
    count: 1, //默认9
    sizeType: ['original', 'compressed'],
    sourceType: ['album', 'camera'],
    success: (res) =>{
        var localIds = res.localIds[0];
        console.log(localIds);
    }
});

需要注意的是这里的 localId 可以通过 img 标签的 src 属性进行展示,但是无法传给服务器接口或者通过 canvas 裁剪,所以还需要上传一步。

· 调用uploadImage API,将之前得到的 localId 传入,获得 serverId。

wx.uploadImage({
    localId: localIds,
    isShowProgressTips: 1,
    success: (res) =>{
        var serverId =res.serverId;
        console.log(serverId);
    }
});

有了 serverId 其实就可以得到保存在微信服务器上的图片了,只是博主之前还去多余的下载一道。

将一开始微信认证时获得的 accessToken与 serverId 拼接到下面的链接即可直接引用

const imgUrl = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=" + accessToken + "&media_id=" + serverId;

接下来就可以创建 image 对象,设置 src 属性,完成拖拽裁切等操作。

初始化

首先要对图片的尺寸进行调整:

· 若图片宽高比比容器的大,即图片比容器“扁”,就让图片的高度与容器保持一致,宽度自动适应保持原图比例不变

· 若图片宽高比比容器的小,即图片比容器“瘦”,就让图片的宽度与容器保持一致,高度自动适应保持原图比例不变

为了便于理解,我们假设容器高宽为1:1,为下图中红色线框区域:

自制一个H5图片拖拽、裁剪插件(原生JS)第1张

自制一个H5图片拖拽、裁剪插件(原生JS)第2张

代码片段

var img = newImage(),
    _this = this;
img.src =imgUrl;
img.style.webkitUserSelect = 'none';
img.onload = function() {
    var imgWidth =img.width,
        imgHeight =img.height,
        imgRate = imgWidth /imgHeight,
        conRate = conWidth /conHeight;
    if (imgRate > conRate) { //宽型
        var imgCurrentHeight =_this.opts.conHeight,
            imgCurrentWidth = imgCurrentHeight *imgRate,
            maxOffset = conWidth -imgCurrentWidth;
        img.setAttribute('width', 'auto');
        img.setAttribute('height', _this.opts.conHeight);
        //......

    } else { //高型
        var imgCurrentWidth =_this.opts.conWidth,
            imgCurrentHeight = imgCurrentWidth /imgRate,
            maxOffset = conHeight -imgCurrentHeight;
        img.setAttribute('width', '100%');
        //......
}
}

上述代码就完成了基本的图片大小调整,其中 conWidth, conHeight 是插件接收的容器高与宽,maxOffset 是图片允许拖拽的最大偏移量。

拖拽

这里我使用了一个比较轻量的手势库——hammer.js,通过手势的位移改变图片的 translate 属性值。

这里只截取横向拖拽的代码片段,纵向类似

hammer.on('pan', function(e) {
    var current = img.style.transform ? img.style.transform.split('(')[1].split('px')[0] : 0,
    move = Number(current) + (e.deltaX * (_this.opts.speed/10));
    if (move >= 0 || move <=maxOffset) {
        return;
    }
    img.style.transform = 'translateX('+move+'px)';
    _this.cutData.moveX =Math.abs(move);
    _this.cutData.moveY = 0;
});

opts.speed 值为插件初始化时设置的拖动速度,这里速度值算法比较简单,有兴趣的朋友可优化使其更平滑些。cutData 用于缓存拖动的位置,用于之后的裁剪。

裁剪

这里使用了 canvas 对图片进行裁剪返回 base64码,可以将 base64码直接展示或者通过 POST 接口传到服务器处理(GET请求长度会超)

cut: function() {
var canvas = document.createElement('canvas'),
    img = document.querySelector('#cutImgObj'),
    data = this.cutData,
    cutWidth = this.opts.conWidth /data.scaleRate,
    cutHeight = this.opts.conHeight /data.scaleRate;
  canvas.width =cutWidth;
  canvas.height =cutHeight;
  canvas.getContext('2d').drawImage(img, data.moveX/data.scaleRate, data.moveY/data.scaleRate, cutWidth, cutHeight, 0, 0, cutWidth, cutHeight);
return canvas.toDataURL('image/png');
},

这里要说明下,由于图片进行了缩放,所以需要将画布调整到原图的尺寸,同时记录的拖动位置也需要除以缩放比例。

调用

· 初始化

var cutter = newCutter(picAreaDom, {
    imgUrl: url, //图片链接
    conWidth: containerDom.offsetWidth, //容器宽度
    conHeight: containerDom.offsetWidth * 1.2, //容器高度
    speed: 2, //拖动速度
    callback: function() {
        //doSomething...
}
});

这里有个地方要说明下,虽然 Cutter 中的 conWidth,conHeight 属性默认为 picAreaDom 的宽高,但如果 picAreaDom 的父级元素为 display:none,那么就获取不到 picAreaDom 尺寸(DEMO中单页应用机制导致的),这时候就需要显式传入裁剪区域的宽高。

callback 为初始化完成时的回调函数,保存实例化对象 cutter,用于之后的裁剪。

· 裁剪

var result = cutter.cut();

result 值即为裁剪后的 base64码。

最后一个小提示,如果需要重新上传图片裁剪,记得将容器中的 img 对象移除。具体的细节可以参考原码,整体比较简单。

感谢你的浏览,希望能有所帮助

免责声明:文章转载自《自制一个H5图片拖拽、裁剪插件(原生JS)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇lua 函数调用1 -- 闭包详解和C调用Thinkphp6笔记八:公共函数配置下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

js和java中使用join来进行数组元素的连接

  合理地使用join来进行数组中元素的连接,代码简洁,比自己编码也更为方便。   js中join的用法 var arr = new Array(3) arr[0] = "a" arr[1] = "b" arr[2] = "c" arr.join(".") a.b.c ------------------ arr.join(",") a,b,c   ja...

Docker实现运行tomcat并部署项目war包,并实现挂载目录

之前写的有点乱,现在再来整理一下docker的简单部署运行 借鉴博客:https://blog.csdn.net/qq_32351227/article/details/78673591 一、docker的安装,以及配置开机自启docker服务就不说了,网上一大把,我也做了另一篇博客笔记 #。。。 二、docker下载tomcat镜像并运行   2.1:搜...

jQuery 分步引导 插件

转自:http://blog.libnav.com/js/57.html 很多时候一个网站或者一个Web应用出品,为了让你的用户知道你的站点(或应用)有些什么?如何操作?为了让你的用户有更好的体验。往往这个时候都 会给你的站点(应用)添加一个分步指引的效果。然而这样的效果,对于不懂原生js的同学来说,是件蛮头痛的事情。不过大家不要慌,根据 Webreso...

Docker 容器日志管理

Docker 日志分为两类: Docker 引擎日志(也就是 dockerd 运行时的日志), 容器的日志,容器内的服务产生的日志。 一 、Docker 引擎日志 Docker 引擎日志一般是交给了 Upstart(Ubuntu 14.04) 或者 systemd (CentOS 7, Ubuntu 16.04)。前者一般位于 /var/log/ups...

Mysql:主从集群配置

我这里是去网易蜂巢取得镜像:https://c.163yun.com/hub#/m/home/ 命令:docker pull hub.c.163.com/library/mysql:latest 拉取完之后查询镜像 命令:docker images 3.配置主从复制 (1)创建配置文件 目录:/usr/local/mysql/ 注意:目录你个人设定,这不...

使用css将网页变成黑白色

其实将整个网页全局变色,无非就是三种,css直接设置,添加svg滤镜,通过js遍历所有标签更改颜色,于是 1、css 直接编辑样式,然后在需要应用的地方设置class 1 .gray { 2 -webkit-filter: grayscale(100%); 3 -moz-filter: grayscale(100%); 4 -ms...