移动端图片裁剪-JavaScript

由于业务需要用户上传图片并且需要用户自行对上传的图片做尺寸裁剪,本次目的是让用户操作方便、简单:

腾讯前端团队的AlloyCrop.js demo运行不了仓库似乎也没有维护了

这俩款库都支持移动端和pc端,API文档也都写得清晰明了,这里就用Croppie。

安装

NPM:

  npm install croppie

Bower:

  bower install croppie

或者直接引入

  <link rel="stylesheet" href="croppie.css" />
  <script src="croppie.js"></script>

使用

  • 简单用法
<div class="demo"></div>
<script>
$('.demo').croppie({
    url: 'demo/demo-1.jpg',
});
</script>
<!--更简单用法 -->
<img class="my-image" src="demo/demo-1.jpg" />
<script>
$('.my-image').croppie();
</script>

初始化对象

  • 在页面中添加一个容器
<div id="demo"></div>
  • 不依赖jQuery的用法
//参数1:页面上的容器Node
//参数2:插件配置项
var c = new Croppie(document.getElementById('demo'), opts);
// 调用方法
//参数:方法接收的参数
c.method(args);
  • 依赖jQuery的用法
//参数:插件配置项
$('#demo').croppie(opts);
// 调用方法
//参数1:方法名
//参数2:方法接收的参数
$('#demo').croppie(method, args);

配置项:

  • boundary object {width:number,height:number}

    外部容器大小

    默认值 用户自定义定容器填充满

  • customClass string

    自定义外部容器class类名,自定义样式

    默认值 ''

  • enableExif boolean

    是否启用exif纠正图片旋转方向,ps:开启此属性需要自行引入Exif.js
    (ios相机拍出的照片会出现旋转的情况常用exif读取图片EXIF元数据然后做相应的旋转纠正,详情参阅 exif.js

    默认值false

  • enableOrientation boolean

    是否启用自定义图像旋转方向,此选项和bind方法的orientation属性配合使用

    默认值 false

  • enableResize boolean

    是否启用视口大小拖动调整

    默认值 false

  • enableZoom boolean

    是否启用缩放功能,关闭后底部滑块也会跟随关闭

    默认值 true

  • enforceBoundary boolean Experimental

    限制缩放,使图像不能小于视口

    默认值 true

  • mouseWheelZoom bool/string

    是否启用鼠标滚轮放大或缩小,也可设置为'ctrl'设置后需要按住ctrl+滚轮 才能缩放图片

    默认值true

  • showZoomer boolean

    显示隐藏底部控制滑块

    默认值true

  • viewport object

    内部容器大小,图像可见部分即裁剪部分大小。

    默认值 { width: 100, height: 100, type: 'square' }

    type可选值:'square' 'circle'type=circle的时候一般会与result方法的circle=true参数配合使用

方法

  • get()

    返回 object
    获取相对于图片的裁切点和缩放值

  • bind({ url, points, orientation, zoom })

    返回 Promise
    动态将图像载入进容器
    参数:
    url string 图像的url地址(可以是base64 或者URL.createObjectURL创建的地址)
    points array数组形式选择展示图片的哪些部位 [topLeftX, topLeftY, bottomRightX, bottomRightY]
    zoom number缩放值,1<缩小 >1放大
    orientation number 自定义图片旋转方向,在exif调整方向之后应用。需要开启enableOrientation选项

    orientation的可选值:
    1 默认
    2 水平翻转
    3 旋转180°
    4 垂直翻转
    5 水平翻转,然后向左旋转90°
    6 顺时针旋转90°
    7 水平翻转,然后向右旋转90°
    8 逆时针旋转90°

  • destroy()

    销毁一个croppie实例并将其从DOM中移除

  • result({ type, size, format, quality, circle })

    获取最终裁切出的图像
    返回 Promise
    参数
    type string 期望输出什么类型的数据,默认'canvas'

    type 可选值
    'base64' 返回base64数据
    'html' 返回div内部嵌套img并且div被设置了隐藏溢出样式
    'blob'返回blob对象
    'rawcanvas' 返回canvas元素,可以在获取结果图像之前进行自定义操作

    size string|object 裁剪图像的大小,默认为 'viewport'

    size可选值
    'viewport' 生成的图像的大小与视口的宽度和高度相同
    'original' 生成的图像的大小将为图像的原始比例
    {width, height} 定义宽度和高度的对象。如果仅指定一个尺寸,则将使用视口宽高比计算另一个尺寸。

    format string 指定图像格式,默认为'png'

    format可选值
    'jpeg'|'png'|'webp'

    quality number 图片的质量 0 ~ 1,1质量最高 , 默认 1
    circle boolean 是否裁剪为一个圆,默认false ,一般会与viewport.type = 'circle'配合使用

  • rotate(degrees)

    将图像旋转指定的度数。仅在启用enableOrientation选项的情况下起作用(请参见“选项”)。
    有效度数:90, 180, 270, -90, -180, -270

  • setZoom(value)

    设置Croppie实例的缩放。传入的值仍限制为Croppie设置的最小值/最大值。
    设置浮点值以缩放裁剪图像。必须介于裁剪设置的最小值和最大值之间。

功能实现

首先在页面插入一些节点作为剪切图片的操作面板。并简单设置一下样式,以及rem单位划分

<style>
        *{padding: 0; margin: 0;}
        html,body{ width: 100%; height: 100%; }
        body{background: #fff;position: relative;}
        .croppie-box{ height: 100%; width: 100%; position: absolute; left: 0; top: 0; z-index: 9999; display: none;}
        .croppie-box .button{ position: absolute; right: 3rem; bottom: 2rem; width: 8rem; height: 2.5rem; z-index: 99; border-radius: 2px; text-align: center; line-height: 2.5rem; font-size: 1rem; }
        .croppie-box .button.ok{ color:#002531; background: rgb(43, 202, 253);}
        .croppie-box .button.cancel{ background-color: #ccc; color:#444; left: 3rem;}
</style>
<script>
        var htmlWidth = document.documentElement.clientWidth || document.body.clientWidth;
        var htmlHeight = document.documentElement.clientHeight || document.body.clientHeight;
        var htmlDom = document.documentElement;
        var WIDTH = htmlWidth;
        if(htmlWidth>htmlHeight){
            WIDTH = 750;
            htmlDom.style.cssText = 'width:750px;margin:0 auto;background:#000;'
        }
        htmlDom.style.fontSize= WIDTH/25 + 'px';
</script>
<div class="croppie-box">
  <div class="croppie"></div>
  <div class="button ok">确定</div>
  <div class="button cancel">取消</div>
</div>
<input type="file" name=""  class="upload">
<img class="img" style="width: 100%;height: auto;padding: 2rem;box-sizing: border-box;display: block;" src="" alt="">

将需要用到的节点全部存起来

var croppie = undefined,
  fileInput = document.querySelector('.upload'),
  okBtn = document.querySelector('.button.ok'),
  cancelBtn = document.querySelector('.button.cancel'),
  croppieBox = document.querySelector('.croppie-box'),
  resultImg = document.querySelector('.img');
  scale  = (WIDTH-50) / 5;//计算一个倍数简单适配一下不同手机屏幕

定义俩个待会儿需要用到的方法

croppieBox.show = function(){
  this.style.cssText = 'display:block;'
}
 croppieBox.hide = function(){
  this.style.cssText = 'display:none;'
}

业务要求用户需要裁剪一个5:4比例的图片。
创建Croppie实例,并且不需要底部滑块所以隐藏掉

croppie = new Croppie(croppieBox.querySelector('.croppie'),{
  showZoomer:false,//隐藏滑块
  viewport: {
      width: 5*scale,//乘上倍数 保证裁剪框大小是5:4
      height: 4*scale
  },
  enableExif: true//纠正旋转角度
})

给file绑定一个事件然后把file选择的图片读取到croppie容器里面进行裁剪,zoom设置为0.00001是为了让图片载入的时候能够把一个边完全贴合容器。

fileInput.addEventListener('change', function (e) {
  croppieBox.show();
  croppie.bind({
    url: window.URL.createObjectURL(e.target.files[0]),
    zoom:0.00001,
  })
});

接下来给俩个按钮绑定事件,result方法的size属性需要注意如果选择'viewport'得到的图片会比较模糊因为宽高是根据裁剪视口大小来的(即图像宽通常 < window.innerWidth)。当然可以自行设定{widnth,height}拿固定值(需要注意裁剪的比例如果指定的大小和裁剪比例不一致会导致图片拉伸),在这里的业务场景比较适合用原始图像的宽高所以选择了'original',点击确定调用result方法生成一个blob对象,接下来拿到blob之后就可以自己随意操作了

okBtn.addEventListener('click', function (ev) {
    croppie.result({
      type: 'blob',
      size: 'original',
    }).then(function (resp) {
      resultImg.setAttribute('src',window.URL.createObjectURL(resp))
      fileInput.value='';
      croppieBox.hide();
    });
});

cancelBtn.addEventListener('click', function (ev) {
  croppieBox.hide();
  fileInput.value='';
});

点击预览

仓库地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341