android自定义游戏闯关图,Android自定义View(四) -- Canvas
本文計劃根據(jù)HenCoder系列文章進行學習,所以代碼風格及博文素材可能會摘自其中。
1 范圍裁切
范圍裁切有兩個方法: clipRect() 和 clipPath()。裁切方法之后的繪制代碼,都會被限制在裁切范圍內(nèi)。
1.1 clipRect()
使用很簡單,直接應用:
canvas.clipRect(100,100,400,400);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snoopy);
canvas.drawBitmap(bitmap,100,100,paint);
原圖 對比 裁切
記得要加上 Canvas.save() 和 Canvas.restore() 來及時恢復繪制范圍。
1.2 clipPath()
其實和 clipRect() 用法完全一樣,只是把參數(shù)換成了 Path ,所以能裁切的形狀更多一些:
canvas.save();
path.addCircle(500,500,400, Path.Direction.CCW);
canvas.clipPath(path);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.snoopy);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
image.png
2. 幾何變換
幾何變換的使用大概分為三類:
使用 Canvas 來做常見的二維變換;
使用 Matrix 來做常見和不常見的二維變換;
使用 Camera 來做三維變換。
2.1 使用 Canvas 來做常見的二維變換:
2.1.1 Canvas.translate(float dx, float dy) 平移
參數(shù)里的 dx 和 dy 表示橫向和縱向的位移。
canvas.save();
canvas.translate(300,100);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
image.png
2.1.2 Canvas.rotate(float degrees, float px, float py) 旋轉(zhuǎn)
參數(shù)里的 degrees 是旋轉(zhuǎn)角度,單位是度(也就是一周有 360° 的那個單位),方向是順時針為正向; px 和 py 是軸心的位置。
canvas.save();
canvas.rotate(200);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
2.1.3 Canvas.scale(float sx, float sy, float px, float py) 放縮
參數(shù)里的 sx sy 是橫向和縱向的放縮倍數(shù); px py 是放縮的軸心。
canvas.save();
canvas.scale(1.5f,0.8f,100,100);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
2.1.4 skew(float sx, float sy) 錯切
參數(shù)里的 sx 和 sy 是 x 方向和 y 方向的錯切系數(shù)。
canvas.save();
canvas.skew(0.3f,0.3f);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
2.2 使用 Matrix 來做變換
2.2.1 使用 Matrix 來做常見變換
Matrix 做常見變換的方式:
創(chuàng)建 Matrix 對象;
調(diào)用 Matrix 的 pre/postTranslate/Rotate/Scale/Skew() 方法來設置幾何變換;
使用 Canvas.setMatrix(matrix) 或 Canvas.concat(matrix) 來把幾何變換應用到 Canvas。
平移
matrix.reset();
matrix.postTranslate(300,300);
canvas.save();
canvas.concat(matrix);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
.png
其他效果就不一一展示,和Canvas方法一樣。
把 Matrix 應用到 Canvas 有兩個方法: Canvas.setMatrix(matrix) 和 Canvas.concat(matrix)。
Canvas.setMatrix(matrix):用 Matrix 直接替換 Canvas 當前的變換矩陣,即拋棄 Canvas 當前的變換,改用 Matrix 的變換(注:根據(jù)下面評論里以及我在微信公眾號中收到的反饋,不同的系統(tǒng)中 setMatrix(matrix) 的行為可能不一致,所以還是盡量用 concat(matrix) 吧);
Canvas.concat(matrix):用 Canvas 當前的變換矩陣和 Matrix 相乘,即基于 Canvas 當前的變換,疊加上 Matrix 中的變換。
2.2.2 使用 Matrix 來做自定義變換
Matrix 的自定義變換使用的是 setPolyToPoly() 方法。
2.2.2.1 Matrix.setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount) 用點對點映射的方式設置變換
private float[] pointSrc = {20,50,200,400, 80,90,300,50};
private float[] pointsDst = {10, 70, 320, 310, 200, 100, 310, 200};
matrix.reset();
matrix.setPolyToPoly(pointSrc , 0,pointsDst,0,3);
canvas.save();
canvas.concat(matrix);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
image.png
參數(shù)里,src 和 dst 是源點集合目標點集;srcIndex 和 dstIndex 是第一個點的偏移;pointCount 是采集的點的個數(shù)(個數(shù)不能大于 4,因為大于 4 個點就無法計算變換了)。
2.3 使用 Camera 來做三維變換
Camera 的三維變換有三類:旋轉(zhuǎn)、平移、移動相機。
2.3.1 Camera.rotate*() 三維旋轉(zhuǎn)
Camera.rotate*() 一共有四個方法: rotateX(deg) rotateY(deg) rotateZ(deg) rotate(x, y, z)。這四個方法的區(qū)別不用我說了吧?
canvas.save();
camera.save();
camera.rotate(0,0,20);
camera.applyToCanvas(canvas);
camera.restore();
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
image.png
如果你需要圖形左右對稱,需要配合上 Canvas.translate(),在三維旋轉(zhuǎn)之前把繪制內(nèi)容的中心點移動到原點,即旋轉(zhuǎn)的軸心,然后在三維旋轉(zhuǎn)后再把投影移動回來:
canvas.save();
canvas.translate(100,100);
camera.save();
camera.rotate(-20,0,20);
camera.applyToCanvas(canvas);
camera.restore();
canvas.translate(-100,-100);
canvas.drawBitmap(bitmap,100,100,paint);
canvas.restore();
Canvas 的幾何變換順序是反的,所以要把移動到中心的代碼寫在下面,把從中心移動回來的代碼寫在上面。
2.3.2 Camera.translate(float x, float y, float z) 移動
它的使用方式和 Camera.rotate*() 相同,而且我在項目中沒有用過它,所以就不貼代碼和效果圖了。
2.3.3 Camera.setLocation(x, y, z) 設置虛擬相機的位置
注意!這個方法有點奇葩,它的參數(shù)的單位不是像素,而是 inch,英寸。
image
我 TM 的真沒逗你,我也沒有胡說八道,它的單位就。是。英。寸。
這種設計源自 Android 底層的圖像引擎 Skia 。在 Skia 中,Camera 的位置單位是英寸,英寸和像素的換算單位在 Skia 中被寫死為了 72 像素,而 Android 中把這個換算單位照搬了過來。是的,它。寫。死。了。
image
吐槽到此為止,俗話說看透不說透,還是好朋友。
在 Camera 中,相機的默認位置是 (0, 0, -8)(英寸)。8 x 72 = 576,所以它的默認位置是 (0, 0, -576)(像素)。
如果繪制的內(nèi)容過大,當它翻轉(zhuǎn)起來的時候,就有可能出現(xiàn)圖像投影過大的「糊臉」效果。而且由于換算單位被寫死成了 72 像素,而不是和設備 dpi 相關的,所以在像素越大的手機上,這種「糊臉」效果會越明顯。
image
而使用 setLocation() 方法來把相機往后移動,就可以修復這種問題。
camera.setLocation(0, 0, newZ);
image
Camera.setLocation(x, y, z) 的 x 和 y 參數(shù)一般不會改變,直接填 0 就好。
好了,上面這些就是本期的內(nèi)容:范圍裁切和幾何變換。
總結(jié)
以上是生活随笔為你收集整理的android自定义游戏闯关图,Android自定义View(四) -- Canvas的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言单元测验,C语言程序设计单元测验一
- 下一篇: android tag的使用方法,And