這是一篇總結(jié)性地文章,內(nèi)容來自扔物線文章以及網(wǎng)易公開課,本文是自己對(duì)文章的總結(jié)
一、View的坐標(biāo)系
每一個(gè)子View都有一個(gè)自己的坐標(biāo)系,并且互不影響,坐標(biāo)系的原點(diǎn)是View的左上角,遵循右正左負(fù),下正上負(fù)
如這張圖所示,在左上定點(diǎn)為畫布的原點(diǎn),圓心的左邊是(300,300)
二、canvas的作用
1.canvas可以指定繪制的位置,以及繪制什么樣的圖層
canvas.drawColor() 在整個(gè)繪制層上繪制一層背景色
三、Paint負(fù)責(zé)繪制的風(fēng)格
繪制的顏色,抗鋸齒,繪制線條的方式,實(shí)心還是空心等等和風(fēng)格相關(guān)的都是由paint來做的
Paint.setAntiAlias(boolean aa) 設(shè)置抗鋸齒開關(guān)
Paint.setStyle(Paint.Style.STROKE) 畫出圖形的線條 不會(huì)填充整個(gè)圖形
Paint.setStrokeCap(cap) 設(shè)置線條端點(diǎn)形狀
Paint. setShader 設(shè)置著色器
Paint.setColorFilter 設(shè)置顏色的過濾效果 比如加濾鏡
Paint.setStrokeJoin 設(shè)置線條拐角的方式
Paint.setDither(boolean dither) 加入抖動(dòng)效果有規(guī)律地?cái)_亂圖像來讓圖像對(duì)于肉眼更加真實(shí)
Paint.setFilterBitmap(filterBitmap)優(yōu)化圖像放大后的效果,消除馬賽克
Paint.setPathEffect 圖像外圍輪廓線的效果
Paint.setShadowLayer 給繪制的內(nèi)容加一層陰影 BlurMaskFilter 模糊效果
1. Paint.setStrokeCap(cap)效果示意圖
2. Paint.setFilterBitmap(true)效果示意圖
左邊是未開啟優(yōu)化的,右邊是開啟優(yōu)化的,可以看到少了許多馬賽克的效果
3. Paint.setStrokeJoin效果示意圖
4.使用著色器可以實(shí)現(xiàn)一種規(guī)律性的變化。著色器分為三類 線性漸變new LinearGradient,從中心進(jìn)行輻射漸變RadialGradient,像雷達(dá)
一樣掃描的漸變SweepGradient, 使用圖像來圖形上色 BitmapShader,將多個(gè)著色器組合起來使用的ComposeShader
線性的著色器示例
/**
* 1.線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
* (x0,y0):漸變起始點(diǎn)坐標(biāo)
* (x1,y1):漸變結(jié)束點(diǎn)坐標(biāo)
* color0:漸變開始點(diǎn)顏色,16進(jìn)制的顏色表示,必須要帶有透明度
* color1:漸變結(jié)束顏色
* colors:漸變數(shù)組
* positions:位置數(shù)組,position的取值范圍[0,1],作用是指定某個(gè)位置的顏色值,如果傳null,漸變就線性變化。
* tile:用于指定控件區(qū)域大于指定的漸變區(qū)域時(shí),空白區(qū)域的顏色填充方法
*/
mShader = new LinearGradient(0, 0, 500, 500, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
mPaint.setShader(mShader);
canvas.drawRect(0,0,1000,1000, mPaint);
環(huán)形的著色器示例
/* 環(huán)形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
* centerX ,centerY:shader的中心坐標(biāo),開始漸變的坐標(biāo)
* radius:漸變的半徑
* centerColor,edgeColor:中心點(diǎn)漸變顏色,邊界的漸變顏色
* colors:漸變顏色數(shù)組
* stoops:漸變位置數(shù)組,類似掃描漸變的positions數(shù)組,取值[0,1],中心點(diǎn)為0,半徑到達(dá)位置為1.0f
* tileMode:shader未覆蓋以外的填充模式。
*/
mShader = new RadialGradient(250, 250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
位圖的著色器示例
/**
* 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
* Bitmap:構(gòu)造shader使用的bitmap
* tileX:X軸方向的TileMode
* tileY:Y軸方向的TileMode
REPEAT, 繪制區(qū)域超過渲染區(qū)域的部分,重復(fù)排版
CLAMP, 繪制區(qū)域超過渲染區(qū)域的部分,會(huì)以最后一個(gè)像素拉伸排版
MIRROR, 繪制區(qū)域超過渲染區(qū)域的部分,鏡像翻轉(zhuǎn)排版
*/
mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
mPaint.setShader(mShader);
canvas.drawRect(0,0,500, 500, mPaint);
組合的著色器示例
/**
* 組合渲染,
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
* ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
* shaderA,shaderB:要混合的兩種shader
* Xfermode mode: 組合兩種shader顏色的模式
* PorterDuff.Mode mode: 組合兩種shader顏色的模式
*/
BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
LinearGradient linearGradient = new LinearGradient(0, 0, 1000, 1600, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
mPaint.setShader(mShader);
canvas.drawCircle(250, 250, 250, mPaint);
三、Canvas重點(diǎn)API
drawArc :畫扇形
drawPath(Path,Paint):畫自定義的圖形
drawTextOnPath:沿著一趟線繪制文字
1.對(duì)于drawPath需要傳入path對(duì)象。path對(duì)象又有幾種屬性。
addXXX 表示添加某圖形
quadTo:貝塞爾曲線
moveTo:將圓點(diǎn)移動(dòng)到指定的位置,不管畫什么圖形都是從當(dāng)前位置開始畫的,通過moveTo可以指定畫筆起始的位置。
close() 自動(dòng)封閉,假設(shè)畫了三角形的兩邊后直接調(diào)用該方法,會(huì)自動(dòng)將兩點(diǎn)連接起來形成封閉。
setFillType(Path.FillType ft) 設(shè)置填充方式
2.drawText難點(diǎn)
1.drawText指定的x,y是要繪制的文字左下角的坐標(biāo),縱坐標(biāo)y代表文字的基線
2.可以使用StaticLayout來實(shí)現(xiàn)繪制文字的自動(dòng)換行
- setTypeface設(shè)置字體
- setStrikeThruText刪除線setUnderlineText下劃線
- setLetterSpacing字符的間距
- setFontFeatureSettings使用css的方式設(shè)置字體
- setTextAlign對(duì)其方式
- setTextLocale設(shè)置繪制文字的地域文字類型。大陸簡(jiǎn)體 臺(tái)灣繁體
- getFontSpacing獲取推薦的行距,可以在換行繪制時(shí)使用
canvas.drawText(texts[1], 100, 150 + paint.getFontSpacing, paint);
4.canvas的裁切
繪制的內(nèi)容超出這個(gè)范圍會(huì)被裁切掉,使用clipRect方法。clipPath
5.保存canvas的一次繪制狀態(tài)
canvas.save, canvas.restore。幾何變化一定要配合save和restore來配合使用。否則將后續(xù)繪制也受之前的影響
canvas的幾何變換
canvas的幾何變換代碼執(zhí)行順序是倒序的,如果想要先旋轉(zhuǎn)再平移,那么平移代碼要寫在最上面,再寫旋轉(zhuǎn)的代碼。translate,scale,rotate,skew
6.canvas的平移
使用translate方法讓中心點(diǎn)平移到某個(gè)位置,由于canvas的幾何變換是反著的,所以如果要先平移到一個(gè)點(diǎn),再移動(dòng)回原點(diǎn)要先寫移動(dòng)回原點(diǎn)的代碼,再寫移動(dòng)到其他位置的代碼。
7.使用matris矩陣來變換
post..方法代表在前面插入,也就是變換代碼是順序執(zhí)行的
per..方法是往后邊的代碼插入,也就是和canvas的變換順序,會(huì)插入到其他變換代碼的后面。
四、使用Camera來實(shí)現(xiàn)三維旋轉(zhuǎn)
1.camera.save/restore/applytoCanvas
camera的操作是在圖像的原點(diǎn)(0,0)進(jìn)行的,因此使用camera變化是不對(duì)稱的,如果想要在圖形的中心點(diǎn)進(jìn)行變化,需要配合canvas的translate方法將canvas移動(dòng)到中心點(diǎn)進(jìn)行變化,然后再移動(dòng)回去。因?yàn)閏amera是不支持設(shè)置軸心的,軸心永遠(yuǎn)是(0,0點(diǎn))。
2.使用setLocation來將相機(jī)的位置向后移動(dòng)
相機(jī)后移投影的圖像變小。一般情況不需要移動(dòng)x,y 只需要移動(dòng)z軸。因?yàn)橄鄼C(jī)是在z軸上。
camera.setLocation(0, 0, newZ);
**3.camera的旋轉(zhuǎn)正方向
View繪制的過程
1.新繪制的總是會(huì)覆蓋之前繪制的內(nèi)容
2.View的繪制過程是從drawBackground(不能重寫),onDraw繪制主題,dispatchDraw繪制子view,drawForeground繪制前景色,而這些都是由draw方法觸發(fā)的
3.如果是直接繼承view,super.onDraw并沒有什么用,因?yàn)閛nDraw本身就是空實(shí)現(xiàn)
4.ViewGroup在通過onDraw繪制完自身后,會(huì)通過onDispatchDraw方法繪制子View
5.ViewGroup默認(rèn)會(huì)跳過draw方法而直接執(zhí)行dispatchDraw,如果想讓它繪制自身,使用setWillNotDraw(false)來執(zhí)行完整的繪制流程