以下代码允许我用箭头画一条线:
public sealed class LineArrow : Shape
{
#region X1
public double X1
{
get { return (double)GetValue( X1Property ); }
set { SetValue( X1Property, value ); }
}
// Using a DependencyProperty as the backing store for X1. This enables animation, styling, binding, etc...
public static readonly DependencyProperty X1Property =
DependencyProperty.Register( "X1", typeof( double ), typeof( LineArrow ), new FrameworkPropertyMetadata( 0.0,
FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure ) );
#endregion
#region Y1
public double Y1
{
get { return (double)GetValue( Y1Property ); }
set { SetValue( Y1Property, value ); }
}
// Using a DependencyProperty as the backing store for Y1. This enables animation, styling, binding, etc...
public static readonly DependencyProperty Y1Property =
DependencyProperty.Register( "Y1", typeof( double ), typeof( LineArrow ), new FrameworkPropertyMetadata(
0.0, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure ) );
#endregion
protected override Geometry DefiningGeometry
{
get
{
var lineStart = new Point( X1, Y1 );
var lineEnd = new Point( this.ActualWidth, this.ActualHeight );
var lineAngle = Math.Atan2( this.ActualHeight, this.ActualWidth );
RotateTransform rotation = new RotateTransform() { Angle = lineAngle * 180 / Math.PI, CenterX = 0.5, CenterY = 0.5 };
TranslateTransform translate = new TranslateTransform( lineEnd.X, lineEnd.Y );
StreamGeometry streamGeometry = new StreamGeometry();
using( StreamGeometryContext geometryContext = streamGeometry.Open() )
{
geometryContext.BeginFigure( lineStart, true, true );
geometryContext.LineTo( lineEnd, true, true );
//left arrow
geometryContext.BeginFigure( lineStart, true, true );
geometryContext.PolyLineTo( new List<Point>()
{
rotation.Transform( new Point( 0, -15 ) ),
rotation.Transform( new Point( -15, 0 ) ),
rotation.Transform( new Point( 0, 15 ) )
}, true, true );
//right arrow
geometryContext.BeginFigure( lineEnd, true, true );
geometryContext.PolyLineTo( new List<Point>()
{
translate.Transform( rotation.Transform( new Point( 0, -15 ) ) ),
translate.Transform( rotation.Transform( new Point( 15,0 ) ) ),
translate.Transform( rotation.Transform( new Point( 0, 15 ) ))
}, true, true );
}
streamGeometry.Freeze();
return streamGeometry;
}
}
}
以下是它的表现:
如何在旋转时使箭头保持15x15的初始尺寸,特别是在接近180度或90度的角度时?
答案 0 :(得分:2)
让我们考虑几何背景。你有一个中心,你有一个箭头。当角度改变时,箭头的长度不应改变。我们刚才描述的形状是什么?是的,你是对的,它是圈。现在,圆圈的属性是什么?其中心是您用作稳定点的(X1,Y1)点,其半径是箭头的初始长度。基本上,您打算根据中心,半径和角度找到终点。
假设角度为alpha。在这种情况下,您要搜索的(X2,Y2)坐标为:
X2 = X1 +半径* cos(alpha)
Y2 = Y1 +半径* sin(alpha)
答案 1 :(得分:0)
您应该像X1
那样定义Y1
,X2
,Y2
和Line
属性。
然后绘图可以像下面所示完成,可能用另一个依赖属性的值替换箭头尺寸的常量。它首先绘制一条带箭头的水平线,其中矢量的长度连接起点和终点,然后适当地旋转它。
protected override Geometry DefiningGeometry
{
get
{
var vector = new Point(X2, Y2) - new Point(X1, Y1);
var angle = Vector.AngleBetween(new Vector(1, 0), vector);
var geometry = new StreamGeometry();
using (var sgc = geometry.Open())
{
// left arrow
sgc.BeginFigure(new Point(X1, Y1), true, true);
sgc.LineTo(new Point(X1 + 15, Y1 - 10), true, true);
sgc.LineTo(new Point(X1 + 15, Y1 + 10), true, true);
// right arrow
sgc.BeginFigure(new Point(X1 + vector.Length, Y1), true, true);
sgc.LineTo(new Point(X1 + vector.Length - 15, Y1 - 10), true, true);
sgc.LineTo(new Point(X1 + vector.Length - 15, Y1 + 10), true, true);
// line
sgc.BeginFigure(new Point(X1 + 15, Y1), false, false);
sgc.LineTo(new Point(X1 + vector.Length - 15, Y1), true, true);
}
geometry.Transform = new RotateTransform(angle, X1, Y1);
geometry.Freeze();
return geometry;
}
}