问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何用Swift做一个不错的按钮变换动画

发布网友 发布时间:2022-04-20 05:08

我来回答

1个回答

热心网友 时间:2023-09-03 19:05

我们可以这样手动创建一个短短的直线:

let shortStroke: CGPath = {let path = CGPathCreateMutable()CGPathMoveToPoint(path, nil, 2, 2)CGPathAddLineToPoint(path, nil, 28, 2)return path}()

不过对于中间那个线,因为它有比较复杂的运动轨迹,所以我用 Sketch 创建了一条路径,把动画融入了线条中:

接下来我把图片导出成了 SVG 格式,然后通过 PaintCode 1 把图片转换成代码片段,导入项目中。接下来我重写了导入的代码片段,并且创建了想要的 CGPath 对象:

let outline: CGPath = {let path = CGPathCreateMutable()CGPathMoveToPoint(path, nil, 10, 27)CGPathAddCurveToPoint(path, nil, 12.00, 27.00, 28.02, 27.00, 40, 27)CGPathAddCurveToPoint(path, nil, 55.92, 27.00, 50.47,2.00, 27,2)CGPathAddCurveToPoint(path, nil, 13.16,2.00,2.00, 13.16,2, 27)CGPathAddCurveToPoint(path, nil,2.00, 40.84, 13.16, 52.00, 27, 52)CGPathAddCurveToPoint(path, nil, 40.84, 52.00, 52.00, 40.84, 52, 27)CGPathAddCurveToPoint(path, nil, 52.00, 13.16, 42.39,2.00, 27,2)CGPathAddCurveToPoint(path, nil, 13.16,2.00,2.00, 13.16,2, 27)return path}()

可能有第三方的类库可以让你直接把 SVG 转换成 CGPath,但是对于这种简单的图像,没必要杀鸡用牛刀。

在我自定义的 UIButton 的子类里,我添加了三个  CAShapeLayer 属性并且把他们和前面定义的路径关联了起来:

self.top.path = shortStrokeself.middle.path = outlineself.bottom.path = shortStroke

然后设置一下相关的属性:

layer.fillColor = nillayer.strokeColor = UIColor.whiteColor().CGColorlayer.lineWidth = 4layer.miterLimit = 4layer.lineCap = kCALineCapRoundlayer.masksToBounds = true

为了正确的计算出边框 ( bounds ) ,我需要对这些线条的大小进行计算。谢天谢地,用CGPathCreateCopyByStrokingPath 这个函数可以创建一条和原来线条一样的路径,所以它的  bounds 和参数里那个 CAShapeLayer 类型的内容完全一致:

let boundingPath = CGPathCreateCopyByStrokingPath(layer.path, nil, 4, kCGLineCapRound, kCGLineJoinMiter, 4)layer.bounds = CGPathGetPathBoundingBox(boundingPath)

因为汉堡按钮的上下两个线条接下来会绕着最右点旋转,所以在布局图层的时候,我们需要相应的设置它的锚点 ( anchorPoint ):

self.top.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)self.top.position = CGPointMake(40, 18)self.middle.position = CGPointMake(27, 27)self.middle.strokeStart = hamburgerStrokeStartself.middle.strokeEnd = hamburgerStrokeEndself.bottom.anchorPoint = CGPointMake(28.0 / 30.0, 0.5)self.bottom.position = CGPointMake(40, 36)

接下来就是动画的部分了。当按钮的状态改变的时候,三条直线应该会动态的移动到新的位置。对于那两个外围的直线而言,实现起来很容易。比如最上面的那条线,我先把它往里移动 4 points 让它位于中心位置,然后再逆时针旋转45度,形成了半个 X :

var transform = CATransform3DIdentitytransform = CATransform3DTranslate(transform, -4, 0, 0)transform = CATransform3DRotate(transform, -M_PI_4, 0, 0, 1)let animation = CABasicAnimation(keyPath: "transform")animation.fromValue = NSValue(CATransform3D: CATransform3DIdentity)animation.toValue = NSValue(CATransform3D: transform)animation.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.8, 0.75, 1.85)animation.beginTime = CACurrentMediaTime() + 0.25self.top.addAnimation(animation, forKey: "transform")self.top.transform = transform

最下面的那条线的部分交给读者朋友们作为练习。

接下来,中间的那条直线似乎有点棘手。为了实现理想的效果,我们需要给 CAShapeLayer 的起点和终点分别设置动画效果。

首先我需要知道这两个属性在两种状态下的值分别是多少。注意,就算是在汉堡状态下,直线也没有从 O 开始。路径稍微的从左边延伸,我们可以稍候应用 timing 函数实现一个酷炫的效果:

let menuStrokeStart: CGFloat = 0.325let menuStrokeEnd: CGFloat = 0.9let hamburgerStrokeStart: CGFloat = 0.028let hamburgerStrokeEnd: CGFloat = 0.111

接下来我们只需要创建动画并加到图层里即可:

let strokeStart = CABasicAnimation(keyPath: "strokeStart")strokeStart.fromValue = hamburgerStrokeStartstrokeStart.toValue = menuStrokeStartstrokeStart.ration = 0.5strokeStart.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)self.middle.addAnimation(strokeStart, forKey: "strokeStart")self.middle.strokeStart = menuStrokeStartlet strokeEnd = CABasicAnimation(keyPath: "strokeEnd")strokeEnd.fromValue = hamburgerStrokeEndstrokeEnd.toValue = menuStrokeEndstrokeEnd.ration = 0.6strokeEnd.timingFunction = CAMediaTimingFunction(controlPoints: 0.25, -0.4, 0.5, 1)self.middle.addAnimation(strokeEnd, forKey: "strokeEnd")self.middle.strokeEnd = menuStrokeEnd

把前面的工作整合一下,你可以看到如下的结果:

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
奶锅如何选购 奶锅有哪些品牌推荐 买多少钱的婴儿小奶锅合适呢? 佛字字法可以悬挂哪里 找人写了一个大佛字想挂家里,不知道有什么说法吗?能挂大佛字吗... 日常生活中,有什么东西让你感叹还有这样的用途呢? 明装暖气片安装流程复杂吗 长沙如何装暖气 美国各军种军服 聊天发嗯嗯是什么意思 flash中点击按钮切换图片的效果怎么做?一个按钮对... 如何在Flash中制作一个按钮使其跳转到一个动画里? 我在FLASH里面做了鼠标划过按钮切换图片的动画,但... Axure如何实现点击按钮,图片切换(如图) FLASH场景中动画和按钮中动画的切换 各位大神。。求flash制作。。怎么通过一个按钮从一... 想给按钮左右切换加个动画效果怎么写css3 flash怎么制作一个按钮使点击实现场景切换啊,顺便... MCGS怎么做一个按钮按下然后4秒候切换到下一界面? flash CS4中如何做点击按钮换画面的效果 在pr中第二次按动切换动画按钮会怎么样 PPT怎么用一个按钮自动播放自定义动画→切换幻灯片→... 什么是万用表 z5x怎么看配置 万用表又称万能表或多用表,可用来测量什么? 万用表各个符号表示的意思? 总裁的替身前妻736 acv万用表是什么意思? 总裁的替身前妻里森森是谁的孩子 万用表rel是什么意思 flash 中如何对多个按钮分别设置成控制不同的动画... flash如何用按钮控制动画 flash cs3怎样用按钮操控场景的切换? flash中怎么设置 点击一按钮然后跳到下一个动画 unity3D用4个按钮播放4个不同的动画,在一个场景,... vivoz5大概什么时候出 有哪些靠谱的软件可以通过积分或者任务得金币来兑... 姚记捕鱼兑换令怎么用 有个打鱼的游戏换话费叫什么名字 什么手机游戏可以兑换手机? 支持手机玩的安卓和苹果版的什么打鱼游戏好玩? 我在一起捕鱼游戏兑换京东虚拟购物卡,软件,在京东... 全景地图怎么下载 怎样查看外地街景和下载 百度街景地图能实现某一片区域的实景单机下载吗? 腾讯全景地图可以下载吗 谁知道谷歌街景地图在哪里下载? 下载哪种软件可查地图实景? 手机街景地图APP哪个好 最好的街景地图