移動(dòng)端圖片裁剪-JavaScript

由于業(yè)務(wù)需要用戶上傳圖片并且需要用戶自行對上傳的圖片做尺寸裁剪烈拒,本次目的是讓用戶操作方便乳乌、簡單:

騰訊前端團(tuán)隊(duì)的AlloyCrop.js demo運(yùn)行不了倉庫似乎也沒有維護(hù)了

這倆款庫都支持移動(dòng)端和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>

初始化對象

  • 在頁面中添加一個(gè)容器
<div id="demo"></div>
  • 不依賴jQuery的用法
//參數(shù)1:頁面上的容器Node
//參數(shù)2:插件配置項(xiàng)
var c = new Croppie(document.getElementById('demo'), opts);
// 調(diào)用方法
//參數(shù):方法接收的參數(shù)
c.method(args);
  • 依賴jQuery的用法
//參數(shù):插件配置項(xiàng)
$('#demo').croppie(opts);
// 調(diào)用方法
//參數(shù)1:方法名
//參數(shù)2:方法接收的參數(shù)
$('#demo').croppie(method, args);

配置項(xiàng):

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

    外部容器大小

    默認(rèn)值 用戶自定義定容器填充滿

  • customClass string

    自定義外部容器class類名,自定義樣式

    默認(rèn)值 ''

  • enableExif boolean

    是否啟用exif糾正圖片旋轉(zhuǎn)方向磺平,ps:開啟此屬性需要自行引入Exif.js
    (ios相機(jī)拍出的照片會(huì)出現(xiàn)旋轉(zhuǎn)的情況常用exif讀取圖片EXIF元數(shù)據(jù)然后做相應(yīng)的旋轉(zhuǎn)糾正,詳情參閱 exif.js

    默認(rèn)值false

  • enableOrientation boolean

    是否啟用自定義圖像旋轉(zhuǎn)方向拐辽,此選項(xiàng)和bind方法的orientation屬性配合使用

    默認(rèn)值 false

  • enableResize boolean

    是否啟用視口大小拖動(dòng)調(diào)整

    默認(rèn)值 false

  • enableZoom boolean

    是否啟用縮放功能,關(guān)閉后底部滑塊也會(huì)跟隨關(guān)閉

    默認(rèn)值 true

  • enforceBoundary boolean Experimental

    限制縮放拣挪,使圖像不能小于視口

    默認(rèn)值 true

  • mouseWheelZoom bool/string

    是否啟用鼠標(biāo)滾輪放大或縮小,也可設(shè)置為'ctrl'設(shè)置后需要按住ctrl+滾輪 才能縮放圖片

    默認(rèn)值true

  • showZoomer boolean

    顯示隱藏底部控制滑塊

    默認(rèn)值true

  • viewport object

    內(nèi)部容器大小俱诸,圖像可見部分即裁剪部分大小菠劝。

    默認(rèn)值 { width: 100, height: 100, type: 'square' }

    type可選值:'square' 'circle'type=circle的時(shí)候一般會(huì)與result方法的circle=true參數(shù)配合使用

方法

  • get()

    返回 object
    獲取相對于圖片的裁切點(diǎn)和縮放值

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

    返回 Promise
    動(dòng)態(tài)將圖像載入進(jìn)容器
    參數(shù):
    url string 圖像的url地址(可以是base64 或者URL.createObjectURL創(chuàng)建的地址)
    points array數(shù)組形式選擇展示圖片的哪些部位 [topLeftX, topLeftY, bottomRightX, bottomRightY]
    zoom number縮放值,1<縮小 >1放大
    orientation number 自定義圖片旋轉(zhuǎn)方向睁搭,在exif調(diào)整方向之后應(yīng)用赶诊。需要開啟enableOrientation選項(xiàng)

    orientation的可選值:
    1 默認(rèn)
    2 水平翻轉(zhuǎn)
    3 旋轉(zhuǎn)180°
    4 垂直翻轉(zhuǎn)
    5 水平翻轉(zhuǎn)笼平,然后向左旋轉(zhuǎn)90°
    6 順時(shí)針旋轉(zhuǎn)90°
    7 水平翻轉(zhuǎn),然后向右旋轉(zhuǎn)90°
    8 逆時(shí)針旋轉(zhuǎn)90°

  • destroy()

    銷毀一個(gè)croppie實(shí)例并將其從DOM中移除

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

    獲取最終裁切出的圖像
    返回 Promise
    參數(shù)
    type string 期望輸出什么類型的數(shù)據(jù)舔痪,默認(rèn)'canvas'

    type 可選值
    'base64' 返回base64數(shù)據(jù)
    'html' 返回div內(nèi)部嵌套img并且div被設(shè)置了隱藏溢出樣式
    'blob'返回blob對象
    'rawcanvas' 返回canvas元素寓调,可以在獲取結(jié)果圖像之前進(jìn)行自定義操作

    size string|object 裁剪圖像的大小,默認(rèn)為 'viewport'

    size可選值
    'viewport' 生成的圖像的大小與視口的寬度和高度相同
    'original' 生成的圖像的大小將為圖像的原始比例
    {width, height} 定義寬度和高度的對象锄码。如果僅指定一個(gè)尺寸夺英,則將使用視口寬高比計(jì)算另一個(gè)尺寸。

    format string 指定圖像格式巍耗,默認(rèn)為'png'

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

    quality number 圖片的質(zhì)量 0 ~ 1,1質(zhì)量最高 , 默認(rèn) 1
    circle boolean 是否裁剪為一個(gè)圓秋麸,默認(rèn)false ,一般會(huì)與viewport.type = 'circle'配合使用

  • rotate(degrees)

    將圖像旋轉(zhuǎn)指定的度數(shù)。僅在啟用enableOrientation選項(xiàng)的情況下起作用(請參見“選項(xiàng)”)炬太。
    有效度數(shù):90, 180, 270, -90, -180, -270

  • setZoom(value)

    設(shè)置Croppie實(shí)例的縮放灸蟆。傳入的值仍限制為Croppie設(shè)置的最小值/最大值。
    設(shè)置浮點(diǎn)值以縮放裁剪圖像亲族。必須介于裁剪設(shè)置的最小值和最大值之間炒考。

功能實(shí)現(xiàn)

首先在頁面插入一些節(jié)點(diǎn)作為剪切圖片的操作面板。并簡單設(shè)置一下樣式,以及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="">

將需要用到的節(jié)點(diǎn)全部存起來

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;//計(jì)算一個(gè)倍數(shù)簡單適配一下不同手機(jī)屏幕

定義倆個(gè)待會(huì)兒需要用到的方法

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

業(yè)務(wù)要求用戶需要裁剪一個(gè)5:4比例的圖片霎迫。
創(chuàng)建Croppie實(shí)例斋枢,并且不需要底部滑塊所以隱藏掉

croppie = new Croppie(croppieBox.querySelector('.croppie'),{
  showZoomer:false,//隱藏滑塊
  viewport: {
      width: 5*scale,//乘上倍數(shù) 保證裁剪框大小是5:4
      height: 4*scale
  },
  enableExif: true//糾正旋轉(zhuǎn)角度
})

給file綁定一個(gè)事件然后把file選擇的圖片讀取到croppie容器里面進(jìn)行裁剪,zoom設(shè)置為0.00001是為了讓圖片載入的時(shí)候能夠把一個(gè)邊完全貼合容器知给。

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

接下來給倆個(gè)按鈕綁定事件瓤帚,result方法的size屬性需要注意如果選擇'viewport'得到的圖片會(huì)比較模糊因?yàn)閷捀呤歉鶕?jù)裁剪視口大小來的(即圖像寬通常 < window.innerWidth)。當(dāng)然可以自行設(shè)定{widnth,height}拿固定值(需要注意裁剪的比例如果指定的大小和裁剪比例不一致會(huì)導(dǎo)致圖片拉伸)涩赢,在這里的業(yè)務(wù)場景比較適合用原始圖像的寬高所以選擇了'original'戈次,點(diǎn)擊確定調(diào)用result方法生成一個(gè)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='';
});

點(diǎn)擊預(yù)覽

倉庫地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末筒扒,一起剝皮案震驚了整個(gè)濱河市怯邪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌花墩,老刑警劉巖悬秉,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異冰蘑,居然都是意外死亡和泌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門祠肥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來允跑,“玉大人,你說我怎么就攤上這事×浚” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵工碾,是天一觀的道長弱睦。 經(jīng)常有香客問我,道長渊额,這世上最難降的妖魔是什么况木? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮旬迹,結(jié)果婚禮上火惊,老公的妹妹穿的比我還像新娘。我一直安慰自己奔垦,他們只是感情好屹耐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著椿猎,像睡著了一般惶岭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上犯眠,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天按灶,我揣著相機(jī)與錄音,去河邊找鬼筐咧。 笑死鸯旁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的量蕊。 我是一名探鬼主播铺罢,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼危融!你這毒婦竟也來了畏铆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吉殃,失蹤者是張志新(化名)和其女友劉穎辞居,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛋勺,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瓦灶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抱完。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贼陶。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碉怔,到底是詐尸還是另有隱情烘贴,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布撮胧,位于F島的核電站桨踪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏芹啥。R本人自食惡果不足惜锻离,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望墓怀。 院中可真熱鬧汽纠,春花似錦、人聲如沸傀履。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啤呼。三九已至卧秘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間官扣,已是汗流浹背翅敌。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惕蹄,地道東北人蚯涮。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像卖陵,于是被迫代替她去往敵國和親遭顶。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355