本文经原作者授权以原创方式二次分享,欢迎转载、分享。 原文作者:普通的地球人 原文地址:https://www.cnblogs.com/tsliwei/p/7155616.html Github地址:https://github.com/WPFDevelopersOrg/WPFDevelopers.Charts
Arc+Popup
实现;Arc
图形表示.需要注意这个Arc
是Blend
里的图形.用Blend
建项- 目的话可以直接用,使用VS
建项目需要添加引用 Microsoft.Expression.Drawing
在引用管理器=>程序集=>扩展
下(前提是已经安装了Blend
);Popu
p控件,IsOpen
属性绑定到Arc
的IsMouseOver
,也就是鼠标进入圆弧的时候,Popu
p就打开显示;Popup
内部一个椭圆控件当作背景,一个文字显示,一个折线虚线化当作指针;Popup
定位到对应圆弧合适的位置去显示(这里取的是圆弧的中间);Arc
有两个重要的属性:StartAngle
起始角度和EndAngle
终结角度.这两个属性决定了圆弧占所在圆环的比例;100
,那么所有圆弧也就组成一个完整的圆环;明细部分分为四种,见图;
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;
}
0-90
度为例,说明一些基本的东西,见图;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
了;1)0-90
度
X轴
:
1、向右移动二分之一个容器的width
;
2、向右移动一个b
的距离;Y轴
:
1、向上移动二分之一个容器的height
;
2、向上移动一个Popup
的height
;
3、向上移动一个a
的距离;2)90-180
度
X轴
:
1、向右移动二分之一个容器的width
;
2、向右移动一个a
的距离;Y轴
:
1、上移二分之一个圆弧的Thickness
,以保证标记的起点在圆弧的中央;
2、上移一个(r-b)
的距离;3)180-270
度
X轴
:
1、向左移动一个b
的距离;Y轴
:
1、上移二分之一个圆弧的Thickness
,以保证标记的起点在圆弧的中央;
2、上移一个(r-a)
的距离;4)270-360
度
X轴
:
1、向左移动一个a的距离;Y轴
:
1、向上移动二分之一个容器的height
;
2、向上移动一个Popup
的height
;
3、向上移动一个b
的距离;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 = _chartSize / 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 = _chartSize / 2 + b;
offsetY = -(_chartSize / 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 = _chartSize / 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 = -_popupWidth + (r - b) + _arcThickness / 2;
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 = -_popupWidth + (r - a) + _arcThickness / 2;
offsetY = -(_chartSize / 2 + _popupHeight + b);
}
popup.HorizontalOffset = offsetX;
popup.VerticalOffset = offsetY;
return popup;
}
差不多主要的就是这些了; 到这; 画图有点累;
源码1[1]Gtihub[2]Gitee[3]
[1]源码: https://files.cnblogs.com/files/tsliwei/ArcChart.zip
[2]Gtihub: https://github.com/WPFDevelopersOrg/WPFDevelopers.Charts
[3]gitee: https://gitee.com/WPFDevelopersOrg/WPFDevelopers.Charts
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有