简体   繁体   中英

How can I fill the circular sector of an elliptic shape with a color gradient?

What I want to do is to create this rotating cone visual effect.
I had previously used DirectX for that.

锥体

What i have tried so far:

Even if I'm changing the thickness to 50 or more, the Arc is still not filled.

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);
        }
    }
}

I want to be able to fill the arc even when the thickness is 20 or less.
Or when the value of the innerR radius changes.

The goal is to be able to fill the arc in any case.

弧

Here's one method of drawing that cone.
It looks like a Radar sweep, so you may want to define the sweep angle and the rotation speed (how much the current rotation angle is increased based on the Timer's interval).
Using a standard System.Windows.Forms.Timer to invalidate the Canvas that contains the Image you're showing here.

The Radar contour (the external perimeter) is centered on the canvas and drawn in relation to the thickness specified (so it's always sized as the canvas bounds). It doesn't necessarily be a perfect circle, it can be elliptical (as in the image here)

The Cone section is drawn adding an Arc to a GraphicsPath and is closed drawing two lines, from the center point of the outer GraphicsPath to the starting and ending points of the Arc (I think this is a simple method to generate a curved conic figure, it can be used in different situations and lets you generate different shapes almost without calculations, see the code about this)

It's filled with a LinearGradientBrush , the section near the center has less transparency than the section near the border; adjust as required

Each time the rotation angle reaches 360° , it's reset to 0 .
This is delegated to the Timer's Tick event handler

=> Built with.Net 7, but if you need to adapt it to.Net Framework, the only things to change are the syntax of the using blocks, remove the null-forgiving operator from here: canvas..ClientRectangle and nullable reference types (eg, change object? to just 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);
    }
}

This is how it works:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM