Тень, созданная с помощью PathGradientBrush, показывает нежелательные результаты с шипами. - PullRequest
2 голосов
/ 20 мая 2019

Я не могу понять, почему у теневого пути шипы около Стрелки.
См. Мой скриншот.

using (GraphicsPath _Path = new GraphicsPath())
{
    Point[] _Points = new Point[] { 
            new Point { X = mouseDownX, Y = mouseDownY }, 
            new Point { X = lineEndX - 51, Y = mouseDownY },
            new Point { X = lineEndX - 51, Y = mouseDownY  - 20 },
            new Point { X = lineEndX, Y = mouseDownY + 5},
            new Point { X = lineEndX -51, Y = mouseDownY + 25},
            new Point { X = lineEndX -51, Y = mouseDownY +10 },
            new Point { X = mouseDownX, Y = mouseDownY +10 }};    
    _Path.AddPolygon(_Points);                                                                                     
    using (PathGradientBrush _Brush = new PathGradientBrush(_Path))
    {
        _Brush.WrapMode = WrapMode.Clamp;
        ColorBlend _ColorBlend = new ColorBlend(3);
        _ColorBlend.Colors = new Color[]{Color.Transparent, 
                                 Color.FromArgb(180, Color.DimGray),
                                 Color.FromArgb(180, Color.DimGray)};
        _ColorBlend.Positions = new float[] { 0f, 0.1f, 1f};
        _Brush.InterpolationColors = _ColorBlend;
        //myGraphics.Clip = new Region(_Path);
        myGraphics.FillPath(_Brush,_Path);
        //myGraphics.ResetClip();
    }
    Matrix _Matrix = new Matrix();
    int _ShadowDistance = -40;
    _Matrix.Translate(_ShadowDistance, _ShadowDistance);
    _Path.Transform(_Matrix);
    myGraphics.FillPath(Brushes.Red, _Path);
}

Снимок экрана:
PathGradientBrush shadow

1 Ответ

2 голосов
/ 20 мая 2019

Один из способов решения проблемы - указать внутренние PathGradientBrush FocusScales , чтобы ограничить спад цвета без ущерба для смешения цветов.

К сожалению 1 Документы на самом деле не описывают, для чего используется это свойство.
Вы можете прочитать более подробное описание здесь: Как: создать градиент пути
К сожалению 2 , код, который должен реализовать , описание отсутствует.

Отклонение можно регулировать по цветным позициям. Поскольку вы указали:

Positions = new float[] { 0.0f, 0.1f, 1.0f }

цветовые спады могут быть установлены на:

brush.FocusScales = new PointF(0.1f, 1.0f);

Горизонтальная шкала может быть скорректирована, но в пределах половины общего измерения, в противном случае смешивание цветов будет нарушено: вы не увидите сглаживание прозрачности на краях фигуры.

Лучший результат достигается также при установке PixelOffsetMode на PixelOffsetMode.Half.
К сожалению, 3 , описание Документов здесь неверно, обратитесь к документации C ++ об этом параметре .

PathGradientBrush - FocusScales

Общая реализация (с использованием Panel как canvas ):
(Вы можете включить рисование только на событии MouseDown)

mousePosition - расположение указателя мыши. Может быть установлен на событие MouseDown.

private Point mousePosition = Point.Empty;
private float lineSize = 100.0f;
private int shadowDistance = 16;

private void panel1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;

    using (var path = new GraphicsPath(FillMode.Winding))
    {
        PointF[] arrowPoints = new PointF[] {
            mousePosition,
            new PointF (mousePosition.X - 20f, mousePosition.Y + 10f),
            new PointF (mousePosition.X - 20f, mousePosition.Y + 3f),
            new PointF (mousePosition.X - lineSize, mousePosition.Y + 3f),
            new PointF (mousePosition.X - lineSize, mousePosition.Y - 3f),
            new PointF (mousePosition.X - 20f, mousePosition.Y - 3f),
            new PointF (mousePosition.X - 20f, mousePosition.Y - 10f)
        };
        path.AddLines(arrowPoints);

        using (var brush = new PathGradientBrush(path.PathPoints, WrapMode.Clamp))
        {
            var blend = new ColorBlend()
            {
                Colors = new Color[] { Color.Transparent,
                                       Color.FromArgb(180, Color.DimGray),
                                       Color.FromArgb(180, Color.DimGray) },
                Positions = new float[] { 0.0f, 0.2f, 1.0f }
            };
            brush.FocusScales = new PointF(0.2f, 1.0f);
            brush.InterpolationColors = blend;
            e.Graphics.FillPath(brush, path);
        }
        using (var mx = new Matrix())
        {
            mx.Translate(-shadowDistance, -shadowDistance);
            e.Graphics.Transform = mx;
            e.Graphics.FillPath(Brushes.Red, path);
        }
    }
}
...