Android Canvas练习(6)饼图(Pie Chart)百分比标注位置计算技巧

来源:互联网 发布:音响软件 编辑:程序博客网 时间:2024/05/17 02:54

     今天终于解决了困扰整整一周的,一个令人抓狂的HPUX代码问题。可以在这半夜神清气爽的说下昨天晚上推导出来的一个小技巧,

如何在一张饼图(Pie Chart)上每个扇形的中心位置标记出百分比。 我之前写了一篇怎么自绘饼图的文章,但百分比都是另外在一个

地方显示的,不是不想显示在每个扇形图中,是当时还不会。昨晚花了点时间,终于找出了计算方法。

   先上张最终效果图:

     

   经历过的思路历程也很有意思,看看下面几张图,可以很清楚的显示说明计算经过是怎么样子的:


          

   靠左的这张图,说明了我需要解决的问题所在,即目前已知圆心坐标,半径,及角度,如何得到扇形的中心点这是个数学问题,而数学我基本都还给老师了,怀着

惭愧的心情baidu了一翻后,终于找到了依角度可求出图上坐标的计算公式,不知其所以然(继续惭愧中.....)的套了上去,得到了中间这张图。

   中间这张图可以很清楚的得到每个角度,最末边交叉点位置。 但这个位置并不是我们想要的,我们想的是中间这个点的坐标。如果是这样,而中点的坐标是多少呢,

好像没啥现成的公式,只好灵活变化一下,还是套用这公式,把角度减少一半不得就行了。这样就得到了最右边这张图。

   最右边这张图已经很接近最终效果了,实际上很多饼图得到这个坐标就够了,直接画一条线延伸出去,再标注百分比就可以了,这种情况适合于角度太小的情况。

但我举的例子中角度都偏大,可以直接标注百分比到图中,怎么做? 按前面取角度的思路想,事情就简单了,即然现在是在边上,那把半径缩小一圈按这个方法计算不就行了,哈哈。 终于得到了想要的效果。

    

  附上主程序代码:     

package com.xcl.canvas05;/** * Canvas练习  *   给饼图标上百分比,能计算出饼图标注的位置 *   * author:xiongchuanliang * date:2014-4-10 */import java.text.DecimalFormat;import com.xcl.chart.XChartCalc;import android.os.Bundle;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Path;import android.graphics.Path.Direction;import android.graphics.RectF;import android.util.DisplayMetrics;import android.view.Menu;import android.view.View;@SuppressLint("NewApi")public class MainActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);     //   setContentView(R.layout.activity_main);        this.setTitle("给饼图标上百分比");        setContentView(new PanelPieChartLabel(this));    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.main, menu);        return true;    }            class PanelPieChartLabel extends View {        private int ScrWidth,ScrHeight;private float rx, ry;public PanelPieChartLabel(Context context) {super(context);// TODO Auto-generated constructor stub//解决4.1版本 以下canvas.drawTextOnPath()不显示问题this.setLayerType(View.LAYER_TYPE_SOFTWARE,null);//屏幕信息DisplayMetrics dm = getResources().getDisplayMetrics();ScrHeight = dm.heightPixels;ScrWidth = dm.widthPixels;}public void onDraw(Canvas canvas){//画布背景canvas.drawColor(Color.WHITE);//画笔初始化Paint PaintArc = new Paint();PaintArc.setColor(Color.RED);Paint PaintGree = new Paint();PaintGree.setColor(Color.GREEN);PaintGree.setStyle(Style.FILL);Paint PaintBlue = new Paint();PaintBlue.setColor(Color.BLUE);PaintBlue.setStyle(Style.STROKE);Paint PaintYellow = new Paint();PaintYellow.setColor(Color.YELLOW);PaintYellow.setStyle(Style.FILL);//抗锯齿PaintArc.setAntiAlias(true);PaintYellow.setAntiAlias(true);PaintGree.setAntiAlias(true);PaintBlue.setTextSize(12);float cirX = ScrWidth / 2;float cirY = ScrHeight / 3 ;float radius = ScrHeight / 5 ;//先画个圆确定下显示位置canvas.drawCircle(cirX,cirY,radius,PaintGree);float arcLeft = cirX - radius;float arcTop  = cirY - radius ;float arcRight = cirX + radius ;float arcBottom = cirY + radius ;RectF arcRF0 = new RectF(arcLeft ,arcTop,arcRight,arcBottom);//////////////////////////////////////////////////////////////饼图标题canvas.drawText("author:xiongchuanliang",60,ScrHeight - 270, PaintBlue);//位置计算类              XChartCalc xcalc = new XChartCalc();                        //实际用于计算的半径            float calcRadius = radius/2;//////////////////////////////////////////////////////////////初始角度 float pAngle1 = 130f; float pAngle2 = 40f; float pAngle3 = 360f - pAngle1 - pAngle2; //填充扇形canvas.drawArc(arcRF0, 0,pAngle1, true,PaintArc); //计算并在扇形中心标注上百分比    130%            xcalc.CalcArcEndPointXY(cirX, cirY, calcRadius, pAngle1/2);             canvas.drawText(Float.toString(pAngle1)+"%", xcalc.getPosX(),xcalc.getPosY(), PaintBlue);              //////////////////////////////////////////////////////////////                        ////////////////////////////////////////////////////////////                         //填充扇形            canvas.drawArc(arcRF0, pAngle1,pAngle2, true,PaintYellow);                        //计算并在扇形中心标注上百分比   40%            xcalc.CalcArcEndPointXY(cirX, cirY, calcRadius, pAngle1 + pAngle2/2);                        canvas.drawText(Float.toString(pAngle2)+"%", xcalc.getPosX(),xcalc.getPosY(), PaintBlue);                          ////////////////////////////////////////////////////////////              //计算并在扇形中心标注上百分比  190%            xcalc.CalcArcEndPointXY(cirX, cirY, calcRadius, pAngle1 + pAngle2 + pAngle3/2);                        canvas.drawText(Float.toString(pAngle3)+"%", xcalc.getPosX(),xcalc.getPosY(), PaintBlue);              ////////////////////////////////////////////////////////////  }    }    }

   附上计算位置的代码类:     

package com.xcl.chart;/** * Canvas练习  *   图形相关的计算类 *    * author:xiongchuanliang * date:2014-4-9 */public class XChartCalc {//Position位置private float posX = 0.0f;private float posY = 0.0f;public XChartCalc(){}//依圆心坐标,半径,扇形角度,计算出扇形终射线与圆弧交叉点的xy坐标public void CalcArcEndPointXY(float cirX, float cirY, float radius, float cirAngle){//将角度转换为弧度        float arcAngle = (float) (Math.PI * cirAngle / 180.0);        if (cirAngle < 90)        {            posX = cirX + (float)(Math.cos(arcAngle)) * radius;            posY = cirY + (float)(Math.sin(arcAngle)) * radius;        }        else if (cirAngle == 90)        {            posX = cirX;            posY = cirY + radius;        }        else if (cirAngle > 90 && cirAngle < 180)        {        arcAngle = (float) (Math.PI * (180 - cirAngle) / 180.0);            posX = cirX - (float)(Math.cos(arcAngle)) * radius;            posY = cirY + (float)(Math.sin(arcAngle)) * radius;        }        else if (cirAngle == 180)        {            posX = cirX - radius;            posY = cirY;        }        else if (cirAngle > 180 && cirAngle < 270)        {        arcAngle = (float) (Math.PI * (cirAngle - 180) / 180.0);            posX = cirX - (float)(Math.cos(arcAngle)) * radius;            posY = cirY - (float)(Math.sin(arcAngle)) * radius;        }        else if (cirAngle == 270)        {            posX = cirX;            posY = cirY - radius;        }        else        {        arcAngle = (float) (Math.PI * (360 - cirAngle) / 180.0);            posX = cirX + (float)(Math.cos(arcAngle)) * radius;            posY = cirY - (float)(Math.sin(arcAngle)) * radius;        }}    //////////////public float getPosX() {return posX;}public float getPosY() {return posY;}    //////////////}
   至此,我最近遇到的两个技术问题(一个被工作逼的,一个感兴趣的)都基本解决了,爽!

   

附其它链接:

   Android Canvas练习(1)画一张报表来玩   

   Android Canvas练习(2)自已绘饼图

   Android Canvas练习(3)自已绘柱形图

   Android Canvas练习(4)自已绘折线图

    Android Canvas练习(5)自已绘面积图(Area Chart)


MAIL: xcl_168@aliyun.com

BLOG: http://blog.csdn.net/xcl168


0 0
原创粉丝点击