Android從0到1繪制冬奧吉祥物冰墩墩,實(shí)現(xiàn)一戶一墩
北京冬奧雖然已經(jīng)結(jié)束了,但吉祥物冰墩墩的熱度依然不減,毫不疑問冰墩墩是今年冬奧名副其實(shí)的新晉頂流?,F(xiàn)在網(wǎng)上還流傳著一句很貼切的話,那就是一“墩”難求。既然身無余“墩”,那就畫一個(gè)夢(mèng)中情“墩”,學(xué)會(huì)繪制冰墩墩,手動(dòng)實(shí)現(xiàn)一戶一墩不是夢(mèng),趕快學(xué)起來吧。
先來看看最終效果圖:

根據(jù)效果圖,我們大概可以看出這得自定義繪制,此冰墩墩基本是由點(diǎn)、矩形、橢圓、圓等常規(guī)圖形構(gòu)成,重點(diǎn)還是使用了比較多的曲線繪制而成,常規(guī)圖形可以使用Canvas繪制,曲線則要使用Path繪制貝塞爾曲線,我們先來回顧一下涉及的知識(shí)點(diǎn)。
一、涉及知識(shí)點(diǎn)
回顧一下畫筆paint涉及的API:

回顧一下canvas繪制涉及的API:

回顧一下path涉及的API:

具體到每個(gè)API這里就不展開講解了,如有需要可以查閱相關(guān)資料。
二、實(shí)現(xiàn)步驟
1、首先畫一個(gè)橢圓,如下圖所示:

這個(gè)還是比較簡(jiǎn)單的,繪制長(zhǎng)半軸在y軸的橢圓,橢圓具體數(shù)值短半軸為屏幕寬度/4,長(zhǎng)半軸為屏幕高度/6,具體代碼如下:
private void init() {//初始化矩陣rectF = new RectF();//創(chuàng)建畫筆paint = new Paint();//設(shè)置畫筆顏色paint.setColor(Color.BLACK);//設(shè)置畫筆寬度paint.setStrokeWidth(10);//設(shè)置畫筆填充方法:描邊paint.setStyle(Paint.Style.STROKE);//設(shè)置抗鋸齒paint.setAntiAlias(true);paintBlack.setColor(Color.BLACK);paintBlack.setStrokeWidth(10);paintBlack.setStyle(Paint.Style.FILL);paintBlack.setAntiAlias(true);paintRed.setColor(Color.parseColor("#AA292D"));paintRed.setStrokeWidth(10);paintRed.setStyle(Paint.Style.FILL);paintRed.setAntiAlias(true);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {//設(shè)置中心點(diǎn)mCentenWith = w / 2;mCentenHight = h / 2;//設(shè)置橢圓長(zhǎng)、短半軸mWith = mCentenWith / 2;mHight = mCentenHight / 3;super.onSizeChanged(w, h, oldw, oldh);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制頭部//將坐標(biāo)原點(diǎn)移動(dòng)到屏幕中心canvas.translate(mCentenWith, mCentenHight);//設(shè)置矩陣坐標(biāo)rectF.set(-mWith, -mHight, mWith, mHight);//畫橢圓canvas.drawOval(rectF, paint);}
2、然后再畫兩個(gè)耳朵,并填滿顏色,如圖所示:

這里繪制用到的是二階貝塞爾曲線,還涉及到橢圓上的點(diǎn)x、y坐標(biāo)的確認(rèn),根據(jù)參數(shù)方程:
x=acost;y=bsint;焦點(diǎn)在y軸上,短半軸為a,長(zhǎng)半軸為b,t為坐標(biāo)角度這里二階貝塞爾曲線起點(diǎn)設(shè)置在橢圓角度為π/5處,而終點(diǎn)設(shè)置在橢圓角度為π/3處,具體代碼如下所示:
private Path mPathEar1 = new Path();private Path mPathEar2 = new Path();@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右耳朵// x=acost;y=bsint;焦點(diǎn)在y軸上,短半軸為a,長(zhǎng)半軸為b//起點(diǎn)float ear_x1 = (float) (mWith * Math.cos(Math.PI / 5));float ear_y1 = (float) (mHight * Math.sin(Math.PI / 5));//終點(diǎn)float ear_x2 = (float) (mWith * Math.cos(Math.PI / 3));float ear_y2 = (float) (mHight * Math.sin(Math.PI / 3));//移動(dòng)起點(diǎn)位置mPathEar1.moveTo(ear_x1, -ear_y1);//繪制曲線mPathEar1.quadTo(mWith, -mHight, ear_x2, -ear_y2);canvas.drawPath(mPathEar1, paintBlack);//繪制左耳朵//移動(dòng)起點(diǎn)位置mPathEar2.moveTo(-ear_x1, -ear_y1);//繪制曲線mPathEar2.quadTo(-mWith, -mHight, -ear_x2, -ear_y2);canvas.drawPath(mPathEar2, paintBlack);}
3、接下來就是繪制冰墩墩的兩只手臂啦,在右手臂再畫一個(gè)小心心在手上顏色填滿,如圖所示:

這里就要用到三階貝塞爾曲線啦,這里的難點(diǎn)主要是控制點(diǎn)的坐標(biāo)不好掌握,我這里繪制的點(diǎn)都是通過測(cè)試獲取的,所以調(diào)試時(shí)間還是用的比較多的,最好的請(qǐng)?jiān)O(shè)計(jì)幫忙,通過ps給個(gè)大致估算,這里只是跟著感覺試出來的,這里的愛心是通過四段三階貝塞爾曲線合成的愛心,具體代碼如下:
private Path mPathHandRight = new Path();private Path mPathHandLeft = new Path();private Path mPathHeart = new Path();@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右手//終點(diǎn)float hand_x = (float) (mWith * Math.cos(Math.PI / 8));float hand_y = (float) (mHight * Math.sin(Math.PI / 8));//移動(dòng)起點(diǎn)mPathHandRight.moveTo(mWith, 0);//繪制曲線mPathHandRight.cubicTo(mWith * 7 / 6, -mHight / 2, 2 * mWith, -mHight / 4, hand_x, hand_y);canvas.drawPath(mPathHandRight, paintBlack);//繪制右手紅心,這里的愛心是通過四段三階貝塞爾曲線合成的愛心//重新設(shè)置坐標(biāo)原點(diǎn),將畫布平移到右手位置canvas.translate(mWith * 9 / 7, -mHight / 8);//將畫布旋轉(zhuǎn)30度canvas.rotate(30);//移動(dòng)起點(diǎn)mPathHeart.moveTo(0, -2);//繪制曲線mPathHeart.cubicTo(mWith / 16, -mHight / 16, mWith / 12, -mHight / 16, mWith / 12, 0);canvas.drawPath(mPathHeart, paintRed);//繪制曲線mPathHeart.cubicTo(mWith / 12, 0, mWith / 12, mHight / 16, 0, mHight / 12);canvas.drawPath(mPathHeart, paintRed);//移動(dòng)起點(diǎn)mPathHeart.moveTo(0, -2);//繪制曲線mPathHeart.cubicTo(-mWith / 16, -mHight / 16, -mWith / 12, -mHight / 16, -mWith / 12, 0);canvas.drawPath(mPathHeart, paintRed);//繪制曲線mPathHeart.cubicTo(-mWith / 12, 0, -mWith / 12, mHight / 16, 0, mHight / 12);canvas.drawPath(mPathHeart, paintRed);//將畫布還原回去canvas.rotate(-30);canvas.translate(-mWith * 9 / 7, mHight / 8);//繪制左手//移動(dòng)起點(diǎn)mPathHandLeft.moveTo(-mWith, 0);//繪制曲線mPathHandLeft.cubicTo(-mWith * 5 / 3, mHight / 2, -mWith * 7 / 6, mHight, -hand_x, hand_y);canvas.drawPath(mPathHandLeft, paintBlack);}
4、接下來就是畫冰墩墩的兩只腳啦,顏色填滿,如圖所示:

這里也要用到三階貝塞爾曲線,控制點(diǎn)也是通過橢圓的長(zhǎng)短半軸試出來的,具體代碼如下所示:
private Path mPathArmRight = new Path();private Path mPathArmLeft = new Path();@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右腳//起點(diǎn)float arm_x = (float) (mWith * Math.cos(Math.PI / 3));float arm_y = (float) (mHight * Math.sin(Math.PI / 3));//終點(diǎn)float arm_final_x = (float) (mWith * Math.cos(Math.PI * 4 / 9));float arm_final_y = (float) (mHight * Math.sin(Math.PI * 4 / 9));//移動(dòng)起點(diǎn)mPathArmRight.moveTo(arm_x, arm_y);//繪制曲線mPathArmRight.cubicTo(arm_x + mWith / 12, mHight * 3 / 2, arm_x / 4, mHight * 3 / 2, arm_final_x, arm_final_y);canvas.drawPath(mPathArmRight, paintBlack);//繪制左腳//移動(dòng)起點(diǎn)mPathArmLeft.moveTo(-arm_x, arm_y);//繪制曲線mPathArmLeft.cubicTo(-(arm_x + mWith / 12), mHight * 3 / 2, -(arm_x / 4), mHight * 3 / 2, -arm_final_x, arm_final_y);canvas.drawPath(mPathArmLeft, paintBlack);}
5、接下來就是繪制頭部輪廓啦,先在內(nèi)部繪制類似饅頭的五環(huán)形狀,如圖所示:

這里主要用到的也是三階貝塞爾曲線,控制點(diǎn)數(shù)值也是模擬出來的,具體如下所示:
private Path mPathBody = new Path();private int[] colors = {Color.parseColor("#88C46A"), Color.parseColor("#E5C267"),Color.parseColor("#6872AE"), Color.parseColor("#AE2C6D"), Color.parseColor("#6CC4F3")};@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制臉部輪廓for (int i = 0; i < 5; i++) {float r = mWith * 7 / 8 - 10 * i;mPathBody.reset();//移動(dòng)起點(diǎn)mPathBody.moveTo(-r, 0);//控制點(diǎn)float x1 = mWith * 3 / 4 - 10 * i;float y1 = mHight / 2 - 10 * i;mPathBody.cubicTo(-x1, y1, x1, y1, r, 2);//控制點(diǎn)float x2 = mWith - 10 * i;float y2 = mHight * 5 / 4 - 10 * i;mPathBody.cubicTo(x2, -y2, -x2, -y2, -r, 2);//設(shè)置顏色paint.setColor(colors[i]);canvas.drawPath(mPathBody, paint);}//還原設(shè)置paint.setColor(Color.BLACK);}
6、接下來就是畫眼睛啦,畫兩個(gè)橢圓黑眼圈,如圖所示:

這里還是比較簡(jiǎn)單的,就是繪制橢圓,然后通過旋轉(zhuǎn),具體代碼如下所示:
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右眼睛輪廓//繪制矩陣rectF.set(mWith / 4, -mHight * 2 / 5, mWith * 3 / 4, mHight / 6);//旋轉(zhuǎn)角度canvas.rotate(-40);//繪制橢圓canvas.drawOval(rectF, paintBlack);//還原角度canvas.rotate(40);//繪制左眼睛輪廓//繪制矩陣rectF.set(-mWith / 4, -mHight * 2 / 5, -mWith * 3 / 4, mHight / 6);//旋轉(zhuǎn)角度canvas.rotate(40);//繪制橢圓canvas.drawOval(rectF, paintBlack);//還原角度canvas.rotate(-40);}
橢圓里再畫兩個(gè)大眼睛,如圖所示:

這里繪制大眼睛還是比較簡(jiǎn)單的,就是繪制兩個(gè)圓,代碼如下所示:
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右眼睛paint.setColor(Color.WHITE);canvas.drawCircle(mWith / 4, -mHight * 2 / 5, mWith / 6, paint);//還原設(shè)置paint.setColor(Color.BLACK);//繪制左眼睛paint.setColor(Color.WHITE);canvas.drawCircle(-mWith / 4, -mHight * 2 / 5, mWith / 6, paint);//還原設(shè)置paint.setColor(Color.BLACK);}
最后上色,留出眼白,點(diǎn)上高光比較可愛,如圖所示:

這里的眼白也是用圓繪制,具體代碼如下所示:
@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制右眼珠paint.setStyle(Paint.Style.FILL);canvas.drawCircle(mWith / 3, -mHight * 3 / 7, mWith / 20, paint);//還原設(shè)置paint.setStyle(Paint.Style.STROKE);//繪制左眼珠paint.setStyle(Paint.Style.FILL);canvas.drawCircle(-mWith / 3, -mHight * 3 / 7, mWith / 20, paint);//還原設(shè)置paint.setStyle(Paint.Style.STROKE);}
7、最后繪制冰墩墩的鼻子和嘴巴,如圖所示:

這里鼻子就是一個(gè)圓,嘴巴用到了二階貝塞爾曲線和點(diǎn),這也是比較簡(jiǎn)單的,具體代碼如下所示:
private Path mPathMouse = new Path();@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//繪制鼻子paint.setStyle(Paint.Style.FILL);//繪制圓canvas.drawCircle(0, -mHight / 7, mWith / 20, paint);//繪制嘴巴paint.setStyle(Paint.Style.STROKE);//移動(dòng)起點(diǎn)mPathMouse.moveTo(mWith / 4, 0);mPathMouse.quadTo(0, mHight / 6, -mWith / 4, 0);canvas.drawPath(mPathMouse, paint);//繪制嘴巴兩邊的點(diǎn)canvas.drawCircle(mWith / 4, 0, 1, paint);canvas.drawCircle(-mWith / 4, 0, 1, paint);}
到這里自定義的部分就繪制完成啦。
這里就不搞動(dòng)畫繪制了,需要的童鞋自己弄哈,接下來就是使用了,這還是比較簡(jiǎn)單的,如下所示:
xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity">android:layout_width="match_parent"android:layout_height="match_parent" />
需要源碼的童鞋【龍旋】公眾號(hào)后臺(tái)回復(fù)關(guān)鍵字:冰墩墩,注意這個(gè)讀墩(dun),別回復(fù)錯(cuò)關(guān)鍵字哈。
到這里就搞定啦。
