How to draw arc with radius and start and stop angle(如何用半径和开始和停止角度绘制圆弧)
问题描述
如果我的 Canvas 元素的 DataContext 中有以下四个属性
If I have the following four properties in my DataContext of my Canvas element
Point Center
double Radius
double StartAngle
double EndAngle
我可以在没有任何额外代码的情况下绘制圆弧吗?
can I draw an arc without any extra code behind?
推荐答案
事实证明,提供自定义组件是最好的解决方案.我在我的代码中这样使用它
Providing a custom component turned out to be the best solution. I use it like this in my code
<Controls:Arc Center="{Binding Path=PreviousMousePositionPixels}"
Stroke="White"
StrokeDashArray="4 4"
SnapsToDevicePixels="True"
StartAngle="0"
EndAngle="{Binding Path=DeltaAngle}"
SmallAngle="True"
Radius="40" />
SmallAngle
当true
将渲染点之间的小角度,而与StartAngle
和EndAngle
的顺序无关.当 SmallAngle
为 false
时,弧线逆时针渲染.
SmallAngle
when true
will render the small angle between the points irrespective of order of StartAngle
and EndAngle
. When SmallAngle
is false
the arc is rendered counter clockwise.
实现是
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
public sealed 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(Math.PI / 2.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 SmallAngle
{
get => (bool)GetValue(SmallAngleProperty);
set => SetValue(SmallAngleProperty, value);
}
// Using a DependencyProperty as the backing store for SmallAngle. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SmallAngleProperty =
DependencyProperty.Register(nameof(SmallAngle), typeof(bool), typeof(Arc),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender));
static Arc() => DefaultStyleKeyProperty.OverrideMetadata(typeof(Arc), new FrameworkPropertyMetadata(typeof(Arc)));
protected override Geometry DefiningGeometry
{
get
{
double a0 = StartAngle < 0 ? StartAngle + 2 * Math.PI : StartAngle;
double a1 = EndAngle < 0 ? EndAngle + 2 * Math.PI : EndAngle;
if (a1 < a0)
a1 += Math.PI * 2;
SweepDirection d = SweepDirection.Counterclockwise;
bool large;
if (SmallAngle)
{
large = false;
d = (a1 - a0) > Math.PI ? SweepDirection.Counterclockwise : SweepDirection.Clockwise;
}
else
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);
}
}
}
这篇关于如何用半径和开始和停止角度绘制圆弧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何用半径和开始和停止角度绘制圆弧
- Windows 喜欢在 LINUX 中使用 MONO 进行服务开发? 2022-01-01
- 在 LINQ to SQL 中使用 contains() 2022-01-01
- Azure Active Directory 与 MVC,客户端和资源标识同一 2022-01-01
- 为什么 C# 中的堆栈大小正好是 1 MB? 2022-01-01
- 带问号的 nvarchar 列结果 2022-01-01
- 是否可以在 .Net 3.5 中进行通用控件? 2022-01-01
- 在 C# 中异步处理项目队列 2022-01-01
- 使用 rss + c# 2022-01-01
- CanBeNull和ReSharper-将其用于异步任务? 2022-01-01
- C# 通过连接字符串检索正确的 DbConnection 对象 2022-01-01