WPF椭圆弧形弧线控件
属性:
StartAngle: 起点角度;
EndAngle: 终点角度;
IsStartCenter:是否从圆心开始画线;
IsClosed:是否封闭;
使用方式:
<control:Arc Width="100" Height="100" StartAngle="110" EndAngle="-45" Stroke="Blue" StrokeThickness="5" IsStartCenter="True" IsClosed="True" Fill="Orange"/>
源码:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApp2.Controls
{
public class Arc : Shape
{
Size _size = Size.Empty;
protected override Geometry DefiningGeometry {
get
{
if(_size == Size.Empty)
return Geometry.Empty;
return GetGeometry();
}
}
Geometry GetGeometry()
{
double angle = this.EndAngle - StartAngle;
if (angle == 0) return Geometry.Empty;
if (Math.Abs(angle) >= 360d) return new EllipseGeometry(new Point(_size.Width / 2, _size.Height / 2), RadiusXNoThickness, RadiusYNoThickness);
var path = new PathGeometry();
var figure = new PathFigure();
path.Figures.Add(figure);
var arc = new ArcSegment();
figure.Segments.Add(arc);
arc.IsLargeArc = Math.Abs(EndAngle) > 180 || Math.Abs(EndAngle - StartAngle) > 180;
arc.SweepDirection = EndAngle > StartAngle ? SweepDirection.Counterclockwise : SweepDirection.Clockwise;
arc.Size = new Size(RadiusXNoThickness, RadiusYNoThickness);
arc.Point = GetPoint(EndAngle);
figure.StartPoint = GetPoint(StartAngle);
if (IsStartCenter)
{
figure.Segments.Insert(0, new LineSegment(figure.StartPoint, true));
figure.StartPoint = new Point(_size.Width / 2, _size.Height / 2);
}
if(IsClosed)
figure.IsClosed = true;
return path;
}
Point GetPoint(double angle)
{
double d = angle / 180 * Math.PI;
double a = RadiusXNoThickness, b = RadiusYNoThickness;
double t = a * b / Math.Sqrt(Math.Pow(a * Math.Sin(d), 2) + Math.Pow(b * Math.Cos(d), 2));
double x = t * Math.Cos(d);
double y = t * Math.Sin(d);
var endPoint = new Point(x + a + (StrokeThickness / 2), b - y + (StrokeThickness / 2));
return endPoint;
}
protected override Size MeasureOverride(Size constraint)
{
_size = constraint;
return base.MeasureOverride(constraint);
}
protected override Size ArrangeOverride(Size finalSize)
{
_size = finalSize;
return base.ArrangeOverride(finalSize);
}
double RadiusXNoThickness => Math.Max(_size.Width / 2 - StrokeThickness / 2, 0);
double RadiusYNoThickness => Math.Max(_size.Height / 2 - StrokeThickness / 2, 0);
/// <summary>
/// 起始点角度
/// </summary>
public double StartAngle
{
get { return (double)GetValue(StartAngleProperty); }
set { SetValue(StartAngleProperty, value); }
}
public static readonly DependencyProperty StartAngleProperty =
DependencyProperty.Register("StartAngle", typeof(double), typeof(Arc), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// 终点角度
/// </summary>
public double EndAngle
{
get { return (double)GetValue(EndAngleProperty); }
set { SetValue(EndAngleProperty, value); }
}
public static readonly DependencyProperty EndAngleProperty =
DependencyProperty.Register("EndAngle", typeof(double), typeof(Arc), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// 是否从椭圆中心开始画线
/// </summary>
public bool IsStartCenter
{
get { return (bool)GetValue(IsStartCenterProperty); }
set { SetValue(IsStartCenterProperty, value); }
}
public static readonly DependencyProperty IsStartCenterProperty =
DependencyProperty.Register("IsStartCenter", typeof(bool), typeof(Arc), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender));
/// <summary>
/// 是否封闭图形
/// </summary>
public bool IsClosed
{
get { return (bool)GetValue(IsClosedProperty); }
set { SetValue(IsClosedProperty, value); }
}
public static readonly DependencyProperty IsClosedProperty =
DependencyProperty.Register("IsClosed", typeof(bool), typeof(Arc), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsRender));
}
}