You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在C#中实现类谷歌地图锥形渐变:角度与宽度控制问题

实现谷歌地图风格锥形渐变效果(支持颜色、朝向角度、宽度控制)

问题描述

需要实现类似谷歌地图的锥形渐变效果,具体需求:

  • 可控制渐变颜色
  • 可控制锥形的朝向角度
  • 可控制锥形的宽度范围(0-360度)

现有C#代码如下:

internal static Bitmap Generate()
{
    int width = 160;
    int height = 160;
    var color1 = CreateRandomShare(Color.AliceBlue);
    var color2 = CreateRandomShare(Color.Navy);
    var bitmap = GenerateGradient(color1, color2, width, height, LinearGradientMode.BackwardDiagonal);
    bitmap.Save("test.bmp", ImageFormat.Bmp);

    return bitmap;
}

private static Color CreateRandomShare(Color color)
{
    const int range = 1000;
    const int variance = 700;
    var random = new Random(DateTime.Now.Millisecond);
    int factor = random.Next(range - variance, range + variance + 1);
    int r = color.R + factor / range;
    int g = color.G + factor / range;
    int b = color.B + factor / range;

    return Color.FromArgb(255, Math.Min(r, 255), Math.Min(g, 255), Math.Min(b, 255));
}

private static Bitmap GenerateGradient(Color color1, Color color2, int width, int height, LinearGradientMode mode)
{
    Bitmap bmp = new Bitmap(width, height);
    Graphics g = Graphics.FromImage(bmp);
    var brush = new LinearGradientBrush(new Rectangle(0, 0, width, height), color1, color2, mode);
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.SmoothingMode = SmoothingMode.AntiAlias;
    PointF[] points =
    {
        new (50, 50),
        new (100, 25),
        new (200, 5),
        new (250, 5),
        new (300, 100),
        new (350, 200),
        new (250, 250),
    };

    g.FillPolygon(brush, points);
    return bmp;
}

当前效果已接近目标,但无法控制锥形的朝向角度和宽度范围,需要优化实现。

解决方案

核心思路是通过绘制扇形路径结合路径渐变笔刷实现可控的锥形渐变,具体实现如下:

1. 核心修改后的代码

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

public static class ConeGradientGenerator
{
    internal static Bitmap GenerateConeGradient(int width = 160, int height = 160, 
                                               Color centerColor = default, Color edgeColor = default,
                                               float facingAngle = 0f, float coneWidth = 90f)
    {
        // 默认颜色设置(未传入时使用)
        if (centerColor == default) centerColor = Color.AliceBlue;
        if (edgeColor == default) edgeColor = Color.Navy;

        Bitmap bmp = new Bitmap(width, height);
        using (Graphics g = Graphics.FromImage(bmp))
        {
            g.Clear(Color.Transparent); // 背景设为透明(可选)
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            // 计算扇形核心参数
            PointF center = new PointF(width / 2f, height / 2f);
            float radius = Math.Min(width, height) / 2f - 5; // 留边避免超出画布
            // 调整起始角度,使锥形中心对准设定的朝向
            float startAngle = facingAngle - coneWidth / 2f;
            float sweepAngle = coneWidth;

            // 创建扇形路径
            using (GraphicsPath path = new GraphicsPath())
            {
                path.AddPie(center.X - radius, center.Y - radius, 
                            radius * 2, radius * 2, 
                            startAngle, sweepAngle);

                // 创建路径渐变笔刷,实现中心到边缘的颜色过渡
                using (PathGradientBrush brush = new PathGradientBrush(path))
                {
                    brush.CenterColor = centerColor;
                    brush.SurroundColors = new[] { edgeColor };
                    // 可选:调整渐变焦点,控制颜色过渡的集中区域
                    // brush.FocusScales = new PointF(0.2f, 0.2f);

                    g.FillPath(brush, path);
                }
            }
        }

        bmp.Save("cone_test.bmp", ImageFormat.Bmp);
        return bmp;
    }

    // 保留原有的随机颜色生成方法(可选)
    private static Color CreateRandomShare(Color color)
    {
        const int range = 1000;
        const int variance = 700;
        var random = new Random(DateTime.Now.Millisecond);
        int factor = random.Next(range - variance, range + variance + 1);
        int r = color.R + factor / range;
        int g = color.G + factor / range;
        int b = color.B + factor / range;

        return Color.FromArgb(255, Math.Min(r, 255), Math.Min(g, 255), Math.Min(b, 255));
    }

    // 使用示例
    internal static void TestGenerate()
    {
        // 生成朝向90度(东)、宽度60度的锥形渐变
        GenerateConeGradient(facingAngle: 90f, coneWidth: 60f,
                             centerColor: CreateRandomShare(Color.LightBlue),
                             edgeColor: CreateRandomShare(Color.DarkBlue));
    }
}

2. 需求实现说明

  • 颜色控制:通过centerColor和edgeColor参数直接传入目标颜色,也可结合原有的CreateRandomShare方法生成随机衍生颜色。
  • 朝向角度控制:facingAngle参数控制锥形的中心朝向,默认0度为向上(北),90度为向右(东),代码通过startAngle = facingAngle - coneWidth / 2f确保锥形中心精准对准设定方向。
  • 宽度范围控制:coneWidth参数设置锥形的角度宽度(0-360度),传入360度时将生成完整的圆形渐变。

3. 关键细节说明

  • 使用GraphicsPath.AddPie创建扇形路径,这是实现锥形形状的核心。
  • PathGradientBrush实现从中心到边缘的平滑渐变,完美匹配谷歌地图锥形的视觉表现。
  • 画布中心定位和半径计算确保锥形始终在画布内,避免超出边界。

内容的提问来源于stack exchange,提问作者styx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:14:57