AI智能
改变未来

WPF之小米Logo超圆角的实现

某些新闻:小米logo换新,程序员一行代码(border-radius:19px)实现,目前此行代码价值200万

某程序员内心:所以还是因为我代码写太少了,所以这200万才没有我的份吗?

这事儿也成功的引起了本羊的注意,花点时间,咱也用WPF来实现一下,到底这超圆角有多好看?

先上效果图:

经过一番了解,其实本质也就一条数学函数:|x|^n+|y|^n=1,上代码:

1  public class UIElementHelper2     {3         public static double GetSuperCornerRadius(FrameworkElement obj)4         {5             return (double)obj.GetValue(SuperCornerRadiusProperty);6         }78         public static void SetSuperCornerRadius(FrameworkElement obj, double value)9         {10             obj.SetValue(SuperCornerRadiusProperty, value);11         }1213         public static readonly DependencyProperty SuperCornerRadiusProperty =14             DependencyProperty.RegisterAttached(\"SuperCornerRadius\", typeof(double), typeof(UIElementHelper), new PropertyMetadata(0.0, new PropertyChangedCallback((s, e) =>15             {16                 var n = (double)e.NewValue;17                 var el = s as FrameworkElement;18                 if (n == 0)1956c{20                     el.Clip = null;21                 }22                 else23                 {24                     UpdateClip(el);25                     if (!el.IsLoaded)26                     {27                         el.SizeChanged += OnSizeChanged;28                     }29                 }30             })));3132         private static void OnSizeChanged(object sender, SizeChangedEventArgs e)33         {34             UpdateClip(sender as FrameworkElement, false);35         }3637         private static void UpdateClip(FrameworkElement el, bool updatePoints = true)38         {39             if (!updatePoints && el.Clip is StreamGeometry clip && !clip.IsFrozen)40             {41                 //42             }43             else44             {45                 clip = new StreamGeometry();46                 var points = GetSuperCornerRadiusPoints(GetSuperCornerRadius(el));47                 using(var context = clip.Open())48                 {49                     context.BeginFigure(points[0], true, true);50                     context.PolyBezierTo(points, true, true);//根据坐标点画贝塞尔曲线51                 }52                 points.Clear();53                 el.Clip = cad8lip;//元素的剪切路径54             }55             var group = new TransformGroup();56             group.Children.Add(new TranslateTransform(1, 1));//WPF以左上角为坐标原点,所以这里进行位移57             var w = el.RenderSize.Width / 2;58             group.Children.Add(new ScaleTransform(w, w));//放大59             clip.Transform = group;60         }6162         /// <summary>63         /// 计算超圆角路径的坐标点64         /// </summary>65         /// <param name=\"n\"></param>66         /// <returns></returns>67         public static List<Point> GetSuperCornerRadiusPoints(double n = 3)68         {69             var points = new List<Point>();70             //求出Y>0时坐标71             for (double x = -1; x <= 1; x += 0.001)72             {73                 var y = Math.Pow(1 - Math.Pow(Math.Abs(x), n), 1 / n);//公式:|x|^n+|y|^n=174                 points.Add(new Point(x, Math.Round(y, 3)));//3位小数,精度应该足够了75             }76             //Y<0的坐标77             var count = points.Count;78             for (int i = 1; i < count + 1; i++)79             {80                 var p = points[count - i];81                 points.Add(new Point(p.X, p.Y * -1));82             }83             return points;84         }858687     }

工程文件,感兴趣的下载玩玩。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » WPF之小米Logo超圆角的实现