由于業(yè)務(wù)需要用戶上傳圖片并且需要用戶自行對上傳的圖片做尺寸裁剪烈拒,本次目的是讓用戶操作方便乳乌、簡單:
Croppie.js
https://github.com/foliotek/croppieCroppr.js
https://jamesooi.design/Croppr.js/
騰訊前端團(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='';
});