13

我有以下内容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:黄色
  • 位置 0.75:Yellow<~>Green

WPF在/某些第三方库中是否有 API可以做到这一点?

4

3 回答 3

19

要获得特定点的颜色,必须了解所讨论的渐变,这不是 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则会抛出 a。

在您当前的上下文(命名空间上下文)中添加此类

为了让你的颜色在任何地方你插入这样的东西:

var color = grsc.GetRelativeColor(.75);
于 2012-03-10T23:21:35.443 回答
4

我试过 Jonny Piazzi 写的方法。但它不能正常工作。
所以我在下面写了我自己的一个:

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}"/>
于 2016-09-12T12:21:47.160 回答
0
  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;
                }
            }
于 2013-10-17T21:20:18.560 回答