winforms 如何使用颜色渐变填充椭圆形状的圆形部分?

iih3973s  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(194)

我想做的是创造这个旋转圆锥体的视觉效果。
我以前使用过DirectX。

到目前为止,我已经尝试过:
即使我将厚度更改为50或更大,Arc仍未填充。

public partial class Form1 : Form
{
    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        var g = e.Graphics;
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        var center = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2);
        var innerR = 30;
        var thickness = 20;
        var startAngle = 0;
        var arcLength = 360;
        var outerR = innerR + thickness;
        var outerRect = new Rectangle
                        (center.X - outerR, center.Y - outerR, 2 * outerR, 2 * outerR);
        var innerRect = new Rectangle
                        (center.X - innerR, center.Y - innerR, 2 * innerR, 2 * innerR);

        using (var p = new GraphicsPath())
        {
            p.AddArc(outerRect, startAngle, arcLength);
            p.AddArc(innerRect, startAngle + arcLength, -arcLength);
            p.CloseFigure();
            e.Graphics.FillPath(Brushes.Green, p);
            e.Graphics.DrawPath(Pens.Green, p);
        }
    }
}

我希望即使厚度为20或更小时也能填充圆弧。
或者当半径innerR的值改变时。
目标是在任何情况下都能够填充圆弧。

t40tm48m

t40tm48m1#

这里有一种绘制圆锥体的方法。
它看起来像雷达扫描,因此您可能需要定义扫描Angular 和旋转速度(根据计时器的间隔,当前旋转Angular 增加了多少)。
使用标准的System.Windows.Forms.Timer使包含图像的画布无效。

  • Radar* 轮廓(外部周长)在画布上居中,并根据指定的厚度绘制(因此它的大小始终与画布边界一致)。它不一定是正圆,也可以是椭圆(如图所示)
  • Cone* 部分是通过向GraphicsPath添加一个Arc来绘制的,并且是通过绘制两条线来闭合的,从外部GraphicsPath的中心点到Arc的起点和终点(我认为这是一个生成曲线圆锥图形的简单方法,它可以用于不同的情况,并且让您几乎无需计算就可以生成不同的形状,请参阅有关此操作的代码)

它是用LinearGradientBrush填充的,靠近中心的部分比靠近边界的部分透明度低;按需调整
每次旋转Angular 达到360°时,都会重置为0
这将委托给计时器的Tick事件处理程序
=〉使用.Net 7构建,但如果您需要将其适配到.Net Framework,则只需更改using块的语法,从此处删除空值宽容运算符:canvas!.ClientRectangle和可空引用类型(例如,将object?更改为object

public partial class SomeForm : Form {
    public SomeForm() {
        InitializeComponent();
        radarTimer.Interval = 100;
        radarTimer.Tick += RadarTimer_Tick;
    }

    float coneSweepAngle = 36.0f;
    float coneRotationAngle = .0f;
    float radarSpeed = 1.8f;
    float radarThickness = 5.0f;
    System.Windows.Forms.Timer radarTimer = new System.Windows.Forms.Timer();

    private void RadarTimer_Tick(object? sender, EventArgs e) {
        coneRotationAngle += radarSpeed;
        coneRotationAngle %= 360.0f;
        canvas.Invalidate();
    }

    private void canvas_Paint(object sender, PaintEventArgs e) {
        var center = new PointF(canvas.Width / 2.0f, canvas.Height / 2.0f);
        RectangleF outerRect = canvas!.ClientRectangle;
        outerRect.Inflate(-(radarThickness / 2.0f), -(radarThickness / 2.0f));

        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

        using var pathOuter = new GraphicsPath();
        using var pathInner = new GraphicsPath();
        pathOuter.AddEllipse(outerRect);

        pathInner.StartFigure();
        pathInner.AddArc(outerRect, coneRotationAngle, coneSweepAngle);
        var arcPoints = pathInner.PathPoints;
        PointF first = arcPoints[0];
        PointF last = arcPoints[arcPoints.Length - 1];
        pathInner.AddLines(new[] { center, last, center, first });
        pathInner.CloseFigure();

        using var outerPen = new Pen(Color.FromArgb(100, Color.Red), radarThickness);
        using var innerBrush = new LinearGradientBrush(
            center, first, Color.FromArgb(200, Color.Orange), Color.FromArgb(20, Color.Orange));

        e.Graphics.FillPath(innerBrush, pathInner);
        e.Graphics.DrawPath(outerPen, pathOuter);
    }
}

它是这样工作的:

相关问题