Canvas&Paint使用心得

緣起

自己畫圖在平常開發(fā)中不算很常見的需求凌摄,但偶爾有些需求還必須通過Canvas自己畫出來浪秘,最近筆者就遇到了這樣的事情,由于以前對這些API不是很熟悉丁眼,一路走來也是磕磕絆絆筷凤,不過總算熬過來了,最終也算是對這些API有了更深刻的認(rèn)識苞七,正好寫篇文章記錄下藐守,供參考挪丢。

實際開發(fā)中發(fā)現(xiàn),當(dāng)我們new一個Paint的時候卢厂,其默認(rèn)的style就是FILL模式乾蓬,strokeWidth默認(rèn)大概1像素左右,一般如果你用到的話足淆,最好自己顯式設(shè)置成合適的值巢块,單位為像素。

各種API的使用詳解

  1. Canvas#drawCircle(float cx, float cy, float radius, Paint paint);
    作用:畫一個圓巧号;
    cx族奢,cy表示圓心,radius表示半徑丹鸿,paint的style如果是stroke則畫出來的是一個鏤空的圓越走,否則會是填充效果的圓;
    正常畫圓的時候靠欢,這個API還是很簡單的廊敌,但當(dāng)我們設(shè)置了paint的strokeWidth為某一具體值時,比如50px门怪,即我們想畫一個圓環(huán)效果骡澈。
    但當(dāng)你通過這樣的方式畫一個帶寬度的圓環(huán)時,半徑要特別注意下掷空,舉例如下:
    假設(shè)你要在寬高都是y的矩形區(qū)域畫一個寬度為strokeW的圓環(huán)肋殴,那么圓環(huán)的半徑應(yīng)該是:
    r1 = y /2; 外圓,緊切著最外面的矩形區(qū)域
    r2 = y/2 - strokeW; // 半徑稍小的內(nèi)圓
    這時坦弟,你可能以為半徑為r2就ok了护锤,可是實際測試發(fā)現(xiàn),當(dāng)通過drawCircle畫一個帶有寬度的圓時(圓環(huán))酿傍,正確的半徑應(yīng)該是r = r2 + strokeW/2, 比想象中的要往外再擴大點烙懦,即要加上一半的strokeW;
    可以簡單理解成有寬度時,需要的半徑是中心圓(即不是內(nèi)圓也不是外圓)的半徑(外圓半徑-strokeW/2或者內(nèi)圓半徑+strokeW/2)赤炒。

  2. Canvas#drawOval(RectF oval, Paint paint);
    作用:畫橢圓
    oval:給定的矩形區(qū)域氯析,在這個邊界內(nèi)畫橢圓(矩形的內(nèi)切圓),如果這個矩形區(qū)域恰好是正方形可霎,那么畫出來的橢圓實際上就是圓了魄鸦,介紹這個主要是為了給下面的畫弧線做鋪墊。

  3. Canvas#drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);
    作用:畫弧線癣朗,橢圓的某一部分拾因;
    oval: 弧線所在的橢圓的邊界矩形區(qū)域,同上面的解釋;
    startAngle: 起始角度绢记,0度是指x軸正方向(鐘表上的3點鐘方向)扁达,正數(shù)表示沿順時針方向轉(zhuǎn),負(fù)數(shù)則是逆時針方向蠢熄,<0或>360實際相當(dāng)于startAngle%360;
    sweepAngle: 掃過的角度跪解,正數(shù)表示順時針掃過,負(fù)數(shù)表示逆時針掃過签孔,如果>360 or <-360叉讥,則整個橢圓會被畫出來;
    useCenter:一般為false饥追,不包括中心點图仓,可以設(shè)為true來畫一部分扇形;

  4. Canvas#drawText(String text, float x, float y, Paint paint)但绕;
    作用:畫文字救崔,這個時候經(jīng)常需要調(diào)用paint#setTextSize方法來設(shè)置文字的大小,單位是px捏顺;
    其中Paint里面的textAlign六孵,對最終結(jié)果會有重要的影響。
    paint.setTextAlign(Paint.Align.RIGHT);
    比如text是“你好啊世界”
    假設(shè)你Text align是Left幅骄,那么 x,y是相對text的左邊說的劫窒,也就是會把“你”這個文字畫在x的位置;
    center也是同樣的道理拆座,x表示中間字的位置烛亦,Right是說會把“界”字畫在x位置,其他文字還是會在左邊依次畫出來懂拾;
    這里的y是指文字的baseline,并不是我們常見的top頂部铐达,效果上是要偏下方點岖赋,注意這個區(qū)別。

  5. Canvas#transalte(dx, dy) 平移畫布
    作用:將當(dāng)前的畫布坐標(biāo)原點移動dx瓮孙,dy唐断,比如原先是0,0杭抠,經(jīng)過(100, 100)操作后脸甘,新的繪制對應(yīng)的原點就是(100,100)偏灿;

  6. Canvas#scale(sx, sy)丹诀、scale(sx, sy, px, py) 縮放畫布
    這2個方法的區(qū)別,可以看下源碼,很清楚的展現(xiàn)了區(qū)別:

public void scale(float sx, float sy) {  
        native_scale(mNativeCanvasWrapper, sx, sy);
}
public final void scale(float sx, float sy, float px, float py) { 
        translate(px, py);    
        scale(sx, sy);    
        translate(-px, -py);
}

畫布的縮放铆遭,比如scale(0.5f, 0.5f) 表示x硝桩、y方向上各縮小一半,比如畫了個400*400的矩形枚荣,出來的效果就是200*200的碗脊,px,py表示對原點的平移橄妆。

  1. Canvas#rotate(float degrees, float px, float py); 旋轉(zhuǎn)畫布
    它的理解幾乎和scale一模一樣衙伶,這個方法在有些情況下是非常有用的,比如有個需求是要畫個類似鐘表刻度那樣的界面害碾,如下:

    鐘表刻度盤

    你要做的只是畫一條垂直方向的直線(線段)矢劲,然后不停的旋轉(zhuǎn)不同的角度即可(旋轉(zhuǎn)360度),按照這個思路一下子就可以將這個復(fù)雜的問題完美解決掉蛮原。
    對這幾個變換方法的理解可以參考下這篇文章卧须,寫的非常不錯。

  2. 給Paint設(shè)置漸變器Shader儒陨;
    對Shader的理解可以參考這篇文章Shader圖文詳解 花嘶。
    經(jīng)常我們需要用漸變色填充一個區(qū)域(比如由path決定的),實際中常用在繪制收益率曲線蹦漠,然后將曲線圍起來的下方區(qū)域用漸變色填充起來椭员,示意代碼如下:

 private void fillRegionWithGradientColor(Canvas canvas, Paint paint) {
        int w = getWidth();
        int h = getHeight();

        Path path1 = new Path();
        path1.moveTo(0, h);
        path1.lineTo(100, 200);
        path1.lineTo(150, 300);
        path1.lineTo(w/2, h/2);
        path1.lineTo(w/2+150, h/2);

        path1.lineTo(w, h);
       //path1.close();

        // 為Paint設(shè)置漸變器 在豎直方向從h/2到h漸變2個顏色值
        Shader mShader = new LinearGradient(0, h/2, 0, h, new int[] {
                0xffff5377, 0xfffeeeee}, null,
                Shader.TileMode.CLAMP);
        paint.setShader(mShader);
        canvas.drawPath(path1, paint);
    }
  1. Paint#setShadowLayer(float radius, float dx, float dy, int shadowColor);
    作用:實現(xiàn)在幾何圖形底部畫陰影的效果,可以想象成陽光從上往下斜著照射笛园;
    radius:陰影模糊層的高度隘击,為0表示沒有陰影層,值越大陰影區(qū)域越大但也更模糊研铆,人視覺上的效果相當(dāng)于在dx/dy偏移量的基礎(chǔ)上再拼上個radius這么大的模糊層埋同,一般你不想讓它看起來很模糊的話,傳一個比較小的值棵红,比如傳1就好了凶赁,注意當(dāng)這個值為0時,即使有dx/dy也不會有陰影畫出來逆甜;
    dx虱肄,dy:這2個值是陰影圖形相對于原圖形的偏移,可以想象成陽光從上往下以不同的角度照過來交煞,比如都為正數(shù)30咏窿,相當(dāng)于往右下角平移30個像素;
    shadowColor:陰影的顏色素征,如果這個顏色值不帶透明度的話集嵌,那透明度會使用Paint的(如果它有的話)萝挤,否則用陰影自己的透明度;

總結(jié)

這些API其實用起來也沒多少難度纸淮,大家在不確定的時候最好能夠動手寫個小demo跑起來看看效果平斩,一般也都能搞明白作用。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末咽块,一起剝皮案震驚了整個濱河市绘面,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侈沪,老刑警劉巖揭璃,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亭罪,居然都是意外死亡瘦馍,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門应役,熙熙樓的掌柜王于貴愁眉苦臉地迎上來情组,“玉大人,你說我怎么就攤上這事箩祥≡撼纾” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵袍祖,是天一觀的道長底瓣。 經(jīng)常有香客問我,道長蕉陋,這世上最難降的妖魔是什么捐凭? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮凳鬓,結(jié)果婚禮上茁肠,老公的妹妹穿的比我還像新娘。我一直安慰自己缩举,他們只是感情好官套,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚁孔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惋嚎。 梳的紋絲不亂的頭發(fā)上杠氢,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音另伍,去河邊找鬼鼻百。 笑死绞旅,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的温艇。 我是一名探鬼主播因悲,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勺爱!你這毒婦竟也來了晃琳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤琐鲁,失蹤者是張志新(化名)和其女友劉穎卫旱,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體围段,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡顾翼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奈泪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片适贸。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖涝桅,靈堂內(nèi)的尸體忽然破棺而出拜姿,到底是詐尸還是另有隱情,我是刑警寧澤苹支,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布砾隅,位于F島的核電站,受9級特大地震影響债蜜,放射性物質(zhì)發(fā)生泄漏晴埂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一寻定、第九天 我趴在偏房一處隱蔽的房頂上張望儒洛。 院中可真熱鬧,春花似錦狼速、人聲如沸琅锻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恼蓬。三九已至,卻和暖如春僵芹,著一層夾襖步出監(jiān)牢的瞬間处硬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工拇派, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荷辕,地道東北人凿跳。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像疮方,于是被迫代替她去往敵國和親控嗜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容