角度或旋转角度绘制弧线"/>
WPF根据起始角度或旋转角度绘制弧线
实现指定圆心与起止角度;或指定圆心、起点与旋转角度,绘制弧线。
参考文章:How to draw arc with radius and start and stop angle-stackoverflow
主要在原回答基础上增加了相对起点的旋转参数,更改了部分显示逻辑。
xaml插入方式参考原文
修改后的控件代码如下:
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;namespace Controls
{public class Arc : Shape{public Point Center{get => (Point)GetValue(CenterProperty);set => SetValue(CenterProperty, value);}// Using a DependencyProperty as the backing store for Center. This enables animation, styling, binding, etc...public static readonly DependencyProperty CenterProperty =DependencyProperty.Register(nameof(Center), typeof(Point), typeof(Arc),new FrameworkPropertyMetadata(new Point(), FrameworkPropertyMetadataOptions.AffectsRender));public double StartAngle{get => (double)GetValue(StartAngleProperty);set => SetValue(StartAngleProperty, value);}// Using a DependencyProperty as the backing store for StartAngle. This enables animation, styling, binding, etc...public static readonly DependencyProperty StartAngleProperty =DependencyProperty.Register(nameof(StartAngle), typeof(double), typeof(Arc),new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));public double EndAngle{get => (double)GetValue(EndAngleProperty);set => SetValue(EndAngleProperty, value);}// Using a DependencyProperty as the backing store for EndAngle. This enables animation, styling, binding, etc...public static readonly DependencyProperty EndAngleProperty =DependencyProperty.Register(nameof(EndAngle), typeof(double), typeof(Arc),new FrameworkPropertyMetadata(90.0, FrameworkPropertyMetadataOptions.AffectsRender));public double RotateAngle{get => (double)GetValue(RotateAngleProperty);set => SetValue(RotateAngleProperty, value);}// Using a DependencyProperty as the backing store for EndAngle. This enables animation, styling, binding, etc...public static readonly DependencyProperty RotateAngleProperty =DependencyProperty.Register(nameof(RotateAngle), typeof(double), typeof(Arc),new FrameworkPropertyMetadata(90.0, FrameworkPropertyMetadataOptions.AffectsRender));public double Radius{get => (double)GetValue(RadiusProperty);set => SetValue(RadiusProperty, value);}// Using a DependencyProperty as the backing store for Radius. This enables animation, styling, binding, etc...public static readonly DependencyProperty RadiusProperty =DependencyProperty.Register(nameof(Radius), typeof(double), typeof(Arc),new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsRender));public bool Clockwise{get => (bool)GetValue(ClockwiseProperty);set => SetValue(ClockwiseProperty, value);}// Using a DependencyProperty as the backing store for SmallAngle. This enables animation, styling, binding, etc...public static readonly DependencyProperty ClockwiseProperty =DependencyProperty.Register(nameof(Clockwise), typeof(bool), typeof(Arc),new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));static Arc() => DefaultStyleKeyProperty.OverrideMetadata(typeof(Arc), new FrameworkPropertyMetadata(typeof(Arc)));protected override Geometry DefiningGeometry{get{if (RotateAngle == 90.0 && EndAngle == 90.0){//若均为初始值,选择rotate优先EndAngle = Clockwise? StartAngle + (double)RotateAngle : StartAngle - (double)RotateAngle;}//若有旋转角度,则用旋转角度计算endif (RotateAngle != 90.0){EndAngle = Clockwise ? StartAngle + (double)RotateAngle : StartAngle - (double)RotateAngle;}if(Math.Abs(StartAngle-EndAngle)>=360){//差值大于360度,画圆return new EllipseGeometry(Center,Radius,Radius);}//起止都约束到360度内long temp0 = Convert.ToInt64(StartAngle);long temp1 = Convert.ToInt64(EndAngle);StartAngle = StartAngle - temp0 + temp0 % 360;EndAngle = EndAngle - temp1 + temp1 % 360;//不需特意实现//if (StartAngle == EndAngle)//{//起止点相同,画点。//}//起止都修正为正值double a0 = StartAngle < 0 ? StartAngle + 360 : StartAngle;double a1 = EndAngle < 0 ? EndAngle + 360 : EndAngle;//起止都转为弧度a0 = a0 / 180.0 * Math.PI;a1 = a1 / 180.0 * Math.PI;if (a1 < a0){a1 += Math.PI * 2;//不影响sin与cos值}//差大于PI时,顺时针为优弧;差小于PI时,顺时针为劣弧。//默认为顺时针优弧。SweepDirection d;bool large;//是否是优弧//判断是优弧还是劣弧if (Clockwise){d = SweepDirection.Clockwise;large = (Math.Abs(a1 - a0) > Math.PI);}else{d = SweepDirection.Counterclockwise;large = (Math.Abs(a1 - a0) < Math.PI);}Point p0 = Center + new Vector(Math.Cos(a0), Math.Sin(a0)) * Radius;Point p1 = Center + new Vector(Math.Cos(a1), Math.Sin(a1)) * Radius;List<PathSegment> segments = new List<PathSegment>{//使用起止点绘图——设置终点与半径new ArcSegment(p1, new Size(Radius, Radius), 0.0, large, d, true)};List<PathFigure> figures = new List<PathFigure>{//使用起止点绘图——设置起点new PathFigure(p0, segments, true){IsClosed = false}};return new PathGeometry(figures, FillRule.EvenOdd, null);}}}
}
更多推荐
WPF根据起始角度或旋转角度绘制弧线
发布评论