Android 2D Graphics學習(二)、Canvas篇2、Canvas裁剪和Region、RegionIterator
canvas 還提供裁剪的功能。
裁剪功能由Canvas提供的一系列的clip...方法 和quickReject方法來完成。 前面已經提到,真正提供可繪製區域的是Canvas內部的mutable bitmap。 Canvas更像是一個圖層,我們只能在這上面的圖層來繪製東西。
1、首先介紹Region類
Region,中文意思即區域的意思,它表示的是canvas圖層上的某一塊封閉的區域。
- /**構造方法*/
- public Region() //建立一個空的區域
- public Region(Region region) //拷貝一個region的範圍
- public Region(Rect r) //建立一個矩形的區域
- public Region(int left, int top, int right, int bottom) //建立一個矩形的區域
- /**一系列set方法,這些set方法,和上面構造方法形式差不多*/
- public void setEmpty() {
- public boolean set(Region region)
- public boolean set(Rect r)
- public boolean set(int left, int top, int right, int bottom)
- /*往一個Region中新增一個Path只有這種方法,引數clip代表這個整個Region的區域,在在裡面裁剪出path範圍的區域*/
- public boolean setPath(Path path, Region clip) //用指定的Path和裁剪範圍構建一個區域
- /**幾個判斷方法*/
- public native boolean isEmpty();//判斷該區域是否為空
- public native boolean isRect(); //是否是一個矩陣
- public native boolean isComplex();//是否是多個矩陣組合
- /**一系列的getBound方法,返回一個Region的邊界*/
- public Rect getBounds()
- public boolean getBounds(Rect r)
- public Path getBoundaryPath()
- public boolean getBoundaryPath(Path path)
- /**一系列的判斷是否包含某點 和是否相交*/
- public native boolean contains(int x, int y);//是否包含某點
- public boolean quickContains(Rect r) //是否包含某矩陣
- public native boolean quickContains(int left, int top, int right,
- int bottom) //是否沒有包含某矩陣
- public boolean quickReject(Rect r) //是否沒和該矩陣相交
- public native boolean quickReject(int left, int top, int right, int bottom); //是否沒和該矩陣相交
- public native boolean quickReject(Region rgn); //是否沒和該矩陣相交
- /**幾個平移變換的方法*/
- public void translate(int dx, int dy)
- public native void translate(int dx, int dy, Region dst);
- public void scale(float scale) //hide
- public native void scale(float scale, Region dst);//hide
- /**一系列組合的方法*/
- public final boolean union(Rect r)
- public boolean op(Rect r, Op op) {
- public boolean op(int left, int top, int right, int bottom, Op op)
- public boolean op(Region region, Op op)
- public boolean op(Rect rect, Region region, Op op)
上面幾乎是Region的所有API,很好理解,主要說明一下最後的一組關於Region組合的方式。組合即當前的Region和另外的一個Region組合,可以用不同的Op方式來進行組合。
Op是一個列舉,定義在Region類中。
- 假設用region1 去組合region2
- public enum Op {
- DIFFERENCE(0), //最終區域為region1 與 region2不同的區域
- INTERSECT(1), // 最終區域為region1 與 region2相交的區域
- UNION(2), //最終區域為region1 與 region2組合一起的區域
- XOR(3), //最終區域為region1 與 region2相交之外的區域
- REVERSE_DIFFERENCE(4), //最終區域為region2 與 region1不同的區域
- REPLACE(5); //最終區域為為region2的區域
- }
ApiDemo中已經提供了一個關於組合的例子,在最後面給出。
Android還提供了一個RegionIterator來對Region中的所有矩陣進行迭代,可以使用該類,獲得某個Region的所有矩陣。比較簡單。
2、什麼是裁剪
裁剪Clip,即裁剪Canvas圖層,我們繪製的東西,只能在裁剪區域的範圍能才能顯示出來。
- @Override
- protected void onDraw(Canvas canvas) {
- Paint paint=new Paint();
- canvas.save();
- canvas.clipRect(new Rect(100,100,300,300));
- canvas.drawColor(Color.BLUE);//裁剪區域的rect變為藍色
- canvas.drawRect(new Rect(0,0,100,100), paint);//在裁剪的區域之外,不能顯示
- canvas.drawCircle(150,150, 50, paint);//在裁剪區域之內,能顯示
- canvas.restore();
- }
裁剪並不像Matrix變換,它相對於mutable bitmap的座標是不會改變的。所以超出裁剪區域的繪製不會被顯示
3、裁剪的儲存和回滾
在之前已經提到了,canvas.save()和canvas.restore()不僅對matrix有效,同樣對clip有類似的效果。
4、裁剪的方式
Canvas提供了三種裁剪的方式:
1、最基本的clipRect,裁剪一個矩形
2、clipPath,裁剪Path包括的範圍,Path所包括的範圍不是空的才有效。
3、clipRegion。
Region在前面已經介紹過了,其實Region就是一個對區域組合的一個封裝。但是它和clipRect和clipPath的最大區別在於下面:
- Note that unlike
- clipRect() and clipPath() which transform their arguments by the
- current matrix, clipRegion() assumes its argument is already in the
- coordinate system of the current layer's bitmap, and so not
- transformation is performed.
- Paint paint=new Paint();
- canvas.scale(0.5f, 0.5f);
- canvas.save();
- canvas.clipRect(new Rect(100,100,200,200));//裁剪區域實際大小為50*50
- canvas.drawColor(Color.RED);
- canvas.restore();
- canvas.drawRect(new Rect(0,0,100,100), paint);//矩形實際大小為50*50
- canvas.clipRegion(new Region(new Rect(300,300,400,400)));//裁剪區域實際大小為100*100
- canvas.drawColor(Color.BLACK);
可以看到,Canvas的變換 對clipRegion沒有作用。
ApiDemo中關於組合的例子:
- public class Clipping extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(new SampleView(this));
- }
- private static class SampleView extends View {
- private Paint mPaint;
- private Path mPath;
- public SampleView(Context context) {
- super(context);
- setFocusable(true);
- mPaint = new Paint();
- mPaint.setAntiAlias(true);
- mPaint.setStrokeWidth(6);
- mPaint.setTextSize(16);
- mPaint.setTextAlign(Paint.Align.RIGHT);
- mPath = new Path();
- }
- private void drawScene(Canvas canvas) {
- canvas.clipRect(0, 0, 100, 100);
- canvas.drawColor(Color.WHITE);
- mPaint.setColor(Color.RED);
- canvas.drawLine(0, 0, 100, 100, mPaint);
- mPaint.setColor(Color.GREEN);
- canvas.drawCircle(30, 70, 30, mPaint);
- mPaint.setColor(Color.BLUE);
- canvas.drawText("Clipping", 100, 30, mPaint);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.drawColor(Color.GRAY);
- canvas.save();
- canvas.translate(10, 10);
- drawScene(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(160, 10);
- canvas.clipRect(10, 10, 90, 90);
- canvas.clipRect(30, 30, 70, 70, Region.Op.DIFFERENCE);
- drawScene(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(10, 160);
- mPath.reset();
- canvas.clipPath(mPath); // makes the clip empty
- mPath.addCircle(50, 50, 50, Path.Direction.CCW);
- canvas.clipPath(mPath, Region.Op.REPLACE);
- drawScene(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(160, 160);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.UNION);
- drawScene(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(10, 310);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.XOR);
- drawScene(canvas);
- canvas.restore();
- canvas.save();
- canvas.translate(160, 310);
- canvas.clipRect(0, 0, 60, 60);
- canvas.clipRect(40, 40, 100, 100, Region.Op.REVERSE_DIFFERENCE);
- drawScene(canvas);
- canvas.restore();
- }
- }
- }
效果圖:
5、裁剪的一個小用處
- public class ClippingRegion extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(new SampleView(this));
- }
- private class SampleView extends View {
- private Bitmap mBitmap;
- private int limitLength = 0;
- private int width;
- private int heigth;
- private static final int CLIP_HEIGHT = 30;
- private boolean status = HIDE;//顯示還是隱藏的狀態,最開始為HIDE
- private static final boolean SHOW = true;//顯示圖片
- private static final boolean HIDE = false;//隱藏圖片
- public SampleView(Context context) {
- super(context);
- mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
- limitLength = width = mBitmap.getWidth();
- heigth = mBitmap.getHeight();
- }
- @Override
- protected void onDraw(Canvas canvas) {
- Region region = new Region();
- int i = 0;
- while (i * CLIP_HEIGHT <= heigth) {//計算clip的區域
- if (i % 2 == 0) {
- region.union(new Rect(0, i * CLIP_HEIGHT, limitLength, (i + 1) * CLIP_HEIGHT));
- } else {
- region.union(new Rect(width - limitLength, i * CLIP_HEIGHT, width, (i + 1)
- * CLIP_HEIGHT));
- }
- i++;
- }
- canvas.clipRegion(region);
- canvas.drawBitmap(mBitmap, 0, 0, new Paint());
- if (status == HIDE) {//如果此時是隱藏
- limitLength -= 5;
- if(limitLength<=0)
- status=SHOW;
- } else {//如果此時是顯示
- limitLength += 5;
- if(limitLength>=width)
- status=HIDE;
- }
- invalidate();
- }
- }
- }
效果就是一直這樣交叉的隱藏和顯示圖片
相關文章
- canvas 2d toDataURLCanvas
- canvas學習筆記-2d畫布基礎Canvas筆記
- Bitmap回收—Canvas: trying to use a recycled bitmap android.graphicsCanvasAndroid
- Flutter Canvas學習之繪圖篇FlutterCanvas繪圖
- 2019.1.21 canvas學習小計Canvas
- Canvas學習筆記(一)Canvas筆記
- canvas實現的前端壓縮裁剪工具Canvas前端
- Android: Bitmap/Canvas/DrawableAndroidCanvas
- One simple way to draw canvas, wxml2canvasCanvasXML
- 學習canvas基礎的總結Canvas
- canvas繪製圖片drawImage學習Canvas
- 【練習】canvas——flappyBirdCanvasAPP
- Android的Paint、Canvas和Path基本使用總結AndroidAICanvas
- Canvas 2D 渲染指南 - 用 TypeScript 實現一個程式入口 Application 類CanvasTypeScriptAPP
- 學習HTML5 Canvas這一篇文章就夠了HTMLCanvas
- canvas save()和restore()CanvasREST
- canvas實現二維碼和圖片合成Canvas
- 跟著專案學 android canvas——InDoorView 地圖引擎AndroidCanvasView地圖
- 圖解Android - Android GUI 系統 (2) - 視窗管理 (View, Canvas, Window Manager)圖解AndroidGUIViewCanvas
- canvas Path2D 物件Canvas物件
- 基於 HTML5 Canvas 2D 拓撲圖和 3D 機櫃模型的增刪操作HTMLCanvas3D模型
- 學習 canvas 的 globalCompositeOperation 做出的神奇效果Canvas
- Android自定義View之Canvas的使用AndroidViewCanvas
- canvasCanvas
- 使用html2canvas將頁面轉成圖,用canvas2image下載HTMLCanvas
- 分享一個canvas程式碼2Canvas
- wxml2canvas爬坑之路XMLCanvas
- canvas 2 image的使用小心得Canvas
- HTML5學習之Canvas基礎知識HTMLCanvas
- Android 高階UI9 Canvas save和restore例項解析AndroidUICanvasREST
- 使用 HTML5 Canvas 實現圓形圖片裁剪並上傳HTMLCanvas
- 使用 HTML5 Canvas 實現使用者自定義裁剪圖片HTMLCanvas
- 小程式canvas適配android7,8CanvasAndroid
- WPF C# create canvas and draw ellipse in canvasC#Canvas
- canvas鍵盤打字練習功能Canvas
- canvas初探實踐-第一篇Canvas
- canvas rect()Canvas
- canvas strokeStyleCanvas
- canvas lineTo()Canvas