How to build a nice Hamburger Button transition in Swift

How to build a nice Hamburger Button transition in Swift,第1张

概述Hamburger buttons may have become somewhat of a cliché in interface designlately, but when I came across a particularly nice transition of ahamburger button on dribbble, I had to try and recreate it i

Hamburger buttons may have become somewhat of a cliché in interface designlately,but when I came across a particularly nice transition of ahamburger button on dribbble,I had to try and recreate it in code.

Here’s the original shot by the CreativeDash team:

You’ll notice how the top and bottom strokes of the hamburger form a X,whilethe mIDdle one morphs into an outline. I knew this effect Could be recreatedusing CAShapeLayer,but first I had to create a CGPath for each of the threestrokes.

The short,straight strokes can be figured out manually:

let shortstroke: CGPath = {    let path = CGPathCreateMutable()    CGPathMovetoPoint(path,nil,2,2)    CGPathAddlinetoPoint(path,28,2)    return path}()

For the mIDdle stroke however,I created a path in Sketch that starts from themIDdle and seamlessly Transitions into the outline.

I then exported this path as an SVG file and imported it into the oldPaintCode 1,which converted the file into a code snippet that created aUIBezIErPath. I then rewrote saID pIEce of code into the followinginstructions that create the desired CGPath object:

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

There probably is a library that allows you to load CGPaths straight from SVGfiles,but for a short path like this one,having it in code is not a big deal.

In my UIbutton subclass,I added three CAShapeLayer propertIEs and set thetheir paths accordingly:

self.top.path = shortstrokeself.mIDdle.path = outlineself.bottom.path = shortstroke

Then I styled all three of them like so:

layer.fillcolor = nillayer.strokecolor = UIcolor.whitecolor().CGcolorlayer.linewidth = 4layer.miterlimit = 4layer.lineCap = kCAlineCapRoundlayer.masksToBounds = true

In order to calculate their bounds correctly,I needed take the size of thestroke into account. Thankfully,CGPathCreatecopyByStrokingPath will create apath that follows the outlines of the original stroke,therefore its boundingBox will then fully contain the contents of the CAShapeLayer:

let boundingPath = CGPathCreatecopyByStrokingPath(layer.path,4,kCGlineCapRound,kCGlineJoinMiter,4)layer.bounds = CGPathGetPathBoundingBox(boundingPath)

Since the outer strokes will later rotate around their right-most point,I hadto set their anchorPoint accordingly when layouting their layers:

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)

Now,when the button changes state,it should animate the three strokes to theirnew positions. Once again,the two outer strokes are easy. For the top stroke,Ifirst moved it inward by 4 points to keep in centered,then rotated it bynegative 45 degrees to form one half of the X:

var transform = CAtransform3DIDentitytransform = CAtransform3DTranslate(transform,-4,0)transform = CAtransform3DRotate(transform,-M_PI_4,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

(The bottom stroke is left as an exercise to the reader.)

Again,the mIDdle stroke is a little trickIEr. In order to achIEve the desiredeffect,I needed to animate the CAShapeLayer’s strokeStart and strokeEndpropertIEs separately.

First I had to figure out the correct values for the two propertIEs in the twostates. Note that the even in its hamburger state,the stroke does not start at0. By having the path extend slightly beyond the left edge of the outer strokes,we can achIEve a nice anticipation effect when applying the timing functionlater:

let menustrokeStart: CGfloat = 0.325let menustrokeEnd: CGfloat = 0.9let hamburgerstrokeStart: CGfloat = 0.028let hamburgerstrokeEnd: CGfloat = 0.111

Now we only need to create the animations and add them to the layer:

let strokeStart = CABasicAnimation(keyPath: "strokeStart")strokeStart.fromValue = hamburgerstrokeStartstrokeStart.tovalue = menustrokeStartstrokeStart.duration = 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.duration = 0.6strokeEnd.timingFunction = camediatimingFunction(controlPoints: 0.25,1)self.mIDdle.addAnimation(strokeEnd,forKey: "strokeEnd")self.mIDdle.strokeEnd = menustrokeEnd

Putting everything together,the result looks something like this:

总结

以上是内存溢出为你收集整理的How to build a nice Hamburger Button transition in Swift全部内容,希望文章能够帮你解决How to build a nice Hamburger Button transition in Swift所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1080775.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存