欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WPF实现背景灯光随鼠标闪动效果

程序员文章站 2022-05-28 19:41:51
...

实现效果如下:

WPF实现背景灯光随鼠标闪动效果

思路:将容器分割成组合三角形Path,鼠标移动时更新每个三角形的填充颜色。

步骤:

1、窗体xaml

只需放置一个Canvas。

<Canvas x:Name="container" Width="400" Height="400"></Canvas>

2、交互逻辑

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private Point lastMousePosition = new Point(0, 0);//鼠标位置
        private int triangleLength = 100;//三角形边长

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;
            CompositionTarget.Rendering += UpdateTriangle;
            this.container.PreviewMouseMove += UpdateLastMousePosition;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            //将长方形容易划分成组合三角形
            int horizontalCount = (int)(this.container.ActualWidth / triangleLength);
            int verticalCount = (int)(this.container.ActualHeight / triangleLength);
            for (int i = 0; i < horizontalCount; i++)
            {
                for (int j = 0; j < verticalCount; j++)
                {
                    Path trianglePath1 = new Path();
                    var g1 = new StreamGeometry();
                    using (StreamGeometryContext context = g1.Open())
                    {
                        context.BeginFigure(new Point(i * triangleLength, j * triangleLength), true, true);
                        context.LineTo(new Point(i * triangleLength, (j + 1) * triangleLength), true, false);
                        context.LineTo(new Point((i + 1) * triangleLength, (j + 1) * triangleLength), true, false);
                    }
                    trianglePath1.Data = g1;
                    trianglePath1.Fill = new SolidColorBrush(Color.FromArgb(255, 247, 18, 65));
                    this.container.Children.Add(trianglePath1);

                    Path trianglePath2 = new Path();
                    var g2 = new StreamGeometry();
                    using (StreamGeometryContext context = g2.Open())
                    {
                        context.BeginFigure(new Point(i * triangleLength, j * triangleLength), true, true);
                        context.LineTo(new Point((i + 1) * triangleLength, j * triangleLength), true, false);
                        context.LineTo(new Point((i + 1) * triangleLength, (j + 1) * triangleLength), true, false);
                    }
                    trianglePath2.Data = g2;
                    trianglePath2.Fill = new SolidColorBrush(Color.FromArgb(255, 247, 18, 65));
                    this.container.Children.Add(trianglePath2);
                }
            }
        }

        private void UpdateTriangle(object sender, EventArgs e)
        {
            //获取子控件
            List<Path> childList = GetChildObjects<Path>(this.container);
            for (int i = 0; i < childList.Count; i++)
            {
                for (int j = 1; j < childList.Count; j++)
                {
                    string si = childList[i].Data.ToString();
                    string si1 = MidStrEx(si, "M", "L");
                    string si2 = MidStrEx(si, "L", " ");
                    string si3 = MidStrEx(si, " ", "z");
                    string sj = childList[j].Data.ToString();
                    string sj1 = MidStrEx(sj, "M", "L");
                    string sj2 = MidStrEx(sj, "L", " ");
                    string sj3 = MidStrEx(sj, " ", "z");
                    //左右三角形判断
                    if (si1 == sj1 && si3 == sj3)
                    {
                        double x = childList[i].Data.Bounds.X + (1 - Math.Pow(2, 0.5) / 2) * triangleLength - lastMousePosition.X;
                        double y = childList[i].Data.Bounds.Y + (1 - Math.Pow(2, 0.5) / 2) * triangleLength - lastMousePosition.Y;
                        double rRadio = 1 - Math.Pow(x * x + y * y, 0.5) / Math.Pow(this.container.ActualWidth * this.container.ActualWidth + this.container.ActualHeight * this.container.ActualHeight, 0.5);
                        childList[j].Fill = new SolidColorBrush(Color.FromArgb((byte)(255 * rRadio), 247, 18, 65));
                        x = childList[j].Data.Bounds.TopRight.X - (1 - Math.Pow(2, 0.5) / 2) * triangleLength - lastMousePosition.X;
                        rRadio = 1 - Math.Pow(x * x + y * y, 0.5) / Math.Pow(this.container.ActualWidth * this.container.ActualWidth + this.container.ActualHeight * this.container.ActualHeight, 0.5);
                        childList[i].Fill = new SolidColorBrush(Color.FromArgb((byte)(255 * rRadio), 247, 18, 65));
                        break;
                    }
                }
            }
        }

        private void UpdateLastMousePosition(object sender, MouseEventArgs e)
        {
            lastMousePosition = e.GetPosition(this.container);
        }

        /// <summary>
        /// 获得所有子控件
        /// </summary>
        private List<T> GetChildObjects<T>(System.Windows.DependencyObject obj) where T : System.Windows.FrameworkElement
        {
            System.Windows.DependencyObject child = null;
            List<T> childList = new List<T>();
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                child = VisualTreeHelper.GetChild(obj, i);
                if (child is T)
                {
                    childList.Add((T)child);
                }
                childList.AddRange(GetChildObjects<T>(child));
            }
            return childList;
        }

        /// <summary>
        /// 截取两个指定字符中间的字符串
        /// </summary>
        public static string MidStrEx(string sourse, string startstr, string endstr)
        {
            string result = string.Empty;
            int startindex, endindex;
            try
            {
                startindex = sourse.IndexOf(startstr);
                if (startindex == -1)
                    return result;
                string tmpstr = sourse.Substring(startindex + startstr.Length);
                endindex = tmpstr.IndexOf(endstr);
                if (endindex == -1)
                    return result;
                result = tmpstr.Remove(endindex);
            }
            catch (Exception ex)
            {
            }
            return result;
        }
    }

说明:当组合三角形过多时,会有明显卡顿,需要优化色彩更新方法。