zoukankan      html  css  js  c++  java
  • WPF之小米Logo超圆角的实现

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

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

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

    先上效果图:

     

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

     1  public class UIElementHelper
     2     {
     3         public static double GetSuperCornerRadius(FrameworkElement obj)
     4         {
     5             return (double)obj.GetValue(SuperCornerRadiusProperty);
     6         }
     7 
     8         public static void SetSuperCornerRadius(FrameworkElement obj, double value)
     9         {
    10             obj.SetValue(SuperCornerRadiusProperty, value);
    11         }
    12 
    13         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)
    19                 {
    20                     el.Clip = null;
    21                 }
    22                 else
    23                 {
    24                     UpdateClip(el);
    25                     if (!el.IsLoaded)
    26                     {
    27                         el.SizeChanged += OnSizeChanged;
    28                     }
    29                 }
    30             })));
    31 
    32         private static void OnSizeChanged(object sender, SizeChangedEventArgs e)
    33         {
    34             UpdateClip(sender as FrameworkElement, false);
    35         }
    36 
    37         private static void UpdateClip(FrameworkElement el, bool updatePoints = true)
    38         {
    39             if (!updatePoints && el.Clip is StreamGeometry clip && !clip.IsFrozen)
    40             {
    41                 //
    42             }
    43             else
    44             {
    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.PolyLineTo(points, false, false);//根据坐标点画线
    51                 }
    52                 points.Clear();
    53                 el.Clip = clip;//元素的剪切路径
    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         }
    61 
    62         /// <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=1
    74                 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         }
    85 
    86 
    87     }

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

  • 相关阅读:
    Effective Java:Ch4_Class:Item14_在public类中应该使用访问方法而不是public域
    [置顶] 学习JDK源码:可进一步优化的代码
    [置顶] 学习JDK源码:编程习惯和设计模式
    如何开展软件架构之概念架构
    POJ 3667 & 1823 Hotel (线段树区间合并)
    CF 161D Distance in Tree【树DP】
    BroadcastReceiver基础总结
    OSI七层模型具体解释
    习惯的力量之四理直气壮的借口?
    堆(stack) 之 c 和 c++模板实现(空类默认成员函数 初谈引用 内联函数)
  • 原文地址:https://www.cnblogs.com/LCHL/p/14706407.html
Copyright © 2011-2022 走看看