1捌治、餅圖可以應(yīng)用在多方面,比如 財務(wù)類資金用途占比統(tǒng)計纽窟、生活類個人喜好占比肖油、等等,待產(chǎn)品提出這樣得效果臂港,我們可以隨意的繪制出來森枪。下面我來一步步剖析餅圖的繪制過程。如下圖先看效果
2审孽、第一步先分析一下這個餅圖的思路县袱,首先這個餅圖是由多個扇形以及折線以及文字組成∮恿Γ可以分為三塊來分別繪制式散。首先需要用到的知識點(diǎn)先大概說一下。
· 畫扇形用到canvas.drawArc()或者用Path類下的path.arcTo() 都可以實(shí)現(xiàn)
· 畫折線用drawLine()即可
· 畫文字用drawText()即可
· 計算弧長上的坐標(biāo)需要用到三角函數(shù) cos 余弦打颤、 sin正弦
3暴拄、我們直接來分析代碼
/**
* 餅圖的顏色
*/
private int[] mColors = {Color.YELLOW, Color.RED, Color.GREEN, Color.BLUE, Color.GRAY, Color.LTGRAY};
/**
* 初始化各個扇形的角度
*/
private float[] mPieAngles = {123, 73, 63, 53, 23, 13};
/**
* 初始化文字
*/
private String[] texts = {"feng", "fang", "wei", "ran", "hello world", "some a bitch"};
/**
* 扇形最大的間隔度數(shù)
*/
private int angleDash = 2;
/**
* 扇形的半徑
*/
private int mRadius = 200;
以上是該餅圖所需要的一些初始化數(shù)據(jù)
4、先計算出view可用的寬和高方便平移坐標(biāo)系编饺,以及初始化扇形的外框矩形坐標(biāo)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//view 的可用高度
mViewHeight = h - getPaddingTop() - getPaddingBottom();
//view 的可用寬度
mViewWidth = w - getPaddingLeft() - getPaddingRight();
//畫扇形的矩形坐標(biāo)
mRectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
}
5揍移、之后我們需要初始化扇形、折線反肋、文字的畫筆那伐,以及坐標(biāo)系原點(diǎn)
private void init() {
//扇形的畫筆
mPiePaint = new Paint();
mPiePaint.setAntiAlias(true);
mPiepath = new Path();
//折線的畫筆
mLinePaint = new Paint();
mLinePaint.setStrokeWidth(2);
mLinePaint.setColor(Color.WHITE);
mLinePaint.setAntiAlias(true);
//文字的畫筆
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(25);
//標(biāo)題的畫筆
mTitlePaint = new Paint();
mTitlePaint.setTextSize(40);
mTitlePaint.setAntiAlias(true);
mTitlePaint.setTextAlign(Paint.Align.CENTER);
mTitlePaint.setColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//將坐標(biāo)原點(diǎn)平移到(mViewWidth / 2, mViewHeight / 2)位置處
canvas.translate(mViewWidth / 2, mViewHeight / 2);
//畫文字和折線以及扇形
drawPieAndLineAndText(canvas);
//畫標(biāo)題
drawTitle(canvas);
}
說明:將坐標(biāo)系平移到view中心 便于之后的弧長的中點(diǎn)坐標(biāo)的計算,下面正式進(jìn)入核心代碼
6石蔗、畫扇形
private void drawPie(Canvas canvas, int i) {
//畫扇形
if (i == 0) {
mPiepath.moveTo(10, 10);
mPiepath.arcTo(new RectF(mRectF.left + 10, mRectF.top + 10,
mRectF.right + 10, mRectF.bottom + 10), startAngle, mPieAngles[i]);
} else {
mPiepath.moveTo(0, 0);
mPiepath.arcTo(mRectF, startAngle, mPieAngles[i]);
}
mPiePaint.setColor(mColors[i]);
canvas.drawPath(mPiepath, mPiePaint);
mPiepath.reset();
startAngle = (int) (startAngle + mPieAngles[i] + angleDash);
}
這里我需要解釋一下罕邀,圖示效果,有一個弧度最大的扇形有一個偏移效果养距,我這邊是將path的起點(diǎn)坐標(biāo)從原來的(0诉探,0)變?yōu)椋?0,10)棍厌,將該扇形的矩形輪廓坐標(biāo)也對應(yīng)的偏移了10個像素肾胯,即可達(dá)到偏移效果
這里的startAngle是每個扇形的起始繪制的角度,每繪制一個扇形耘纱,下一個扇形的起始繪制角度就是 上一個扇形的角度與上一個扇形的起始的角度以及扇形之間的間隔角度和敬肚。
7、畫折線和文字 這里只貼出核心代碼解釋
float xStart = (float) (mRadius * Math.cos(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
float yStart = (float) (mRadius * Math.sin(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
float xStop = (float) ((mRadius + lineFirstLength) * Math.cos(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
float yStop = (float) ((mRadius + lineFirstLength) * Math.sin(Math.toRadians(startAngle - angleDash - mPieAngles[i] / 2)));
canvas.drawLine(xStart, yStart, xStop, yStop, mLinePaint);
if (xStop > xStart) {
canvas.drawLine(xStop, yStop, xStop + lineSecondLength, yStop, mLinePaint);
mTextPaint.setTextAlign(Paint.Align.LEFT);
canvas.drawText(texts[i], xStop + lineSecondLength + 10, yStop, mTextPaint);
} else {
canvas.drawLine(xStop, yStop, xStop - lineSecondLength, yStop, mLinePaint);
mTextPaint.setTextAlign(Paint.Align.RIGHT);
canvas.drawText(texts[i], xStop - lineSecondLength - 10, yStop, mTextPaint);
}
根據(jù)三角函數(shù)很容易計算出束析,每個扇形的弧長中點(diǎn)坐標(biāo) 即上面的xStart,yStart 然后根據(jù)同樣的算法艳馒,將半徑延長即可計算出第一段線段的終點(diǎn)坐標(biāo) 即 xStop,yStop,根據(jù)這兩個點(diǎn)即可畫出第一段線段。
第二段線段就需要做一些判斷了 根據(jù)第一段線段的走向弄慰,判斷出第二段線段的走勢第美,如何第一段是趨于向右的,那么第二段線段水平向右陆爽,反之向左什往。
畫完兩段線段之后再末尾 繪制對應(yīng)的文字 (這里根據(jù)畫筆paint的一個屬性即可確定文字是從左向右還是從右向左)
mTextPaint.setTextAlign(Paint.Align.LEFT);
到此,簡單的餅圖就繪制完成了慌闭,其中主要弧長中點(diǎn)坐標(biāo)的計算恶守,以及三角函數(shù)和android的drawXXX()方法的結(jié)合使用
源碼github地址:https://github.com/weiranqiaobo/pieDemo/tree/master