WPF编程,小米Logo超圆角的实现

原文:https://www.cnblogs.com/LCHL/p/14706407.html

代码下载地址:
https://download.csdn.net/download/qq_43307934/18275748

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

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

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

先上效果图:在这里插入图片描述
经过一番了解,其实本质也就一条数学函数:|x|n+|y|n=1,上代码:

public class UIElementHelper
    {
        public static double GetSuperCornerRadius(FrameworkElement obj)
        {
            return (double)obj.GetValue(SuperCornerRadiusProperty);
        }

        public static void SetSuperCornerRadius(FrameworkElement obj, double value)
        {
            obj.SetValue(SuperCornerRadiusProperty, value);
        }

        public static readonly DependencyProperty SuperCornerRadiusProperty =
            DependencyProperty.RegisterAttached("SuperCornerRadius", typeof(double), typeof(UIElementHelper), new PropertyMetadata(0.0, new PropertyChangedCallback((s, e) =>
            {
                var n = (double)e.NewValue;
                var el = s as FrameworkElement;
                if (n == 0)
                {
                    el.Clip = null;
                }
                else
                {
                    UpdateClip(el);
                    if (!el.IsLoaded)
                    {
                        el.SizeChanged += OnSizeChanged;
                    }
                }
            })));

        private static void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateClip(sender as FrameworkElement, false);
        }

        private static void UpdateClip(FrameworkElement el, bool updatePoints = true)
        {
            if (!updatePoints && el.Clip is StreamGeometry clip && !clip.IsFrozen)
            {
                //
            }
            else
            {
                clip = new StreamGeometry();
                var points = GetSuperCornerRadiusPoints(GetSuperCornerRadius(el));
                using(var context = clip.Open())
                {
                    context.BeginFigure(points[0], true, true);
                    context.PolyBezierTo(points, true, true);//根据坐标点画贝塞尔曲线
                }
                points.Clear();
                el.Clip = clip;//元素的剪切路径
            }
            var group = new TransformGroup();
            group.Children.Add(new TranslateTransform(1, 1));//WPF以左上角为坐标原点,所以这里进行位移
            var w = el.RenderSize.Width / 2;
            group.Children.Add(new ScaleTransform(w, w));//放大
            clip.Transform = group;
        }

        /// <summary>
        /// 计算超圆角路径的坐标点
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        public static List<Point> GetSuperCornerRadiusPoints(double n = 3)
        {
            var points = new List<Point>();
            //求出Y>0时坐标
            for (double x = -1; x <= 1; x += 0.001)
            {
                var y = Math.Pow(1 - Math.Pow(Math.Abs(x), n), 1 / n);//公式:|x|^n+|y|^n=1
                points.Add(new Point(x, Math.Round(y, 3)));//3位小数,精度应该足够了
            }
            //Y<0的坐标
            var count = points.Count;
            for (int i = 1; i < count + 1; i++)
            {
                var p = points[count - i];
                points.Add(new Point(p.X, p.Y * -1));
            }
            return points;
        }


    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值