[WPF] 继承Shape实现弧形、扇形控件

属性:

RadianStart:开始弧度,默认值-90,即从最上面开始顺时针画。

Radian:弧度,默认值0。

IsSector:是否扇形,默认值False,默认是弧形。

IsAutoAnimate:是否自动使用动画,默认值False,若为True,则RadianStart和Radian的值变化时,自动使用动画。

 

效果展示:

 

 

 

核心代码:

private Geometry DrawGeometry()
{
    // 圆心
    var cx = RenderSize.Width / 2;
    var cy = RenderSize.Height / 2;

    // 若控件大小为0,或弧度为0,则不绘制
    if (cx == 0 || cy == 0 || Radian == 0)
        return Geometry.Empty;

    var r = Math.Min(cx, cy) - StrokeThickness / 2;  // 半径
    var d = 2 * r; // 直径

    // 若弧度恰好为一个整圆,则绘制两个半圆
    if (Radian % 360 == 0)
    {
        // 计算开始、结束弧度坐标点
        var s = CoordMap(cx, cy, r, 0);
        var e = CoordMap(cx, cy, r, 180);

        var desc = $"M0 0 M{d} {d} M{s.X} {s.Y} A{r} {r} 0 0 1 {e.X} {e.Y} A{r} {r} 0 0 1 {s.X} {s.Y}";
        var geometry = Geometry.Parse(desc);
        geometry.Freeze();

        return geometry;
    }
    else
    {
        // 计算开始、结束弧度坐标点
        var s = CoordMap(cx, cy, r, RadianStart);
        var e = CoordMap(cx, cy, r, RadianStart + Radian);

        // 判断是否为大圆
        var lenghty = Radian % 360 > 180 ? 1 : 0;

        string desc = null;

        // 判断是否扇形
        if (IsSector)
            desc = $"M0 0 M{d} {d} M{cx} {cy} L{s.X} {s.Y} A{r} {r} 0 {lenghty} 1 {e.X} {e.Y} Z";
        else
            desc = $"M0 0 M{d} {d} M{s.X} {s.Y} A{r} {r} 0 {lenghty} 1 {e.X} {e.Y}";

        var geometry = Geometry.Parse(desc);
        geometry.Freeze();

        return geometry;
    }
}
/// <summary>
/// 极坐标转换
/// </summary>
/// <param name="x">圆心x</param>
/// <param name="y">圆心y</param>
/// <param name="r">半径</param>
/// <param name="a">弧度</param>
/// <returns></returns>
private Point CoordMap(Double x, Double y, Double r, Double a)
{
    var ta = (360 - a) * Math.PI / 180;
    var tx = r * Math.Cos(ta); // 角度邻边
    var ty = r * Math.Sin(ta); // 角度的对边
    return new Point(x + tx, y - ty);
}

 

更多详情,请查看PP.WPF控件库。

posted @ 2021-07-14 10:10  孤独成派  阅读(1499)  评论(4编辑  收藏  举报