2016-03-01 4 views
0

Как сопоставить диапазон цветов с целым числом?Как сопоставить диапазон цветов с целым рядом?

В частности, я хочу, чтобы ползунок шел от темно-зеленого, желтого, красного.

Следующий код добавляет оттенок только к цвету.

XAML:

<Window x:Class="MotoLens.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:MotoLens" 
     mc:Ignorable="d" 
     Background="Black" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <local:ValueToBrushConverter x:Key="ValueToBrushConverter" /> 
    </Window.Resources> 
    <Grid> 
     <Slider x:Name="Slider" Grid.Row="0" Minimum="0" Maximum="200" Background="{Binding RelativeSource={RelativeSource Self}, Path=Value, Converter={StaticResource ValueToBrushConverter}, ConverterParameter=0~200}" 
       TickFrequency="1" IsSnapToTickEnabled="True" TickPlacement="TopLeft" /> 
    </Grid> 
</Window> 

ValueConverter:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
{ 
    var args = parameter as string; 
    var minimumInput = int.Parse(args?.Split('~')?[0]); 
    var maximumInput = int.Parse(args?.Split('~')?[1]); 

    var currentValue = (double)value; 
    var colorValue = (int)255 - (currentValue * (COLOR_RANGE_MAX/maximumInput)); 
    var color = Color.FromArgb(COLOR_RANGE_MAX, 0, System.Convert.ToByte(colorValue), 0); 
    return new SolidColorBrush(color); 
} 

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

ОБНОВЛЕНО с помощью Ответ:

namespace MotoLens 
{ 
    class ValueToBrushConverter : IValueConverter 
    { 
     static readonly Color[] _colorTable = 
      { 
      Color.FromRgb( 0, 255, 255), 
      Color.FromRgb( 0, 255, 0), 
      Color.FromRgb(255, 255, 0), 
      Color.FromRgb(255, 0, 0), 
      }; 

     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      var args = parameter as string; 
      var minimumInput = int.Parse(args.Split('~')[0]); 
      var maximumInput = int.Parse(args.Split('~')[1]); 

      var currentValue = ((double)value - minimumInput)/(maximumInput - minimumInput); 
      var col1 = (int)(currentValue * (_colorTable.Length - 1)); 
      var col2 = Math.Min(col1 + 1, (_colorTable.Length - 1)); 

      var t = 1.0/(_colorTable.Length - 1); 
      return new SolidColorBrush(Lerp(_colorTable[col1], _colorTable[col2], (currentValue - t * col1)/t)); 
     } 

     public static Color Lerp(Color col1, Color col2, double t) 
     { 
      var r = col1.R * (1 - t) + col2.R * t; 
      var g = col1.G * (1 - t) + col2.G * t; 
      var b = col1.B * (1 - t) + col2.B * t; 
      return Color.FromRgb((byte)r, (byte)g, (byte)b); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      throw new NotImplementedException(); 
     } 
    } 
} 

ответ

1

Попробуйте это:

private static readonly Color[] ColorTable = 
    { 
     Color.FromRgb(255, 0, 0), 
     Color.FromRgb(255, 255, 0), 
     Color.FromRgb( 0, 255, 0), 
     Color.FromRgb( 0, 255, 255), 
     Color.FromRgb( 0, 0, 255), 
     Color.FromRgb(255, 0, 255), 
     Color.FromRgb(255, 0, 0), 
    }; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    {   
     var args = parameter as string; 
     var minimumInput = int.Parse(args.Split('~')[0]); 
     var maximumInput = int.Parse(args.Split('~')[1]); 
     var currentValue = ((double)value - minimumInput)/(maximumInput - minimumInput); 
     var col1 = (int)(currentValue * (ColorTable.Length-1)); 
     var col2 = Math.Min(col1+1, (ColorTable.Length-1)); 
     var t = 1.0/(ColorTable.Length - 1); 
     return new SolidColorBrush(Lerp(ColorTable[col1], ColorTable[col2], (currentValue - t *col1)/t)); 
    } 

    public static Color Lerp(Color col1, Color col2, double t) 
    { 
     var r = col1.R * (1-t) + col2.R * t; 
     var g = col1.G * (1-t) + col2.G * t; 
     var b = col1.B * (1-t) + col2.B * t; 
     return Color.FromRgb((byte)r, (byte)g, (byte)b); 
    } 
+0

См. Мое обновленное сообщение. –

+0

Итак, вопрос был удовлетворительно удовлетворен? Или существуют другие требования? Кстати, мой ответ на [этот пост] (http://stackoverflow.com/questions/32513387/how-to-create-a-color-canvas-for-color-picker-wpf) относительно выбора цвета также может представлять интерес для в этом случае вы обычно используете что-то вроде полосы оттенков в качестве фона для слайдера. –

+0

Да. Теперь у меня есть новый вопрос: http://stackoverflow.com/questions/35760507/how-can-i-create-a-gauge-i-e-speedometer –

0

Вы могли бы сделать что-то на основе моего ColorExtensions, что есть метод для преобразования из HSL или HSV в RGB. Например.

#region FromHsv() 
/// <summary> 
/// Returns a Color struct based on HSV model. 
/// </summary> 
/// <param name="hue">0..360 range hue</param> 
/// <param name="saturation">0..1 range saturation</param> 
/// <param name="value">0..1 range value</param> 
/// <param name="alpha">0..1 alpha</param> 
/// <returns></returns> 
public static Color FromHsv(double hue, double saturation, double value, double alpha = 1.0) 
{ 
    Debug.Assert(hue >= 0); 
    Debug.Assert(hue <= 360); 

    double chroma = value * saturation; 
    double h1 = hue/60; 
    double x = chroma * (1 - Math.Abs(h1 % 2 - 1)); 
    double m = value - chroma; 
    double r1, g1, b1; 

    if (h1 < 1) 
    { 
     r1 = chroma; 
     g1 = x; 
     b1 = 0; 
    } 
    else if (h1 < 2) 
    { 
     r1 = x; 
     g1 = chroma; 
     b1 = 0; 
    } 
    else if (h1 < 3) 
    { 
     r1 = 0; 
     g1 = chroma; 
     b1 = x; 
    } 
    else if (h1 < 4) 
    { 
     r1 = 0; 
     g1 = x; 
     b1 = chroma; 
    } 
    else if (h1 < 5) 
    { 
     r1 = x; 
     g1 = 0; 
     b1 = chroma; 
    } 
    else //if (h1 < 6) 
    { 
     r1 = chroma; 
     g1 = 0; 
     b1 = x; 
    } 

    byte r = (byte)(255 * (r1 + m)); 
    byte g = (byte)(255 * (g1 + m)); 
    byte b = (byte)(255 * (b1 + m)); 
    byte a = (byte)(255 * alpha); 

    return Color.FromArgb(a, r, g, b); 
} 
#endregion 

Пример - XAML:

<StackPanel> 
    <Slider 
     x:Name="HueSlider" 
     Minimum="0" 
     Maximum="360" 
     StepFrequency="1" 
     ValueChanged="HueSlider_ValueChanged" /> 
    <Rectangle 
     x:Name="HueRect" 
     Width="400" 
     Height="200" /> 
</StackPanel> 

код позади:

private void HueSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e) 
{ 
    HueRect.Fill = new SolidColorBrush(
     FromHsv(e.NewValue, 1, 1)); 
} 
+0

Спасибо. Но я не уверен, что это применительно к отображению целочисленного значения в цвет с помощью min и max. –

+0

Модель HSV имеет компонент оттенка, который легче манипулировать, чтобы получить разные цвета, чем RGB. Вы можете вызывать 'FromHsv (оттенок, 1, 1)' для значений оттенков 0..1 для получения разных значений цвета. Для значений int hue 0..255 вы будете вызывать 'FromHsv ((double) hue/255, 1, 1)', но элемент 'Slider' дает вам' double' напечатал 'Value', а не' int', поэтому вы можете использовать это. –

+0

Собственно, поцарапайте это - диапазон 0..360, поэтому вам нечего делить. –

Смежные вопросы