自定義View Canvas的范圍裁切與幾何變換

Canvas 對繪制的輔助--范圍裁切與幾何變換

1.范圍裁切

范圍裁切有兩個方法:clipRect(),clipPath()
范圍裁切就是將將畫布裁切成指定的形狀大小今瀑,然后在裁切后的畫布上作圖捞稿。

1.1 clipRect()

這里直接進行矩形裁切!

例:
Cavase.clipRect(left,top,right,bottom);

1.2 clipPath()

這里用戶可以按照自己指定的圖形進裁切嗤详!
例:

    canvas.save();  
    canvas.clipPath(path1);  
    canvas.drawBitmap(bitmap, point1.x, point1.y, paint);  
    canvas.restore();

    canvas.save();  
    canvas.clipPath(path2);  
    canvas.drawBitmap(bitmap, point2.x, point2.y, paint);  
    canvas.restore(); 
image.png

2.幾何變換

幾何變換大致分為三類
? 使用canvas來做常見的二維變換
? 使用matrix來做常見和不常見的二維變換
? 使用camera來做三維變換

2.1 使用canvas來做常見的二維變換

2.1.1 使用canvas.translate(float dx,float dy)平移
參數dx和dy表示橫向和縱向的位移。
這個時候可以簡單理解為將物體的左上頂點平移水平平移x距離扣汪,豎直方向平移y距離断楷。

2.1.2 Canvas.rotate(float degrees,float px,float py)旋轉
degrees為旋轉角度(旋轉方向為順時針),px崭别,py為旋轉軸心。
例:

    canvas.save();  
    canvas.rotate(45, centerX, centerY);  
    canvas.drawBitmap(bitmap, x, y, paint);  
    canvas.restore();  
image.png

2.1.3 canvas.scale(float sx,float sy,float px,float py) 縮放
參數 sx sy 為橫向縮放和縱向縮放倍數恐锣,px茅主,py是縮放軸心。
例:

    canvas.save();  
    canvas.scale(1.3f, 1.3f, x + bitmapWidth / 2, y + bitmapHeight / 2);  
    canvas.drawBitmap(bitmap, x, y, paint);  
    canvas.restore(); 
image.png

2.1.4 canvas.skew(float sx,float sy,float sy)錯切
參數:sx sy 為x方向和y方向錯切的錯切系數
例:

    canvas.save();  
    canvas.skew(0, 0.5f);  
    canvas.drawBitmap(bitmap, x, y, paint);  
    canvas.restore(); 
image.png
2.2 使用Matrix 做變換

2.2.1 使用Matrix 做常見變換
1.創(chuàng)建Matrix對象
2.調用Matrix的 pre/postTranslate/Rotate/Scale/Skew() 方法來設置幾何變換
3.使用Canvas.setMatrix(matrix)或Canvas.concat(matrix)來將幾何變換應用到Canvas中土榴。

Canvas.setMatrix(matrix) 和 Canvas.concat(matrix) 方法區(qū)別

? Canvas.setMatrix(matrix):用 Matrix 直接替換 Canvas 當前的變換矩陣诀姚,即拋棄 Canvas 當前的變換,改用 Matrix 的變換(注:不同的系統(tǒng)中 setMatrix(matrix) 的行為可能不一致玷禽,所以還是盡量用 concat(matrix) 吧)赫段;
? Canvas.concat(matrix):用 Canvas 當前的變換矩陣和 Matrix 相乘,即基于 Canvas 當前的變換矢赁,疊加上 Matrix 中的變換糯笙。

2.2.2使用Matrix 來做自定義變換
2.2.2.1 Matrix.setPolyToPoly(float[] src,int srcIndex,float[] dst,int dstIndex,int pointCount)用點對點映射的方式設置變換。

poly 就是「多」的意思撩银。setPolyToPoly() 的作用是通過多點的映射的方式來直接設置變換给涕。「多點映射」的意思就是把指定的點移動到給出的位置额获,從而發(fā)生形變够庙。例如:(0, 0) -> (100, 100) 表示把 (0, 0) 位置的像素移動到 (100, 100) 的位置,這個是單點的映射抄邀,單點映射可以實現(xiàn)平移耘眨。而多點的映射,就可以讓繪制內容任意地扭曲境肾。

例:

    Matrix matrix = new Matrix();  
    float pointsSrc = {left, top, right, top, left, bottom, right, bottom};  
    float pointsDst = {left - 10, top + 50, right + 120, top - 90, left + 20, bottom + 30, right + 20, bottom + 60};

    ...

    matrix.reset();  
    matrix.setPolyToPoly(pointsSrc, 0, pointsDst, 0, 4);

    canvas.save();  
    canvas.concat(matrix);  
    canvas.drawBitmap(bitmap, x, y, paint);  
    canvas.restore(); 
image.png

參數里剔难,src 和 dst 是源點集合目標點集;srcIndex 和 dstIndex 是第一個點的偏移准夷;pointCount 是采集的點的個數(個數不能大于 4钥飞,因為大于 4 個點就無法計算變換了)。
注:使用此方法最好關閉硬件加速衫嵌,單純是drawBitmap可以不用關读宙,其他必須關,不然效果不理想

2.3 使用Camera 做三維變換 Camera 的變化有 旋轉楔绞,平移结闸,移動相機

2.3.1 Camera.rorate*() 三維旋轉
rorateX(deg)沿X軸旋轉
rorateY(deg)沿Y軸旋轉
rorateZ(deg)沿Z軸旋轉
Rorate(x,y,z)沿X,Y,Z軸旋轉

2.3.2 Camera.translate(float x,float y,float z)移動
2.3.3 Camera.setLocation(x,y,z)設置虛擬相機的位置
這里唇兑,設置Camera虛擬相機位置的參數不是像素,是英寸桦锄。

這種設計源自 Android 底層的圖像引擎 Skia 扎附。在 Skia 中,Camera 的位置單位是英寸结耀,英寸和像素的換算單位在 Skia 中被寫死為了 72 像素留夜,而 Android 中把這個換算單位照搬了過來。是的图甜,它碍粥。寫。死黑毅。了嚼摩。

在 Camera 中,相機的默認位置是 (0, 0, -8)(英寸)矿瘦。8 x 72 = 576枕面,所以它的默認位置是 (0, 0, -576)(像素)。
在Camera.setLocation(x,y,z)中缚去,x與y一般不會改動潮秘!

如果繪制的內容過大,當它翻轉起來的時候病游,就有可能出現(xiàn)圖像投影過大的「糊臉」效果唇跨。而且由于換算單位被寫死成了 72 像素,而不是和設備 dpi 相關的衬衬,所以在像素越大的手機上买猖,這種「糊臉」效果會越明顯。


image.png

使用Camera.setLocation(0滋尉,0玉控,x)可以修復這個問題


image.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市狮惜,隨后出現(xiàn)的幾起案子高诺,更是在濱河造成了極大的恐慌,老刑警劉巖碾篡,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虱而,死亡現(xiàn)場離奇詭異,居然都是意外死亡开泽,警方通過查閱死者的電腦和手機牡拇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惠呼,你說我怎么就攤上這事导俘。” “怎么了剔蹋?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵旅薄,是天一觀的道長。 經常有香客問我泣崩,道長少梁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任律想,我火速辦了婚禮猎莲,結果婚禮上,老公的妹妹穿的比我還像新娘技即。我一直安慰自己,他們只是感情好樟遣,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布而叼。 她就那樣靜靜地躺著,像睡著了一般豹悬。 火紅的嫁衣襯著肌膚如雪葵陵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天瞻佛,我揣著相機與錄音脱篙,去河邊找鬼。 笑死伤柄,一個胖子當著我的面吹牛绊困,可吹牛的內容都是我干的。 我是一名探鬼主播适刀,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼秤朗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笔喉?” 一聲冷哼從身側響起取视,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎常挚,沒想到半個月后作谭,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡奄毡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年折欠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡怨酝,死狀恐怖傀缩,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情农猬,我是刑警寧澤赡艰,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站斤葱,受9級特大地震影響慷垮,放射性物質發(fā)生泄漏。R本人自食惡果不足惜揍堕,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一料身、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衩茸,春花似錦芹血、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至囊蓝,卻和暖如春饿悬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背聚霜。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工狡恬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝎宇。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓弟劲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親夫啊。 傳聞我的和親對象是個殘疾皇子函卒,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內容