WPF之小米Logo超圆角的实现
2021-04-26 21:19
781 查看
某些新闻:小米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 56c { 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.PolyBezierTo(points, true, true);//根据坐标点画贝塞尔曲线 51 } 52 points.Clear(); 53 el.Clip = c ad8 lip;//元素的剪切路径 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 }
工程文件,感兴趣的下载玩玩。
相关文章推荐
- WPF TextBox 实现CornerRadius圆角
- WPF/Silverlight TextBox 实现CornerRadius圆角
- WPF/Silverlight TextBox 实现CornerRadius圆角
- WPF——Sharder实现Logo走光动画
- Flex实现ColumnChart柱图为圆角矩形的itemRenderer
- 水晶报表(Crystal Report)通过Visual Studio 2010的WPF实现
- Unity3D 开发之shader教程(实现圆角矩形)
- WPF下可编辑Header的Tab控件实现
- div无图片实现圆角矩形
- WPF实现Winform的DoEvent事件
- WPF实现窗口从右下角垂直向上和水平向左淡出
- WPF实现不规则窗体(C#) .
- WPF数据绑定(一):ListView + BindingList实现列表数据绑定
- WPF实现界面动态布局
- WPF中实现进度条
- Android 完美实现图片圆角和圆形(对实现进行分析)
- MVVM框架下,WPF实现Datagrid里的全选和选择
- Android ListView实现圆角
- 纯CSS实现圆角、可拖动的一个DIV弹出层
- WPF实现窗体中的悬浮按钮