#673 – 将鼠标位置和颜色进行映射(Mapping Mouse Position to Color)

我们可以将鼠标的位置信息隐射成颜色的色调和饱和度,然后将HSV颜色值转换为RGB颜色值(我们将亮度值设为1.0)。我们将鼠标位置和中心点连线的角度作为色调值,将鼠标和中心点的距离作为饱和度值。这个图像模型如下图:

下面的代码中我们有一个400*400的Canvas,取鼠标在其上面的位置算出一个颜色显示在Label中。

<Window Name="win1" x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Color from Mouse Position"
        SizeToContent="WidthAndHeight"
        MouseMove="win1_MouseMove_1">
 
    <Canvas x:Name="canv1" Width="400" Height="400">
        <Label Content="{Binding RGBInfo}" HorizontalAlignment="Center" />
    </Canvas>
</Window>

在后台代码中,我们注册MouseMove 事件,并在里面根据鼠标位置计算颜色,作为背景色显示。

/// <summary>
///
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
    SolidColorBrush backBrush = new SolidColorBrush();
 
    public MainWindow()
    {
        InitializeComponent();
 
        this.DataContext = this;
        win1.Background = backBrush;
    }
 
    private string rgbInfo;
    public string RGBInfo  // 用于显示颜色信息的字符串
    {
        get { return rgbInfo; }
        set
        {
            if (value != rgbInfo)
            {
                rgbInfo = value;
                RaisePropertyChanged("RGBInfo");
            }
        }
    }
 
    private void win1_MouseMove_1(object sender, MouseEventArgs e)  // 鼠标移动事件,计算颜色
    {
        double radius = (canv1.ActualWidth / 2);
 
        Color c = ColorFromMousePosition(e.GetPosition(canv1), radius);
        backBrush.Color = c;
        RGBInfo = string.Format("R={0}, G={1}, B={2}", c.R, c.G, c.B);
    }
 
    Color ColorFromMousePosition(Point mousePos, double radius)
    {
        // 相对canvas中心点的坐标位置
        double xRel = mousePos.X - radius;
        double yRel = mousePos.Y - radius;
 
        // 计算色调, 0-360
        double angleRadians = Math.Atan2(yRel, xRel);
        double hue = angleRadians * (180 / Math.PI);
        if (hue < 0)
            hue = 360 + hue;
 
        // 饱和度是鼠标到中心点的距离和半径的比值,0-1
        double saturation = Math.Min(Math.Sqrt(xRel * xRel + yRel * yRel) / radius, 1.0);
 
        byte r, g, b;
        ColorUtil.HsvToRgb(hue, saturation, 1.0, out r, out g, out b);
        return Color.FromRgb(r, g, b);
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
 
    private void RaisePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

下面是HSV转换RGB的代码http://www.splinter.com.au/converting-hsv-to-rgb-colour-using-c/

public static class ColorUtil
{
    /// <summary>
    /// Convert HSV to RGB
    /// h is from 0-360
    /// s,v values are 0-1
    /// r,g,b values are 0-255
    /// Based upon http://ilab.usc.edu/wiki/index.php/HSV_And_H2SV_Color_Space#HSV_Transformation_C_.2F_C.2B.2B_Code_2
    /// </summary>
    public static void HsvToRgb(double h, double S, double V, out byte r, out byte g, out byte b)
    {
        // ######################################################################
        // T. Nathan Mundhenk
        // mundhenk@usc.edu
        // C/C++ Macro HSV to RGB
 
        double H = h;
        while (H < 0) { H += 360; };
        while (H >= 360) { H -= 360; };
        double R, G, B;
        if (V <= 0)
        { R = G = B = 0; }
        else if (S <= 0)
        {
            R = G = B = V;
        }
        else
        {
            double hf = H / 60.0;
            int i = (int)Math.Floor(hf);
            double f = hf - i;
            double pv = V * (1 - S);
            double qv = V * (1 - S * f);
            double tv = V * (1 - S * (1 - f));
            switch (i)
            {
 
                // Red is the dominant color
 
                case 0:
                    R = V;
                    G = tv;
                    B = pv;
                    break;
 
                // Green is the dominant color
 
                case 1:
                    R = qv;
                    G = V;
                    B = pv;
                    break;
                case 2:
                    R = pv;
                    G = V;
                    B = tv;
                    break;
 
                // Blue is the dominant color
 
                case 3:
                    R = pv;
                    G = qv;
                    B = V;
                    break;
                case 4:
                    R = tv;
                    G = pv;
                    B = V;
                    break;
 
                // Red is the dominant color
 
                case 5:
                    R = V;
                    G = pv;
                    B = qv;
                    break;
 
                // Just in case we overshoot on our math by a little, we put these here. Since its a switch it won't slow us down at all to put these here.
 
                case 6:
                    R = V;
                    G = tv;
                    B = pv;
                    break;
                case -1:
                    R = V;
                    G = pv;
                    B = qv;
                    break;
 
                // The color is not defined, we should throw an error.
 
                default:
                    //LFATAL("i Value error in Pixel conversion, Value is %d", i);
                    R = G = B = V; // Just pretend its black/white
                    break;
            }
        }
        r = Clamp((byte)(R * 255.0));
        g = Clamp((byte)(G * 255.0));
        b = Clamp((byte)(B * 255.0));
    }
 
    /// <summary>
    /// Clamp a value to 0-255
    /// </summary>
    private static byte Clamp(byte i)
    {
        if (i < 0) return 0;
        if (i > 255) return 255;
        return i;
    }
}

可以看到,随着鼠标的移动,窗口的背景色也不断的变化。


原文地址:https://wpf.2000things.com/2012/10/22/673-mapping-mouse-position-to-color/

******************************************************译者注*******************************************************
HSV分别表示的是色调、饱和度和亮度。上面的例子中改变的是色调和饱和度,亮度通常取值为0到1的值。我们可以通过其他方式来映射改变亮度是值,比如鼠标通过滚轮增加和减少亮度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值