[英]Get color in specific location on gradient
I have the following GradientStopCollection
: 我有以下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));
Can I get the color at a specific "location"? 我可以在特定的“位置”获得颜色吗? For example: 例如:
Yellow<~>Green
位置.75: Yellow<~>Green
Is there an API in WPF
/ some third party library that could do that? WPF
/某些第三方库中是否有API可以做到这一点?
To get a color at a specific point is necessary to understand the gradient in question, and this is not the role of class GradientStopCollection. 要获得特定点的颜色,有必要了解有问题的渐变,这不是GradientStopCollection类的作用。 The concept of this class is not to understand a gradient, but should be a simple collection of support to a gradient. 这个类的概念不是要理解渐变,而应该是对渐变的简单支持集合。
Is important that you understand the concept of each class. 重要的是要了解每个班级的概念。
To get a color, you need to instantiate a class that represents a gradient using the gradient to paint and finally get their color from the painting. 要获得颜色,您需要使用渐变来实例化一个表示渐变的类,并最终从绘画中获取颜色。
but I'll give you a quicker solution. 但我会给你一个更快的解决方案。 You can use a gradient algorithm to generate a single point. 您可以使用渐变算法生成单个点。 This is an implementation of how to do this using a linear gradient algorithm: 这是使用线性渐变算法如何执行此操作的实现:
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: This algorithm assumes there are no stops with the same offset. PS:该算法假设没有具有相同偏移的停止。 If there are multiple stops with the same offset a
InvalidOperationException
will be thrown. 如果有多个具有相同偏移量的停靠点,则将抛出InvalidOperationException
。
Add this class in your current context (namespace context) 在当前上下文中添加此类(名称空间上下文)
To get your color in any place you insert something like this: 要在任何地方获取颜色,请插入以下内容:
var color = grsc.GetRelativeColor(.75);
I've tried the method written by Jonny Piazzi. 我尝试过Jonny Piazzi写的方法。 But it didn't work correctly. 但它无法正常工作。
So I write my own one below: 所以我在下面写下自己的一个:
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);
}
I hope it works for you! 我希望这个对你有用!
I've used this method in my xaml code below to show a specified number as heat map position. 我在下面的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}"/>
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.