IOS Animation teaches you to write slack loading animation step _ios

Source: Internet
Author: User
Tags local time time interval

A few days ago to read a blog about animation to hand-touch hand to teach you to write slack Loading animation, looking quite flashy, but is an Android version of The imitation of the copy to write an iOS version, the following is I write this animation decomposition ~

The old rules first figure and demo address:

Just saw this animation, the mind appeared in two schemes, one is to draw out through DrawRect, and then with Cadisplaylink constantly draw line style; The second is to achieve animation effect by Cashapelayer with Caanimation. Think twice about using the latter, because the former needs to be calculated a lot, more complex, and after testing the former consumes more CPU than the latter, I write down the following ideas:

Related configuration and initialization methods

Before writing this animation, we have to write the first required attributes, such as the thickness of the line, animation time, and so on, the following is the relevant configuration and the first method of recognition:

  Line width var linewidth:cgfloat = 0//length of line var linelength:cgfloat = 0/margin var margin:cgfloat = 0//animation time Var Duration:double = 2//animation time interval var interval:double = 1//four line color var colors:[uicolor] = [Uicolor.init (rgba: "#9DD4E 9 "), Uicolor.init (rgba:" #F5BD58 "), Uicolor.init (rgba:" #FF317E "), Uicolor.init (rgba:" #6FC9B5 ")]//state of the animation private (SE T) var status:animationstatus =.
    Normal//Four line private var lines:[cashapelayer] = [] enum Animationstatus {//normal state case normal//animation Case animating//pause case Pause}//mark:initial Methods convenience init (fram:cgrect, colors: [Uicolor]
    {Self.init () Self.frame = frame self.colors = Colors config ()} override init (Frame:cgrect) { Super.init (frame:frame) config ()} required init? (Coder Adecoder:nscoder) {super.init (Coder:adecoder) config ()} private func config () {linelength = max (Frame.width, Frame.heig HT) LineWidth = Linelength/6.0 margin = linelength/4.5 + linewidth/2 drawlineshapelayer () transform = Cgaffinetransformrotate (cgaff

 Inetransformidentity, Angle (-30))}

Draw a line by Cashapelayer

See this line I think of the cashapelayer to deal with, because Cashapelayer can achieve this effect, and its strokeend properties can be used to achieve the length of the line animation, the following four lines of code to draw:

MARK: Draw line/** draw four lines */private func Drawlineshapelayer () {//start dot let startpoint = [Point (LINEWIDTH/2, Y:margin), point (Linelength-margin, Y:LINEWIDTH/2), point (LINELENGTH-LINEWIDTH/2, Y:line  Length-margin), point (Margin, Y:LINELENGTH-LINEWIDTH/2)]//End dot Let endPoint = [points (linelength -LINEWIDTH/2, Y:margin), point (Linelength-margin, Y:LINELENGTH-LINEWIDTH/2), point (Lin EWIDTH/2, Y:linelength-margin), point (Margin, Y:LINEWIDTH/2)] for I in 0...3 {let Line:cashap Elayer = Cashapelayer () line.linewidth = linewidth Line.linecap = Kcalinecapround line.opacity = 0. 8 Line.strokecolor = Colors[i]. Cgcolor Line.path = Getlinepath (Startpoint[i], endpoint:endpoint[i]).
   Cgpath Layer.addsublayer (lines) Lines.append (line)}}/** the path to the fetch-parameter startpoint: Start point
-Parameter endPoint: End point
   -Returns: The path of the line * * Private func Getlinepath (Startpoint:cgpoint, endpoint:cgpoint)-> Uibezierpath {Let Path = Uibezierpath () path.movetopoint (startpoint) path.addlinetopoint (endPoint) return path} private Fu NC Point (X:cgfloat, y:cgfloat)-> Cgpoint {return cgpointmake (x, y)} private func angle (angle:double) ;

 CGFloat {return CGFloat (angle * (m_pi/180))}

After the implementation of the same as the previous image of the effect of ~ ~ ~

Animation decomposition

After analysis, the animation can be divided into four steps:
• Rotate animation of canvas, rotate two circles
• Lines are executed with a long, short animation, a more canvas-selected animation, and the end of a round rotation
• Line displacement animation, the line gradually toward the middle, and then the brush rotation around the time of execution, two laps when the end
• Line from short to long animation, the canvas rotated two times when the execution

First step canvas rotation animation

Here we use the Cabasicanimation basic animation, keypath the transform.rotation.z that works on the canvas, rotate with the z axis, and the following are the effects diagram and code:

MARK: Animation step
  /**
   rotating animation, rotate two laps
  /private func angleanimation () {let
    angleanimation         = Cabasicanimation.init (keypath: "Transform.rotation.z")
    angleanimation.fromvalue      = Angle ( -30)
    Angleanimation.tovalue       = Angle (690)
    Angleanimation.fillmode      = kcafillmodeforwards
    Angleanimation.removedoncompletion = False
    angleanimation.duration      = Duration
    Angleanimation.delegate      = self
    layer.addanimation (angleanimation, Forkey: "Angleanimation")
  }

The second step of the line is a long shortened animation

Here we still use the Cabasicanimation basic animation, KeyPath action on the line Strokeend properties, so that strokeend from 1 to 0来 to achieve the length of the line animation, the following is the effect map and code:


   The first step of/** line animation, line length from long to
   short
  /private func Lineanimationone () {let
    lineanimationone         = Cabasicanimation.init (keypath: "Strokeend")
    lineanimationone.duration      = DURATION/2
    Lineanimationone.fillmode      = kcafillmodeforwards
    lineanimationone.removedoncompletion = False
    Lineanimationone.fromvalue      = 1
    lineanimationone.tovalue       = 0 for
    i-0...3 {let
      linelayer = Lines[i]
      linelayer.addanimation (Lineanimationone, Forkey: "Lineanimationone")
    }
  

Third Step displacement animation of lines

Here we also use Cabasicanimation basic animation, The KeyPath effect on the transform.translation.x and TRANSFORM.TRANSLATION.Y properties of the line, to achieve the effect of crowding into the middle, the following is the effect diagram and code:

/** Line of the second step of animation, line to intermediate translation/private func lineanimationtwo () {for i in 0...3 {var keypath = "Transform.trans Lation.x "if i%2 = = 1 {keypath =" transform.translation.y "} Let Lineanimationtwo = Cabasicanim Ation.init (keypath:keypath) lineanimationtwo.begintime = cacurrentmediatime () + DURATION/2 LINEANIMATIONTWO.D uration = Duration/4 Lineanimationtwo.fillmode = kcafillmodeforwards lineanimationtwo.removedoncompletion = FA LSE Lineanimationtwo.autoreverses = True Lineanimationtwo.fromvalue = 0 if I < 2 {Lineanimat  Iontwo.tovalue = Linelength/4}else {lineanimationtwo.tovalue =-LINELENGTH/4} let Linelayer =  Lines[i] Linelayer.addanimation (lineanimationtwo, Forkey: "Lineanimationtwo")}//triangle on both sides of the ratio let scale =
      (Linelength-2*margin)/(linelength-linewidth) for I in 0...3 {var keypath = "TRANSFORM.TRANSLATION.Y" if i%2 = = 1 {kEypath = "transform.translation.x"} Let Lineanimationtwo = Cabasicanimation.init (Keypath:keypath) line Animationtwo.begintime = Cacurrentmediatime () + DURATION/2 lineanimationtwo.duration = Duration/4 lineAnimatio  Ntwo.fillmode = Kcafillmodeforwards Lineanimationtwo.removedoncompletion = False lineanimationtwo.autoreverses = True Lineanimationtwo.fromvalue = 0 if i = = 0 | | i = = 3 {lineanimationtwo.tovalue = LINELENGTH/4 * Scale}else {lineanimationtwo.tovalue =-linelen GTH/4 * scale} let Linelayer = Lines[i] Linelayer.addanimation (lineanimationtwo, Forkey: "Lineanimation

 Three ")}}

Fourth Step The original length of the line restore animation

Here we still use the Cabasicanimation basic animation, KeyPath action on the line Strokeend properties, so that strokeend from 0 to one to achieve the length of the animation line, the following is the effect map and code:

/**
   Line of the third animation, line from short to long
  /private func Lineanimationthree () {
    //Line Moving animation let
    lineanimationfour         = Cabasicanimation.init (keypath: "Strokeend")
    lineanimationfour.begintime      = Cacurrentmediatime () + duration
    lineanimationfour.duration      = Duration/4
    lineanimationfour.fillmode      = kcafillmodeforwards
    lineanimationfour.removedoncompletion = False
    Lineanimationfour.fromvalue      = 0
    Lineanimationfour.tovalue       = 1 for
    i in 0...3 {
      if i = = 3 {
        lineanimationfour.delegate = self
      }
   let Linelayer = lines[i]
      linelayer.addanimation (lineanimationfour, Forkey: "Lineanimationfour")
    }
  }

The final step involves combining animations

About the animation mix I didn't use to caanimationgroup, because these animations are not added to the same layer, plus the animation type a bit more and more trouble, I use the animation of the BeginTime properties to control the animation sequence, but also add animation pause and continue the function, The results and code are shown in the following figure:

Mark:public Methods/** Start animation/func startanimation () {angleanimation () Lineanimationone () line
    Animationtwo () Lineanimationthree ()}/** suspend animation * * Func pauseanimation () {layer.pauseanimation () For Linelayer in lines {linelayer.pauseanimation ()} The status =. Pause}/** continue animation/func resume Animation () {layer.resumeanimation () for Linelayer in lines {linelayer.resumeanimation ()} status = . animating} extension Calayer {//Pause animation func pauseanimation () {//Convert current time cacurrentmediatime to layer time, upcoming PARE NT time convert to localtime let Pausetime = ConvertTime (Cacurrentmediatime (), Fromlayer:nil)//Set layer Timeoffset, continue operation
  The ratio of Timeoffset = pausetime//localtime to Parenttime is also used to be 0, meaning localtime is suspended speed = 0;
    //Continue animation func resumeanimation () {Let pausedtime = timeoffset Speed = 1 Timeoffset = 0; BeginTime = 0//Compute pause time Let SincepaUse = ConvertTime (Cacurrentmediatime (), Fromlayer:nil)-pausedtime//local time BeginTime begin relative to parent times Time = Sincepause}}//mark:animation Delegate override func Animationdidstart (anim:caanimation) {if Imation = Anim as? cabasicanimation {if Animation.keypath = = "Transform.rotation.z" {status =. Animating}}} override Func Animationdidstop (anim:caanimation, finished Flag:bool) {if let Animati on = Anim as? cabasicanimation {if Animation.keypath = = "Strokeend" {if flag {status =. Normal Dispatch_after (Dispatch_time (Dispatch_time_now, Int64 (interval) * Int64 (NSEC_PER_SEC)), Dispatch_get_main _queue (), {if Self.status!=. animating {self.startanimation ()}}}}}}}//mark:overrid E override func touchesended (touches:set<uitouch>, withevent event:uievent?) {Switch status {case.} AnImating:pauseanimation () case. Pause:resumeanimation ().

 Normal:startanimation ()}}

Summarize

Animation looks very complex, but carefully divided out also on the matter, in the animation before you want to think about the steps of the animation, this is a key, I hope you can learn something through this blog article, what good suggestions can be raised at any time, thank you for reading ~~demo address

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.