當前位置:
首頁 > 知識 > WPF製作帶明細的環形圖表

WPF製作帶明細的環形圖表

效果

明細用Popup實現的,錄gif時,Popup顯示不出來,不知道為什麼,所以靜態圖湊合看吧

WPF製作帶明細的環形圖表

大體思路

圖表使用Arc+Popup實現

圖表分為兩部分,一是環形部分,一是標註的明細部分.

環形部分使用Arc圖形表示.需要注意這個Arc是Blend里的圖形.用Blend建項目的話可以直接用,使用VS建項目需要添加引用 Microsoft.Expression.Drawing 在引用管理器=>程序集=>擴展 下(前提是已經安裝了Blend)

明細部分使用Popup控制項,IsOpen屬性綁定到Arc的IsMouseOver,也就是滑鼠進入圓弧的時候,Popup就打開顯示.

Popup內部一個橢圓控制項當作背景,一個文字顯示,一個折線虛線化當作指針

然後就是把Popup定位到對應圓弧合適的位置去顯示(這裡取的是圓弧的中間)

比較抱歉的是樣式比較醜陋,忽略吧,重點看定位.

圓弧部分

Arc有兩個重要的屬性:StartAngle起始角度和EndAngle終結角度.這兩個屬性決定了圓弧占所在圓環的比例.

每一個數據項就對應一個圓弧,把所有圓弧都放到一個容器里,首尾相連

數據項的總和為100,那麼所有圓弧也就組成一個完整的圓環.

Popup明細部分

明細部分分為四種,見圖

WPF製作帶明細的環形圖表

橢圓

從圖可知,作為背景的橢圓分為兩種情況,小於180度,橢圓靠容器的右邊對齊,大於180度,靠容器的左邊對齊

也就是代碼的這部分:


Ellipse ell = new Ellipse() { Fill = brush };

//中間點角度小於180 明細靠右顯示 否則靠左顯示

Grid detailGrid = new Grid() { Width = _popupHeight, HorizontalAlignment = HorizontalAlignment.Right };

if (middleAngle > 180)

{

detailGrid.HorizontalAlignment = HorizontalAlignment.Left;

}

折線


折線是分為四種,每一個角度區間都對應一種

private Polyline GetPopupPolyline(double middleAngle)

{

Polyline pLine = new Polyline() { Stroke = new SolidColorBrush(Color.FromRgb(0, 0, 0)), StrokeDashArray = new DoubleCollection(new double[] { 5, 2 }) };

double x1 = 0, y1 = 0;

double x2 = 0, y2 = 0;

double x3 = 0, y3 = 0;

if (middleAngle > 0 && middleAngle <= 90)

{

x1 = 0; y1 = _popupHeight;

x2 = _popupWidth / 2; y2 = _popupHeight;

x3 = _popupWidth * 3 / 4; y3 = _popupHeight / 2;

}

if (middleAngle > 90 && middleAngle <= 180)

{

x1 = 0; y1 = 0;

x2 = _popupWidth / 2; y2 = 0;

x3 = _popupWidth * 3 / 4; y3 = _popupHeight / 2;

}

if (middleAngle > 180 && middleAngle <= 270)

{

x1 = _popupWidth; y1 = 0;

x2 = _popupWidth / 2; y2 = 0;

x3 = _popupWidth / 4; y3 = _popupHeight / 2;

}

if (middleAngle > 270 && middleAngle <= 360)

{

x1 = _popupWidth; y1 = _popupHeight;

x2 = _popupWidth / 2; y2 = _popupHeight;

x3 = _popupWidth / 4; y3 = _popupHeight / 2;

}

pLine.Points.Add(new Point(x1, y1));

pLine.Points.Add(new Point(x2, y2));

pLine.Points.Add(new Point(x3, y3));

return pLine;

}

Popup的定位

首先以0-90度為例,說明一些基本的東西,見圖

WPF製作帶明細的環形圖表

首先Popup默認的位置,都是在它容器的左下方的,Popup的左上角和容器的左下角重合.

現在要做的是Popup標記為紅點的位置,和圓環上標記為紅點的位置重合.

先來回顧一下小時候學過的公式:

1.直角三角形 a=r*sinA

2.勾股定理 c^2=a^2+b^2 b=Sqrt(c^2-a^2)

上圖的直角三角形,角A的對邊為a,臨邊為b,斜邊為c.顯然c邊於圓的半徑r相等.注意:因為圓弧是有厚度的,所以取r的時候要減去二分之一的圓弧厚度.

角A是可以通過90度減去圓弧的對應的角度求出來的,也就是sinA的值已知了,那麼就可以求出a和b的長度,然後就可以去移動Popup了

一.0-90度

X軸:1.向右移動二分之一個容器的width 2.向右移動一個b的距離

WPF製作帶明細的環形圖表

Y軸:1.向上移動二分之一個容器的height 2.向上移動一個Popup的height 3.向上移動一個a的距離

WPF製作帶明細的環形圖表

二.90-180度

X軸:1.向右移動二分之一個容器的width 2.向右移動一個a的距離

WPF製作帶明細的環形圖表

Y軸:1.上移二分之一個圓弧的Thickness,以保證標記的起點在圓弧的中央 2.上移一個(r-b)的距離

WPF製作帶明細的環形圖表

三.180-270度

X軸:1.向左移動一個b的距離

WPF製作帶明細的環形圖表

Y軸:1.上移二分之一個圓弧的Thickness,以保證標記的起點在圓弧的中央 2.上移一個(r-a)的距離

WPF製作帶明細的環形圖表

四.270-360度

X軸:1.向左移動一個a的距離

WPF製作帶明細的環形圖表

Y軸:1.向上移動二分之一個容器的height 2.向上移動一個Popup的height 3.向上移動一個b的距離

WPF製作帶明細的環形圖表

代碼部分


private Popup GetPopup(double middleAngle)

{

/*

* 生成popup

* 設置popup的offset 讓標記線的起點 對應到圓弧的中間點

*/

Popup popup = new Popup() { Width = _popupWidth, Height = _popupHeight, AllowsTransparency = true, IsHitTestVisible = false };

//直角三角形 a=r*sinA 勾股定理 c^2=a^2+b^2 b=Sqrt(c^2-a^2)

double r = _chartWidth / 2 - _arcThickness / 2;

double offsetX = 0, offsetY = 0;

if (middleAngle > 0 && middleAngle <= 90)

{

double sinA = Math.Sin(Math.PI * (90 - middleAngle) / 180);

double a = r * sinA;

double c = r;

double b = Math.Sqrt(c * c - a * a);

offsetX = _chartWidth / 2 + b;

offsetY = -(_chartWidth / 2 + _popupHeight + a);

}

if (middleAngle > 90 && middleAngle <= 180)

{

double sinA = Math.Sin(Math.PI * (180 - middleAngle) / 180);

double a = r * sinA;

double c = r;

double b = Math.Sqrt(c * c - a * a);

offsetX = _chartWidth / 2 + a;

offsetY = -(_arcThickness / 2 + (r - b));

}

if (middleAngle > 180 && middleAngle <= 270)

{

double sinA = Math.Sin(Math.PI * (270 - middleAngle) / 180);

double a = r * sinA;

double c = r;

double b = Math.Sqrt(c * c - a * a);

offsetX = -b;

offsetY = -(_arcThickness / 2 + (r - a));

}

if (middleAngle > 270 && middleAngle <= 360)

{

double sinA = Math.Sin(Math.PI * (360 - middleAngle) / 180);

double a = r * sinA;

double c = r;

double b = Math.Sqrt(c * c - a * a);

offsetX = -a;

offsetY = -(_chartWidth / 2 + _popupHeight + b);

}

popup.HorizontalOffset = offsetX;

popup.VerticalOffset = offsetY;

return popup;

}

主要的,就是這些了。

(本文轉載自博客園)



50天安卓課,自己解決住宿問題即可免費學習!

http://www.ujiuye.com/xydt/2017/13042.html?wt.bd=qzb36000j

想就業就就業,優就業就業扶持計劃,拿到滿意的工作offer就是這麼簡單

http://www.ujiuye.com/zt/jyfc/?wt.bd=qzb36000j

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

App 組件化/模塊化之路——如何封裝網路請求框架
vue.js實現內部自定義指令和全局自定義指令——directive
用dtrace 跟蹤 mysql-community-server-5.6.20
linux 常用 掌握要點(一)
linux 常用 掌握要點(二)

TAG:IT優就業 |

您可能感興趣

微軟宣布開源 WPF、WinForms和WinUI
微軟宣布WPF、Windows Forms和WinUI這3個流行框架正式開源
微軟開源 Windows UX 框架:WPF、WinUI、Windows Forms
WPF知識點分享