AlloyCrop 這個項目是8個月前發佈的,做爲AlloyFinger 的典型案例,發佈以後被BAT等其餘公司普遍使用。可是發佈以後,有兩個問題一直沒有抽出時間去解決:css
如今很高興地告訴你們,AlloyCrop 已經徹底搞定了上面兩個問題,本文將解釋新版本的變化和AlloyCrop背後的原理。固然AlloyFinger的原理這裏就再也不闡述,之前有分享過 超小Web手勢庫AlloyFinger原理css3
先看全新的API變化。git
new AlloyCrop({
image_src: "img src",
circle: true, // optional parameters , the default value is false
width: 200, // crop width
height: 100, // crop height
output: 2, // output resolution --> 400*200
ok: function (base64, canvas) { },
cancel: function () { },
ok_text: "yes", // optional parameters , the default value is ok
cancel_text: "no" // optional parameters , the default value is cancel
});複製代碼
參數 | 是否必填 | 意義 |
---|---|---|
image_src | 必須 | 須要裁剪圖片的src地址 |
circle | 沒必要須,默認是false | 表明選取的是不是圓形仍是矩形,默認是矩形,注意:圓形選取裁剪出來的也是正方形圖片 |
width | 必須 | 選區的寬 |
height | 必須 | 選區的高 |
output | 必須 | 輸出的倍率。好比若是output爲2,選區的寬300,選區的高100,輸出的圖像的分辨率爲 (2×300,2×100) |
ok | 必須 | 點擊ok按鈕的回調 |
cancel | 必須 | 點擊cancel按鈕的回調 |
ok_text | 沒必要須,默認是ok | ok按鈕的文本 |
cancel_text | 沒必要須,默認是cancel | cancel按鈕的文本 |
與以前版本最主要的變化就是新增了 output 支持自定義倍率分辨率的圖像輸出。github
crop: function () {
this.calculateRect();
this.ctx.drawImage(this.img, this.crop_rect[0], this.crop_rect[1], this.crop_rect[2], this.crop_rect[3], 0, 0, this.canvas.width, this.canvas.height);
},複製代碼
其中 this.calculateRect() 是計算選取和圖片重疊在一塊兒的矩形區域,drawImage 是把裁剪的區域繪製到 canvas 上。注意 canvas 的寬高是多少?且看:canvas
this.canvas.width = option.width * this.output;
this.canvas.height = option.height * this.output;複製代碼
因此就達到了自定義倍率分辨率的目的。固然這裏圖片的失真又或者超分辨,都取決於 drawImage 插值過程。關於插值,之前特地對比過,使用三次卷積插值完爆了其餘幾個,可是三次卷積插值速度也是最慢,因此瀏覽器內核要權衡效率和插值結果去實現 drawImage。api
由於咱們須要把圖片的某個區域繪製到整個canvas上。因此drawImage的後四個參數爲(0, 0, this.canvas.width, this.canvas.height),而後咱們須要去計算圖片裁剪的區域。瀏覽器
大概就分上面兩種狀況,一種是徹底包含,一種部分相交。函數
由於圖片會被放大或者縮小(scale),因此狀況會變得稍微複雜一點點。求出相交的矩形區域後,要對圖片scale進行校訂,校訂回到1的比例,才能用於drawImage。具體代碼參見 github.com/AlloyTeam/A…優化
使用AlloyCrop是能夠放大或者縮小再進行裁剪,怎麼基於 pinch 的兩個手指的中間進行放大呢?因此的祕密都在這個multipointStart裏。this
new AlloyFinger(this.croppingBox, {
multipointStart: function (evt) {
//reset origin x and y
var centerX = (evt.touches[0].pageX + evt.touches[1].pageX) / 2;
var centerY = (evt.touches[0].pageY + evt.touches[1].pageY) / 2;
var cr = self.img.getBoundingClientRect();
var img_centerX = cr.left + cr.width / 2;
var img_centerY = cr.top + cr.height / 2;
var offX = centerX - img_centerX;
var offY = centerY - img_centerY;
var preOriginX = self.img.originX
var preOriginY = self.img.originY
self.img.originX = offX / self.img.scaleX;
self.img.originY = offY / self.img.scaleY;
//reset translateX and translateY
self.img.translateX += offX - preOriginX * self.img.scaleX;
self.img.translateY += offY - preOriginY * self.img.scaleX;
self.initScale = self.img.scaleX;
},
pinch: function (evt) {
self.img.scaleX = self.img.scaleY = self.initScale * evt.zoom;
},
pressMove: function (evt) {
self.img.translateX += evt.deltaX;
self.img.translateY += evt.deltaY;
evt.preventDefault();
}
});複製代碼
This content is released under the MIT License.