加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

用 Swift 制作一个漂亮的汉堡按钮过渡动画

发布时间:2020-12-14 02:17:28 所属栏目:百科 来源:网络整理
导读:原文: How to build a nice Hamburger Button transition in Swift 汉堡按钮在界面设计中已经是老生常谈了,但是当我在dribbble看到这个 漂亮的过渡动画 时,我决定试试用代码实现它。 这是 CreativeDash team 的原型图: 你可能已经注意到了,汉堡顶部和底

原文:How to build a nice Hamburger Button transition in Swift

汉堡按钮在界面设计中已经是老生常谈了,但是当我在dribbble看到这个 漂亮的过渡动画时,我决定试试用代码实现它。
这是 CreativeDash team的原型图:
你可能已经注意到了,汉堡顶部和底部的线条是来自’X’字符,中间的线条变为外框。我知道这种效果可以用CAShapeLayer创建出来,但是首先我得为三条线分别创建一个CGPath。
这种短直线可以手写出来:
 
 
  1. letshortStroke:CGPath={
  2. letpath=CGPathCreateMutable()
  3. CGPathMoveToPoint(path,nil,2,2)
  4. CGPathAddLineToPoint(path,28,2)
  5. returnpath
  6. }()
对于中间的线条,我用Sketch创建了path,从中间开始,然后无缝地过渡到圆形的外框。
接下来我导出这个 path 为 SVG 文件,然后将它导入到旧的 PaintCode1 中,它将转换文件为 UIBezierPath 代码片段。然后我按照说明改写了部分代码,创建了一个使用 CGPath 描述的对象:
  
  
  • letoutline:CGPath={
  • letpath=CGPathCreateMutable()
  • CGPathMoveToPoint(path,10,27)
  • CGPathAddCurveToPoint(path,12.00,27.00,28.02,40,27)
  • CGPathAddCurveToPoint(path,55.92,50.47,2.00,27,2)
  • CGPathAddCurveToPoint(path,13.16,40.84,52.00,52)
  • CGPathAddCurveToPoint(path,52,42.39,27)
  • 可能有第三方库能够帮助你从 SVG 文件直接加载为 CGPaths,但是这样的 path 我们这里只有这一个,所以用代码写也无所谓啦。
    在我的 UIButton 子类中,我添加了三个 CAShapeLayer 属性,并设置它们为相应的 path:
      
      
  • self.top.path=shortStroke
  • self.middle.path=outline
  • self.bottom.path=shortStroke
  • 然后我设置了它们三个的样式:
      
      
  • layer.fillColor=nil
  • layer.strokeColor=UIColor.whiteColor().CGColor
  • layer.lineWidth=4
  • layer.miterLimit=4
  • layer.lineCap=kCALineCapRound
  • layer.masksToBounds=true
  • 为了正确地计算出它们的边界,我需要将画笔的大小考虑在内。幸运的是,CGPathCreateCopyByStrokingPath 将创建沿用了原先的画笔的轮廓路径,因此它的边框会完全包含 CAShapeLayer 的内容:
      
      
  • letboundingPath=CGPathCreateCopyByStrokingPath(layer.path,4,kCGLineCapRound,kCGLineJoinMiter,4)
  • layer.bounds=CGPathGetPathBoundingBox(boundingPath)
  • 由于外框将在稍后围绕其最右边的点旋转,我只好在 layers 布局时设置相应的 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=hamburgerStrokeStart
  • self.middle.strokeEnd=hamburgerStrokeEnd
  • self.bottom.anchorPoint=CGPointMake(28.0/30.0,0.5)
  • self.bottom.position=CGPointMake(40,36)
  • 现在,当按钮改变状态时,它应当显示三条线到新位置的动画。接下来的两个外笔划非常简单。对于顶部的线条,我首先将它向内移动4个points,以保持在中心,然后旋转至负45度,形成半个X:
      
      
  • vartransform=CATransform3DIdentity
  • transform=CATransform3DTranslate(transform,-4,0)
  • transform=CATransform3DRotate(transform,-M_PI_4,1)
  • letanimation=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.25
  • self.top.addAnimation(animation,forKey:"transform")
  • self.top.transform=transform
  • (底部的线条留给读者作为练习吧。)
    中部的线条有点麻烦。为了达到预期的效果,我需要单独为 CAShapeLayer 的 strokeStart 和 strokeEnd 属性添加动画。
    首先,我必须弄清楚在两种状态下的这两个属性正确的值。注意,即使是汉堡包状态下,笔画也不是从0开始。由现有路径延伸略微超过外笔划的左边缘,当应用到 timingFunction 后,我们就完美实现了预期的效果:
      
      
  • letmenuStrokeStart:CGFloat=0.325
  • letmenuStrokeEnd:CGFloat=0.9
  • lethamburgerStrokeStart:CGFloat=0.028
  • lethamburgerStrokeEnd:CGFloat=0.111
  • 现在我们只需要创建动画,然后添加它们到 layer 中:
      
      
  • letstrokeStart=CABasicAnimation(keyPath:"strokeStart")
  • strokeStart.fromValue=hamburgerStrokeStart
  • strokeStart.toValue=menuStrokeStart
  • strokeStart.duration=0.5
  • strokeStart.timingFunction=CAMediaTimingFunction(controlPoints:0.25,-0.4,0.5,1)
  • self.middle.addAnimation(strokeStart,forKey:"strokeStart")
  • self.middle.strokeStart=menuStrokeStart
  • letstrokeEnd=CABasicAnimation(keyPath:"strokeEnd")
  • strokeEnd.fromValue=hamburgerStrokeEnd
  • strokeEnd.toValue=menuStrokeEnd
  • strokeEnd.duration=0.6
  • strokeEnd.timingFunction=CAMediaTimingFunction(controlPoints:0.25,1)
  • self.middle.addAnimation(strokeEnd,forKey:"strokeEnd")
  • self.middle.strokeEnd=menuStrokeEnd
  • 将所有代码组合在一起,结果如下:
    我很高兴完成了。你可以在 GitHub上找到代码,以及 follow我的Twitter。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    • 推荐文章
        热点阅读