1. 程式人生 > >Android Canvas練習(6)餅圖(Pie Chart)百分比標註位置計算技巧

Android Canvas練習(6)餅圖(Pie Chart)百分比標註位置計算技巧

     今天終於解決了困擾整整一週的,一個令人抓狂的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練習(5)自已繪面積圖(Area Chart)

MAIL: [email protected]

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

相關推薦

Android Canvas練習(6)(Pie Chart)百分比標註位置計算技巧

     今天終於解決了困擾整整一週的,一個令人抓狂的HPUX程式碼問題。可以在這半夜神清氣爽的說下昨天晚上推匯出來的一個小技巧, 如何在一張餅圖(Pie Chart)上每個扇形的中心位置標記出百分比。 我之前寫了一篇怎麼自繪餅圖的文章,但百分比都是另外在一個 地方顯示的,

Canvas百分比標註位置計算技巧

     public class MyViewOne extends View {private int ScrWidth, ScrHeight;private float rx, ry;public MyViewOne(Context context) {super(context);// TODO Au

Android Canvas練習(9)自已繪分割突出效果的(Pie Chart)

   這裡畫了個餅圖的變種,具有分割突出效果的餅圖(Pie Chart),就是個切蛋糕效果的餅圖,畫這種圖,其技巧就在於圓心的偏移。 在圓心偏移,半徑不變的基礎上,效果就出來了。     上圖:               怎麼樣,效果還是有模有樣的吧。      程式碼很

Android Canvas練習(2)自已繪(Pie Chart)

    上文弄了個繪製報表的,有了報表,當然想一併也繪個餅圖,柱形圖之類的玩玩,看看了API,覺得應當很簡單,餅圖實現了下, 實現程式碼確實也很簡單,Android的這些函式封裝的確實好用。    效果圖如下:               不過實現過程還是比較曲折的,首

c#通過.net自帶的chart控制元件繪製pie chart

原文地址:http://www.veryhuo.com/a/view/52954.html 需要實現的目標是:   1.將資料繫結到pie的後臺資料中,自動生成餅圖。   2.生成的餅圖有詳細文字的說明。   具體的實現步驟:   >>前臺介面的設

Android Canvas練習(7)繪製歐冠八強防守&控制率資料對比

    在網易資料酷的<<足壇"斧頭幫"!瘋狂馬競打爆巴薩>>中看到一幅圖,非常有特色,因為最近用Canvas繪了不少圖表,就想用程式碼把這幅圖也繪出來。 基本也繪出來了,效果圖如下:           繪製這張圖,api用得到不多,但恰好把我前面

aNDROID仿支付寶效果

餅圖 aid hao123 .com andro smart and lis oid sMaRT%E6%BC%82%E4%BA%AE%E6%97%B6%E9%92%9F%E2%80%94%E2%80%94%E6%BA%90%E4%BB%A3%E7%A0%81 http:/

ECharts圖表常用屬性參考 -- Pie

option = { color: ['#5697d0', '#56cfd0', '#56d078', '#a9d056', '#d0b856', '#d07b56', '#a656d0', '#d056a1', '#d05656', '#5673d0'],

RDLC-Chart上顯示百分比

RDLC在餅圖上顯示百分比不像水晶報表那樣便捷,需要自己定義相應的公式。但這種方式也使得RDLC更為靈活。 在RDLC的餅圖上顯赫百分比可參考如下公式: =FormatPercent(Count(Fields!ProductId.Value)/Count(Fields!ProductId.V

Echarts圖表庫。 pie 圖表元件的使用。元件API使用規則--DOME

var myChart = echarts.init(document.getElementById('main')); var option = { baseOption:{ //調色盤顏色列表 //

JAVA報表之JasperReport+iReport5.6 和3D的實現(五)

餅圖資料只需要兩個欄位,一個是分類,一個是值,多用於資料類別少的場合。例如:建好一個新的模板後,在chart1(模板)中新增一個數據源ChartDataset,如下圖所示:在報表中的任意位置插入你想要的餅圖,如圖所示:匯入我們剛剛新增的資料來源,如圖所示:完成後的效果圖及預覽

R語言的(pie)學習

 剛開始學習R語言, 第一篇的筆記, 長久以來作為一個數據倉庫工程師,整天活在資料的礦坑中, 卻一直沒有涉足資料探勘,實屬慚愧。 為培養學習的興趣和寫學習筆記的良好愛好, 故選擇最最簡單的餅圖作為分析物件。 第一感覺, R最為統計分析, 資料探勘的工具, 具有強大的分析能力

echarts如何修改百分比位數

今天工作中要求echarts生成的餅圖需要顯示百分比並保留一位小數,在echarts的series.lable.formatter中可以設定該屬性。值得注意的是 自帶的{d}%預設保留兩位小數,如需修改小數位數,需要自己寫一個函式。<script type="text/

echarts 引導線周圍文字位置的改變

app.title = '巢狀環形圖'; option = { tooltip: { trigger: 'item', formatter: "{a} <br/>{b}: {c} ({d}%)" }, leg

Android 使用Canvas繪製

效果: 嗯,一個很簡單的餅圖繪製。 用法 可以在xml檔案中配置,也可以直接new一個例項出來。 <com.paoword.oa.view.SectorGraphView android:id="@+id/s

Android canvas繪制柱形統計

ext.get hit 選擇 etc new 工廠模式 imp 設計模式 layout 如今非常多應用都須要一些統計圖。眼下第三方的統計圖也有非常多。可是在自己看來僅僅要不是特別耽誤時間還是選擇用canvas自己繪制比較合理。依賴於第三方的繪制在需求上也

【Echarts】Pie legend selected 默認是否選中的處理

緩存 select sele echart .cn png str nbsp 2-2 網上找了好多例子 還是自己總結下 legend: { orient: ‘horizontal‘, // ‘vertical‘

Android Things 專題6 完整的栗子:運用TensorFlow解析

out 好玩的 mod tex 解答 debug 碼流 寫文件 應用 文| 谷歌開發技術專家 (GDE) 王玉成 (York Wang) 前面絮叨了這麽多,好像還沒

第166天:canvas繪制動畫

padding new gree component adding 文本 add function 填充 canvas繪制餅狀圖動畫 1、HTML 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head

小程序使用Canvas

tar lin canvas style nload raw 代碼 程序 function 先上效果圖 -------------------------------------------------------------wxml代碼開始---------------