Подтвердить что ты не робот

Получить цвет в определенном месте на градиенте

У меня есть GradientStopCollection:

GradientStopCollection grsc = new GradientStopCollection(3);
grsc.Add(new GradientStop(Colors.Red, 0));
grsc.Add(new GradientStop(Colors.Yellow, .5));
grsc.Add(new GradientStop(Colors.Green, 1));

Можно ли получить цвет в определенном месте? Например: Местоположение 0: Красный Расположение .5: Желтый Местоположение .75:??

Существует сторонний класс, который может это сделать?

4b9b3361

Ответ 1

Чтобы получить цвет в определенной точке, необходимо понять рассматриваемый градиент, и это не роль класса GradientStopCollection. Концепция этого класса заключается не в понимании градиента, а в простом наборе поддержки градиента.

Важно понимать концепцию каждого класса.

Чтобы получить цвет, вам нужно создать экземпляр класса, представляющего градиент, используя градиент для рисования и, наконец, получить свой цвет от картины.

но я дам вам более быстрое решение. Вы можете использовать алгоритм градиента для создания единственной точки. Это реализация того, как это сделать, используя алгоритм линейного градиента:

public static class GradientStopCollectionExtensions
{
    public static Color GetRelativeColor(this GradientStopCollection gsc, double offset)
    {
        var point = gsc.SingleOrDefault(f => f.Offset == offset);
        if (point != null) return point.Color;

        GradientStop before = gsc.Where(w => w.Offset == gsc.Min(m => m.Offset)).First();
        GradientStop after = gsc.Where(w => w.Offset == gsc.Max(m => m.Offset)).First();

        foreach (var gs in gsc)
        {
            if (gs.Offset < offset && gs.Offset > before.Offset)
            {
                before = gs;
            }
            if (gs.Offset > offset && gs.Offset < after.Offset)
            {
                after = gs;
            }
        }

        var color = new Color();

        color.ScA = (float)((offset - before.Offset) * (after.Color.ScA - before.Color.ScA) / (after.Offset - before.Offset) + before.Color.ScA);
        color.ScR = (float)((offset - before.Offset) * (after.Color.ScR - before.Color.ScR) / (after.Offset - before.Offset) + before.Color.ScR);
        color.ScG = (float)((offset - before.Offset) * (after.Color.ScG - before.Color.ScG) / (after.Offset - before.Offset) + before.Color.ScG);
        color.ScB = (float)((offset - before.Offset) * (after.Color.ScB - before.Color.ScB) / (after.Offset - before.Offset) + before.Color.ScB);

        return color;
    }
}

PS: Этот алгоритм предполагает, что нет остановок с одинаковым смещением. Если есть несколько остановок с одинаковым смещением, будет InvalidOperationException.

Добавьте этот класс в ваш текущий контекст (контекст пространства имен)

Чтобы получить свой цвет в любом месте, вы вставляете что-то вроде этого:

var color = grsc.GetRelativeColor(.75);

Ответ 2

Я пробовал метод, написанный Джонни Пьяцци. Но это не сработало правильно. Поэтому я пишу свой собственный ниже:

private static Color GetColorByOffset(GradientStopCollection collection, double offset)
{
    GradientStop[] stops = collection.OrderBy(x => x.Offset).ToArray();
    if (offset <= 0) return stops[0].Color;
    if (offset >= 1) return stops[stops.Length - 1].Color;
    GradientStop left = stops[0], right = null;
    foreach (GradientStop stop in stops)
    {
        if (stop.Offset >= offset)
        {
            right = stop;
            break;
        }
        left = stop;
    }
    Debug.Assert(right != null);
    offset = Math.Round((offset - left.Offset)/(right.Offset - left.Offset), 2);
    byte a = (byte) ((right.Color.A - left.Color.A)*offset + left.Color.A);
    byte r = (byte) ((right.Color.R - left.Color.R)*offset + left.Color.R);
    byte g = (byte) ((right.Color.G - left.Color.G)*offset + left.Color.G);
    byte b = (byte) ((right.Color.B - left.Color.B)*offset + left.Color.B);
    return Color.FromArgb(a, r, g, b);
}

Я надеюсь, что это сработает для вас!

Я использовал этот метод в моем коде xaml ниже, чтобы показать указанное число как положение тепловой карты.

<LinearGradientBrush x:Key="CountBrush" StartPoint="0 0" EndPoint="1 0">
    <GradientStop Offset="0.00" Color="ForestGreen"/>
    <GradientStop Offset="0.50" Color="Yellow"/>
    <GradientStop Offset="1.00" Color="OrangeRed"/>
</LinearGradientBrush>
<local:Int32ToColorConverter x:Key="CountToColorConverter" Min="0" Max="200" LinearBrush="{StaticResource CountBrush}"/>

Ответ 3

  foreach (var gs in gsc)
            {
                if (gs.Offset == offset) return gs.Color; //new line added
                if (gs.Offset < offset && gs.Offset > before.Offset)
                {
                    before = gs;
                }

                if (gs.Offset > offset && gs.Offset < after.Offset)
                {
                    after = gs;
                }
            }