canvas的使用

1:畫(huà)圓
canvas.drawCircle(width / 2, height / 2, radius, mPaint);//繪制圓形,第一個(gè)參數(shù)是圓心的x坐標(biāo),第二個(gè)參數(shù)是圓心的y坐標(biāo),第三個(gè)參數(shù)是半徑,單位都是像素
2:畫(huà)矩形canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);//這里繪制出來(lái)的矩形是實(shí)心的矩形,而不是空心的矩形線條,因?yàn)閜aint設(shè)置的style是Paint.Style.FILL,前四個(gè)參數(shù)的具體含義請(qǐng)看下圖
image.png
3:canvas.save()和canvas.restore()的區(qū)別
@Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),paint);
        canvas.drawRect(10,10,getMeasuredWidth()-10,getMeasuredHeight()-10,paint1);
        canvas.save();
        canvas.translate(10,0);
        canvas.restore();
        super.onDraw(canvas);
    }
區(qū)別是:當(dāng)調(diào)用save方法后,就將canvas的位置和角度記錄下來(lái)了,然后接下來(lái)就可以進(jìn)行畫(huà)布的平移,旋轉(zhuǎn)之類(lèi)的位置變化操作,也可以進(jìn)行畫(huà)圖操作,不過(guò)此時(shí)所畫(huà)的圖是在進(jìn)行了位置變化操作之后的canvas上進(jìn)行的,如果要還原上一次保存的canvas的位置的話,就調(diào)用restore方法,這時(shí)canvas的位置就回到了上一次save時(shí)的狀態(tài)了。
4,畫(huà)圓?。篸rawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

oval :指定圓弧的外輪廓矩形區(qū)域。
startAngle: 圓弧起始角度(x軸的正右的方向,是0度的位置),單位為度。
sweepAngle: 圓弧掃過(guò)的角度,順時(shí)針?lè)较驗(yàn)檎嵌?,單位為?br> useCenter: 如果為T(mén)rue時(shí),用來(lái)繪制扇形,如果為false時(shí),用來(lái)繪制弧形。
paint: 繪制圓弧的畫(huà)板屬性,如顏色,是否填充等。

paint.setStyle(Paint.Style.FILL);
canvas.drawArc(200,100,800,500,180,60,false,paint);
以上兩句代碼畫(huà)出的形狀是
5,畫(huà)筆的一些方法

1:用paint的時(shí)候有三種Style,分別是
Paint.Style.STROKE 只繪制圖形輪廓(描邊)
Paint.Style.FILL 只繪制圖形內(nèi)容 ,默認(rèn)是Paint.Style.FILL
Paint.Style.FILL_AND_STROKE 既繪制輪廓也繪制內(nèi)容


image.png

2:mPaint.setStrokeWidth(40);//用來(lái)設(shè)置畫(huà)筆的寬度

6,設(shè)置畫(huà)布的顏色,這類(lèi)顏色填充方法一般用于在繪制之前設(shè)置底色,或者在繪制之后為界面設(shè)置半透明蒙版。
        canvas.drawColor(Color.RED);
        canvas.drawARGB(100,100,100,100);
        canvas.drawRGB(100,100,100);
7,設(shè)置線條的寬度,在STROKE和FILL_AND_STROKE下使用
paint.setStrokeWidth(10);//設(shè)置線條寬度為10像素
8,在繪制的時(shí)候,往往需要開(kāi)啟抗鋸齒來(lái)讓圖形和文字的邊緣更加平滑
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);//靜態(tài)開(kāi)啟抗鋸齒
        paint.setAntiAlias(true);//動(dòng)態(tài)開(kāi)啟抗鋸齒
9,繪制一個(gè)點(diǎn),前兩個(gè)參數(shù)是x,y坐標(biāo),點(diǎn)的大小可以通過(guò)paint.setStrokeWidth來(lái)設(shè)置,點(diǎn)的形狀可以通過(guò)paint.setStrokeCap來(lái)設(shè)置,其中,SQUARE或BUTT畫(huà)出來(lái)是方形的點(diǎn),ROUND畫(huà)出來(lái)是圓形的點(diǎn)。
canvas.drawPoint(100,100,paint);
10,畫(huà)橢圓
canvas.drawOval(100,100,200,500,paint);
11,畫(huà)線,由于直線不是封閉圖形,所以paint.setStyle對(duì)直線沒(méi)有影響,canvas.drawLine是畫(huà)一條線,可以用canvas.drawLines批量畫(huà)線
canvas.drawLine(200,200,400,400,paint);
12,畫(huà)圓角矩形,第五個(gè)和第六個(gè)參數(shù)是矩形的每個(gè)圓角的橫向半徑和縱向半徑
canvas.drawRoundRect(200,300,400,500,80,80,paint);
13,根據(jù)path畫(huà)圖形
canvas.drawPath(path, paint);

其中,Path對(duì)象有如下

第一組,add...方法(添加完整封閉圖形,除了addPath())

        path.addCircle(300,300,200, Path.Direction.CW);//添加圓
        //path.addOval();//添加橢圓
        //path.addRect();//添加矩形
        //path.addRoundRect();添加圓角矩形
        //path.addPath();添加path

第二組,...To方法(畫(huà)直線或者曲線)

        //lineTo和rLineTo畫(huà)直線
        paint.setStyle(Paint.Style.STROKE);//如果參數(shù)是Paint.Style.FILL,那么畫(huà)出來(lái)的是個(gè)三角形,和上面的那個(gè)畫(huà)圓弧的一樣,將畫(huà)筆style設(shè)置為FILL
        path.lineTo(100,100);//參數(shù)是絕對(duì)坐標(biāo),由當(dāng)前位置(0,0)向(100,100)畫(huà)一條直線
        path.rLineTo(100,0);//參數(shù)是相對(duì)坐標(biāo),由當(dāng)前位置(100,100)向正右方100像素的位置畫(huà)一條直線
        canvas.drawPath(path, paint);

        //moveTo移動(dòng)原點(diǎn)位置
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);//相對(duì)于原點(diǎn)(0,0)畫(huà)直線到點(diǎn)(100,100)
        path.moveTo(200,100);//此時(shí)原點(diǎn)坐標(biāo)為(200,100)
        path.lineTo(200,0);//相對(duì)于原點(diǎn)(200,100)畫(huà)直線到點(diǎn)(200,0),注意這個(gè)(200,0)點(diǎn)還是以(0,0)為原點(diǎn)的(200,0)點(diǎn),因?yàn)橛玫氖莑ineTo,如果是rLineTo()則原點(diǎn)為(200,100)
        canvas.drawPath(path, paint);

        //arcTo畫(huà)弧線
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);
        path.arcTo(100,100,300,300,-90,90,false);//第七個(gè)參數(shù)為直線連線連到弧形起點(diǎn),true為無(wú)痕跡,false為有痕跡,如果沒(méi)有path.lineTo(100,100);這句
        //代碼的話,true和false的效果是一樣的
        canvas.drawPath(path, paint);

        //addArc畫(huà)弧線
        paint.setStyle(Paint.Style.STROKE);
        path.lineTo(100,100);
        path.addArc(100,100,300,300,-90,90);//path.addArc(100,100,300,300,-90,90)相當(dāng)于path.arcTo(100,100,300,300,-90,90,true),addArc()相當(dāng)于arcTo()的第七個(gè)參數(shù)為true的簡(jiǎn)化版
        canvas.drawPath(path, paint);

第三,Path的close方法,不是所有的子圖形都需要使用path的close()來(lái)封閉的,當(dāng)paint的style是FILL或者是FILL_AND_STROKE時(shí),Path會(huì)自動(dòng)封閉子圖形,這就是上面畫(huà)弧和畫(huà)兩條線,如果設(shè)置為FILL,畫(huà)出來(lái)的是填充的弧和三角形的原因。

        paint.setStyle(Paint.Style.FILL);
        path.moveTo(100,100);
        path.lineTo(200,100);
        path.lineTo(150,150);
        canvas.drawPath(path, paint);//這里只繪制了兩條邊,但由于style是FILL,所以繪制時(shí)會(huì)自動(dòng)封口

第四,Path的setFillType方法,對(duì)于添加子圖形類(lèi)方法(如path.addCircle(),path.addRect())的方向,由方法的dir參數(shù)來(lái)控制,而對(duì)于畫(huà)線類(lèi)的方法(如path.lineTo(),path.arcTo())的方向就是圖形的方向

        paint.setStyle(Paint.Style.FILL);
        path.addCircle(300,300,200, Path.Direction.CCW);//CW順時(shí)針,CCW逆時(shí)針
        path.addCircle(300,300,100, Path.Direction.CW);
        path.setFillType(Path.FillType.INVERSE_WINDING);//EVEN_ODD是如果是奇數(shù)就繪制,也就是說(shuō)如果兩個(gè)圖形有部分重合,那么重合的那部分就不繪制,繪制剩下的
        //WINDING是按方向進(jìn)行相加的,順時(shí)針?lè)较?1,逆時(shí)針?lè)较?1,最后為0的那部分不繪制,繪制剩下的
        //INVERSE_EVEN_ODD就是將EVEN_ODD反過(guò)來(lái)
        //INVERSE_WINDING就是將WINDING反過(guò)來(lái)
        canvas.drawPath(path,paint);
來(lái)個(gè)圖片,通俗易懂
14,畫(huà)Bitmap
Bitmap bitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
...
canvas.drawBitmap(bitmap,100,100,paint);
15,繪制文字
        paint.setTextSize(100);//設(shè)置文字的大小
        canvas.drawText("你好啊",200,200,paint);

以前記錄過(guò)的

        Paint a=new Paint();
        a.setColor(Color.RED);
        //a.setAlpha(100);
        //a.setStyle(Style.FILL_AND_STROKE);//設(shè)置畫(huà)筆的風(fēng)格
        //a.setStrokeWidth(33);//設(shè)置空心線寬
        a.setTextSize(34);//設(shè)置畫(huà)筆字體的大小
        //a.setTypeface(Typeface.DEFAULT_BOLD);//設(shè)置字體樣式
        //a.setTextScaleX(55);//設(shè)置比例因子,以一為標(biāo)準(zhǔn)
        //a.setARGB(40, 45, 88, 66);//設(shè)置字體的顏色
        //a.setUnderlineText(true);//設(shè)置下劃線
        //a.setTextSkewX(3);//設(shè)置傾斜因子,以零為標(biāo)準(zhǔn)
        canvas.drawColor(Color.GREEN);//設(shè)置背景顏色
        //canvas.drawText("n好啊", 70, 90, a);
        ///canvas.drawCircle(33, 22, 44, a);
        //canvas.drawLine(33, 44, 11, 22, a);
        //canvas.drawPoint(44, 55, a);
        //canvas.drawRoundRect(new RectF(55,277,488,499), 35, 22, a);//繪制圓角矩形
        //canvas.drawOval(new RectF(33,333,222,444), a);//繪制橢圓形
        //Path ab=new Path();
        //ab.moveTo(33, 44);
        //ab.lineTo(77, 88);
        //ab.lineTo(76, 55);
        //canvas.drawPath(ab, a);//繪制任意多邊形
        //canvas.drawArc(new RectF(33,44,333,444), 66, 55, true, a);//繪制圓弧
        //Bitmap ac=((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap();
        //canvas.drawBitmap(ac, 444, 44, a);//繪制圖像
        
        //canvas.clipRect(44, 66, 222, 330);//裁剪指定的區(qū)域
        //canvas.drawColor(Color.BLUE);
        //canvas.drawText("旋轉(zhuǎn)字", 43, 333, a);
        //canvas.save();
        //canvas.rotate(60,43,333);
        //canvas.drawText("旋轉(zhuǎn)字", 43, 333, a);
        //canvas.restore();//關(guān)于畫(huà)布鎖定和解鎖,旋轉(zhuǎn)的例子

-----------------------------------------------------------------------------------

android群英傳中對(duì)canvas的介紹

1:Canvas.save(),Canvas.restore(),Canvas.translate(),Canvas.rotate()這四個(gè)方法的介紹如下:

Canvas.save()這個(gè)方法,從字面上可以理解為保存畫(huà)布,它的作用就是將之前的所有已繪制圖像保存起來(lái),讓后續(xù)的操作就好像在一個(gè)新的圖層上操作一樣,這一點(diǎn)點(diǎn)與photoshop中的圖層理解基本一致。
Canvas.restore()這個(gè)方法,則可以理解為photoshop中的合并圖層操作,它的作用是將我們?cè)趕ave()之后繪制的所有圖像與save()之前的圖像進(jìn)行合并。
translate()和rotate()方法,就是在調(diào)用translate(x,y)方法之后,將原點(diǎn)(0,0)移動(dòng)到(x,y)。之后的所有繪圖操作都將以(x,y)為原點(diǎn)執(zhí)行。同理totate()方法也是一樣的,它將坐標(biāo)系旋轉(zhuǎn)了一定的角度。

2:Layer圖層

在android中通過(guò)調(diào)用saveLayer()方法,saveLayerAlpha()方法創(chuàng)建一個(gè)圖層,使用restore()方法,restoreToCount()方法合并所有圖層。創(chuàng)建圖層的時(shí)候,后面所有的操作都發(fā)生在這個(gè)圖層上。saveLayerAlpha()的第五個(gè)參數(shù)的取值如果是0比表示完全透明,127表示半透明,255表示完全不透明。示例代碼如下:

        canvas.drawCircle(300,300,200,paint);
        canvas.saveLayerAlpha(0,0,600,600,127);
        paint.setColor(Color.GREEN);
        canvas.drawCircle(300,300,300,paint);
        canvas.restore();

圖如下所示:


3:PorterDuffXfermode(參考文章:http://www.itdecent.cn/p/0f64daf202f2)


示例代碼如下:

...
        canvas.saveLayer(0,0,canvas.getWidth(),canvas.getHeight(),paint);//必須要新建一個(gè)圖層才能看到混合后的效果了
        canvas.drawCircle(0,0,bitmap.getWidth()/2,paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmap,0,0,paint);
        paint.setXfermode(null);// 還原混合模式
        canvas.restore();//合并圖層
...

效果如下:


4:Shader,著色器,渲染器,Shader包括:BitmapShader(位圖Shader),LinearGradient(線性Shader),RadialGradient(光速Shader),SweepGradient(梯度Shader),ComposeShader(混合Shader)

4.1:BitmapShader的使用,填充模式有三種CLAMP(拉伸),REPEAT(重復(fù)),MIRROR(鏡像),示例代碼如下:

 paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);

結(jié)果如下所示:



4.2:LinearGradient的使用,示例代碼如下:

 paint.setShader(new LinearGradient(0,0,canvas.getWidth(),canvas.getHeight(),Color.BLUE,Color.GREEN, Shader.TileMode.CLAMP));
        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2 > canvas.getHeight() / 2 ? canvas.getHeight() / 2 : canvas.getWidth() / 2, paint);

結(jié)果如下所示:


小技巧:Marix.setScale(1F,-1F)可以實(shí)現(xiàn)圖片的垂直翻轉(zhuǎn)。

5:PathEffect

5.1:DiscretePathEffect,使用這個(gè)效果之后,線段上就會(huì)產(chǎn)生許多雜點(diǎn)

        paint.setPathEffect(new DiscretePathEffect(3f,5f));
        Path path=new Path();
        path.moveTo(0,canvas.getHeight()/2);
        path.lineTo(canvas.getWidth()/3,0);
        path.lineTo(canvas.getWidth()/3*2,canvas.getHeight());
        path.lineTo(canvas.getWidth(),0);
        canvas.drawPath(path,paint);

效果圖如下:



5.2:DashPathEffect,這個(gè)效果可以用來(lái)繪制虛線,用一個(gè)數(shù)組來(lái)設(shè)置各個(gè)點(diǎn)之間的間隔,此后繪制虛線時(shí)就重復(fù)這樣的間隔進(jìn)行繪制,另一個(gè)參數(shù)則用來(lái)控制繪制時(shí)數(shù)組的一個(gè)偏移量,通??梢酝ㄟ^(guò)設(shè)置值來(lái)實(shí)現(xiàn)路徑的動(dòng)態(tài)效果。

  paint.setPathEffect(new DashPathEffect(new float[]{20,10,5,10},0));

效果圖如下:



5.3:PathDashPathEffect,這個(gè)效果和DashPathEffect效果類(lèi)似,只不過(guò)它的功能更加強(qiáng)大,可以設(shè)置顯示點(diǎn)的圖形,即方形點(diǎn)的虛線,圓形點(diǎn)的虛線。

        Path path1=new Path();
        path1.addRect(0,0,8,8,Path.Direction.CCW);
        paint.setPathEffect(new PathDashPathEffect(path1,12f,0,PathDashPathEffect.Style.ROTATE));

效果圖如下:



5.4:CornerPathEffect,就是將拐角處變得圓滑,具體圓滑的程度,則由參數(shù)決定。

 paint.setPathEffect(new CornerPathEffect(30));

效果圖如下:



5.5:ComposePathEffect,將任意兩種路徑特效組合起來(lái)形成一個(gè)新的效果。

        PathEffect pathEffect=new CornerPathEffect(30);
        PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
        paint.setPathEffect(new ComposePathEffect(pathEffect,pathEffect1));

效果圖如下:



5.6:SumPathEffect,將任意兩種路徑特效組合起來(lái)形成一個(gè)新的效果。

        PathEffect pathEffect=new CornerPathEffect(30);
        PathEffect pathEffect1=new DashPathEffect(new float[]{20,10,5,10},0);
        paint.setPathEffect(new SumPathEffect(pathEffect,pathEffect1));

效果圖如下:


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容