某些新闻:小米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 }
工程文件,感兴趣的下载玩玩。