Lottie源碼淺探

Lottie(源碼版本:2.5.4)動畫步驟:

前置知識:

Lottie對動畫的變換主要是通過Matrix實現, 因此需要了解Matrix相關知識,可以參考下面的博客:

https://blog.csdn.net/pathuang68/article/details/6991867

一、動畫Json傳入方法:

Json動畫傳入的方式定義在LottieComposition.Factory中,分別爲:

1.      fromAssetFileName:從assets中加載,參數filename指assets中json的名稱

2.      fromRawFile:從res/raw中加載,參數resId就是raw中json的id

3.      fromInputStream:從InputStream中加載

4.      fromJsonString:從Json字串中加載

5.      fromJsonReader:從JsonReader中加載(如果需要解析的是JsonObject,可以通過new JsonReader(newStringReader(jsonObject))的方式加載,不過這種方式不推薦)

二、解析(Lottie中的解析方法都位於com.airbnb.lottie.parser下):

1.      動畫json傳入後,最終會調用到LottieComposition.Factory.fromJsonReader方法,該方法會將解析事件委託給AsyncCompositionLoader異步線程,而AsyncCompositionLoader會調用LottieComposition.Factory.fromJsonSync方法,該方法調用LottieCompositionParser.parse方法開始進行動畫json的解析,並將解析結果生成LottieComposition。

2.      AsyncCompositionLoader中會調用LottieCompositionParser.parse方法進行具體解析,在LottieCompositionParser.parse方法中:

1)      layers會調用parseLayers,parseLayers調用LayerParser.parse解析

2)      assets會調用parseAssets解析

3)      fonts會調用parseFonts,parseFonts調用FontParser.parse解析

4)      chars會調用parseChars,parseChars調用FontCharacterParser.parse解析

5)      w會解析成width

6)      h會解析成height

7)      ip會解析成startFrame

8)      op會解析成endFrame

9)      fr會解析成frameRate(動畫速率)

10)  v會解析成version(插件版本),進行版本支持性校驗

3.      LottieCompositionParser會根據上面的解析結果生成LottieComposition:

1)      Rect bounds:通過scaledWidth(width與屏幕密度的乘積)、scaledHeight(height與屏幕密度的乘積)確定

2)      startFrame、endFrame、frameRate就是上一步解析的值

3)      layers、layerMap是layers中解析的值

4)      precomps是assets中解析的值

5)      images是assets中解析出的圖片的值

6)      characters是chars中解析的值

7)      fonts是fonts中解析的值

三、Layer具體解析:

LayerParser解析layers中的內容,其中關鍵是ks,ks的內容包含了動畫用到的一些值,ks的解析是通過AnimatableTransformParser.parse方法進行,LayerParser.parse會通過上面解析的數據最終生成Layer:

1)      nm:解析爲layerName

2)      ind:解析爲layerId

3)      refId:解析爲refId

4)      ty:解析爲layerType(附錄1)

5)      parent:解析爲parentId

6)      sw:解析爲solidWidth

7)      sh:解析爲solidHeight

8)      sc:解析爲solidColor

9)      ks:解析爲transform

10)  tt:解析爲mattType

11)  masksProperties:數組,裏面數據會通過MaskParser.parse解析成Mask並存入masks中

12)  shapes:數組,裏面數據會通過ContentModelParser.parse解析成ContentModel並存入shapes中

13)  t:文本,會進一步解析:

(1)    d:通過AnimatableValueParser.parseDocumentData解析成text

(2)    a:通過AnimatableTextPropertiesParser.parse方法解析成textProperties

14)  ef:Lottie中目前不支持這種方式的效果,如果要用,需要將這種效果之直接添加到shape的contents中

15)  sr:解析成timeStretch

16)  st:解析成startFrame

17)  w:解析成preCompWidth

18)  h:解析成preCompHeight

19)  ip:解析成inFrame

20)  op:解析成outFrame

21)  tm:解析成timeRemapping

22)  cl:解析成cl

AnimatableTransformParser解析ks內容,包括”a”(位置信息)、”p”(位移)、”s”(縮放)、”rz”(控制3d圖層,暫時不支持)、”r”、”o”、”so”、”eo”,其實質是解析上面各字段下配置的k的值(解析方法爲KeyframesParser.parse),並根據k的值生成對應的AnimatableValue,而k值用到的幾個主要解析方式是:

1)      PathParser:用於解析k數組,解析成PointF,用於生成AnimatablePathValue。

2)      FloatParser:用於解析k數字,解析成Float,用於生成AnimatableFloatValue。

3)      IntegerParser:用於解析k數字,解析成Integer,用於生成AnimatableIntegerValue。

4)      ScaleXYParser:用於解析k數組,解析成ScaleXY,用於生成AnimatableScaleValue。

AnimatableTransformParser中具體字段解析:

1)      a(位置信息):調用AnimatablePathValueParser.parse解析k中配置的值,並將生成的結果賦值給anchorPoint

2)      p(位移信息):調用AnimatablePathValueParser.parseSplitPath解析,並將解析生成的結果賦值給postion

3)      s(縮放信息):調用AnimatableValueParser.parseScale解析,並將解析結果賦值給scale

4)      rz:3D圖層,不支持

5)      r(翻轉信息):調用AnimatableValueParser.parseFloat解析,並將解析結果賦值給rotation

6)      o(不透明度):調用AnimatableValueParser.parseFloat方法解析,並將解析結果賦值給opacity

7)      so(開始時不透明度):調用AnimatableValueParser.parseFloat方法解析,並將解析結果賦值給startOpacity

8)      eo(結束時不透明度):調用AnimatableValueParser.parseFloat方法解析,並將解析結果賦值給endOpacity

四、AnimatablePathValueParser、AnimatableValueParser重要方法解析:

1.      AnimatablePathValueParser中:

1)      parse:若待解析的JsonReader中的值是數組,將調用PathKeyframeParser.parse方法解析並將解析結果存入keyframes(List<Keyframe<PointF>>)中,之後會調用KeyframesParser.setEndFrames將keyframes中Keyframe的startFrame與endFrame依次串聯起來;若不是數組,就直接調用JsonUtils.jsonToPoint方法,並將解析結果生成的Keyframe存入keyframes中。最後根據keyframes生成AnimatablePathValue。

2)      parseSplitPath:

(1)    k:調用AnimatablePathValueParser.parse解析,並將解析結果賦值給pathAnimation

(2)    x:若JsonReader值爲String,不解析,並將hasExpressions置爲true;若不是String,則調用AnimatableValueParser.parseFloat解析,並將結果返回給xAnimation

(3)    y:若JsonReader值爲String,不解析,並將hasExpressions置爲true;若不是String,則調用AnimatableValueParser.parseFloat解析,並將結果返回給yAnimation

如果pathAnimation不爲空(k直接成功),則直接返回pathAnimation;否則返回通過xAnimation、yAnimation生成的AnimatableSplitDimensPathValue。

2.      AnimatableValueParser中parseFloat、parseInteger、parsePoint等方法中最終會調用parse方法解析,而parse方法則調用KeyframesParser.parse解析,:

1)      parseFloat:調用parse並將FloatParser作爲最終解析方法,解析結果生成AnimatableFloatValue

2)      parseInteger:調用parse並將IntegerParser作爲最終解析方法,解析結果生成AnimatableIntegerValue

3)      parsePoint:調用parse並將PointFParser作爲最終解析方法,解析結果生成AnimatablePointValue

4)      parseScale:調用parse並將ScaleXYParser作爲最終解析方法,解析結果生成AnimatableScaleValue

5)      parseShapeData:調用parse並將ShapeDataParser作爲最終解析方法,解析結果生成AnimatableShapeValue

6)      parseDocumentData:調用parse並將DocumentDataParser作爲最終解析方法,解析結果生成AnimatableTextFrame

7)      parseColor:調用parse並將ColorParser作爲最終解析方法,解析結果生成AnimatableColorValue

8)      parseGradientColor(漸變色):調用parse並將GradientColorParser作爲最終解析方法,解析結果生成AnimatableGradientColorValue

3.      KeyframesParser.parse:

Parse方法中首先會判斷JsonReader值是否爲STRING類型,如果是就直接返回空數據集keyframes(List<Keyframe<T>>),若不是,則解析JsonReader中k中配置的值,k中的值基本是3種類型,分別是數字數組、對象數組、對象:

1)      若k中值爲數組,則判斷數組中元素是否爲數字,若是,則調用KeyframeParser.parse解析整個數組(animated爲false);若不是數字,則調用KeyframeParser.parse依次解析數組中元素(animated爲true)

2)      若k中值不是數組,則調用KeyframeParser.parse解析整個數組(animated爲false)

上面的解析結果都會存入keyframes中,最後會調用setEndFrames方法將keyframes中的Keyframe的startFrame與endFrame串聯,最後將keyframes返回給調用者

4.      KeyframeParser:

1)      parse:判斷傳入的animated值,若爲true,則調用parseKeyframe;否則調用parseStaticValue

2)      parseKeyframe方法是用於解析k中對象數組中的值:

(1)    t:解析成startFrame

(2)    s:調用傳入的最終解析方法解析成stratValue

(3)    e:調用傳入的最終解析方法解析成endValue

(4)    o:調用JsonUtils.jsonToPoint解析成cp1

(5)    i:調用JsonUtils.JsonToPoint解析成cp2

(6)    h:解析成hold(若h值爲1則爲true,否則爲false)

(7)    to:調用JsonUtils.jsonToPoint解析成pathCp1

(8)    ti:調用JsonUtils.jsonToPoint解析成pathCp2

解析完後會對解析的值進行進一步操作:

(1)    若hold爲ture,將endValue設置爲startValue,並將interpolator設置爲LINEAR_INTERPOLATOR;

(2)    若hold爲false,並且cp1與cp2均不爲空,則通過MiscUtils.clamp篩選出合適的cp1、cp2的值,並通過PathInterpolatorCompat.create創建interpolator(其中有PathInterpolator緩存的邏輯,想了解的可以看下)。

(3)    若爲其他情況,則將interpolator設置爲LINEAR_INTERPOLATOR

最後,通過解析的startValue、endValue、startFrame以及創建的interpolator生成Keyframe並返回給調用者

3)      parseStaticValue:調用傳入的最終解析方法解析出value,並根據value生成Keyframe

5.      FloatParser.parse:

調用JsonUtils.valueFromObject解析出float值並將結果與傳入的scale相乘後返回

6.      IntegerParser.parse:

調用調用JsonUtils.valueFromObject解析出float值並將結果與傳入的scale相乘,再通過Math.round取出對應整值並返回

7.      PointFParser.parse:

如果reader中值是NUMBER類型,直接通過JsonReader.nextDouble與scale生成PointF;若reader爲數組或對象,則調用JsonUtils.jsonToPoint方法解析出PointF

8.      ScaleXYParser.parse:

若是數組,就調用JsonReader.beginArray開始解析,否則就直接解析。解析JsonReader中連續的兩個double值,並根據這兩個值與scale生成ScaleXY

9.      ShapeDataParser.parse:

(1)    c:解析成closed

(2)    v:調用JsonUitls.jsonToPoints方法解析成pointsArray

(3)    i:調用JsonUtils.jsonToPoints方法解析成inTangents

(4)    o:調用JsonUtils.jsonToPoints方法解析成outTangents

若解析的pointsArray爲空,就構建空的ShapeData

若pointsArray不爲空,則先取出pointsArray中第一個值,將其設置爲initialPoint。然後從第二個值開始循環pointsArray中的值,在for循環中,根據pointsArray中當前的值與inTangents中當前值生成shapeCp1,pointsArray中前一個值與outTangents中前一個值生成shapeCp2,然後通過shapeCp1與shapeCp2以及pointsArray當前值生成CubicCurveData並加入curves中。

然後判斷closed的值,如果closed爲true(標誌這個Shape是封閉圖形),則將pointsArray第一值作爲當前值,最後一個值作爲前一個值,進行上一步for循環中的操作,並將生成的CubicCurveData也填入curves中。

最後根據initialPoint、closed、curves生成ShapeData。

10.  DocumentDataParser.parse:

(1)    t:解析成text

(2)    f:解析成fontName

(3)    s:解析成size

(4)    j:解析成justification

(5)    tr:解析成tracking

(6)    lh:解析成lineHeight

(7)    ls:解析成baselineShift

(8)    fc:調用JsonUtils.jsonToColor解析成fillColor

(9)    sc:調用JsonUtils.jsonToColor解析成strokeColor

(10) sw:解析成strokeWidth

(11) of:解析成strokeOverFill

最後通過上面解析的值生成DocumentData

11.  ColorParser.parse:

若是數組,調用JsonReader.beginArray開始解析,否則直接解析。取JsonReader中連續的4個double值,分別解析成r、g、b、a,若這四個值都小於,則說明它們被配置成色值的比例,將它們分別乘以255,最後調用Color.argb生成顏色值(int類型)

12.  GradientColorParser.parse:

若爲數組,則調用reader.beginArray開始解析,否則直接解析。將JsonReader中全部的double值解析出並存入array中,然後將array中的數據每4個進行循環,這四個值中第一個存入positions,第二、三、四分別爲r、g、b值,通過r、g、b生成color值後存入colors,之後通過positions、colors值生成gradientColor並通過addOpacityStopsToGradientIfNeeded設置透明度(透明度是存放在顏色值的後面,不被4整除的部分),最後將gradientColor返回給調用者

13.  JsonUtils:

1)      jsonToColor:取出傳入的JsonReader中連續的3個double值,分別設置爲r、g、b,然後調用Color.argb方法生成顏色值

2)      jsonToPoints:若是數組,循環數組中的值,調用jsonToPoint解析出PointF並存入points,最後將points返回

3)      jsonToPoint:

(1)    若傳入的JsonReader爲數字,調用jsonNumbersToPoint並返回

(2)    若傳入的JsonReader爲數組,調用jsonArrayToPoint並返回

(3)    若傳入的JsonReader爲對象,調用jsonObjectToPoint並返回

4)      jsonNumbersToPoint:

取出JsonReader連續的兩個double值,分別置成x、y,通過x、y、scale生成PointF

5)      jsonArrayToPoint:

取出數組中連續的兩個double值,分別置成x、y,通過x、y、scale生成PointF

6)      jsonObjectToPoint:

取出對象中的x值置爲x,對象中的y值置爲y,通過x、y、scale生成PointF

7)      valueFromObject:

若傳入的JsonReader爲數字,返回第一個double值;若是數組,返回數組中第一個值。

五、Shape解析(layers中的shapes):

LayerParser會調用ContentModelParser.parse將shapes數組依次解析成ContentModel並存入shapes中。

ContentModleParser.parse首先會解析ty,之後根據ty解析成不同的ContentModel(附錄2)。

1.      gr:調用ShapeGroupParser.parse解析成ShapeGroup,這個是Shape組,裏面會包含各種子Shape。

ShapeGroupParser中會調用ContentModelParser.parse將it數組中的內容依次解析成ContentModel,並存入items中。

2.      st:調用ShapeStrokeParser.parse解析成ShapeStroke,Shape線條的信息。

ShapeStrokeParser.parse中會解析如下字段:

1)      nm:name

2)      c:color,調用AnimatableValueParser.parseColor解析

3)      w:width,調用AnimatableValueParser.parseFloat解析

4)      o:opacity,調用AnimatableValueParser.parseInteger解析

5)      lc:capType,ShapeStroke.LineCapType類型(附錄3)

6)      lj:joinType,ShapeStroke.LineJoinType類型(附錄4)

7)      d:數組,首先會解析n、v(v會解析成val):

(1)    n爲o,將val賦值給offset

(2)    n爲d或g,將val添加到lineDashPattern中

解析完,如果lineDashPattern的個數如果是1,就將該數據再加入lineDashPattern一次

                   最後會根據上面解析出的值生成ShapeStroke

3.      gs:調用GradientStrokeParser.parse解析成GradientStroke

1)      nm:name

2)      o:opacity

3)      t:gradientType,漸變類型(GradientType.Linear或GradientTypeRadial)

4)      s:startPoint

5)      e:endPoint

6)      w:width

7)      lc:capType

8)      lj:joinType

9)      d:lineDashPattern或offset

10)  g:會進一步解析g中的字段

(1)    p:points

(2)    k:color,調用AnimatableValueParser.parseGradientColor並傳入points解析

最後根據解析的值生成GradientStroke

4.      fl:調用ShapeFillParser.parse解析成ShapeFill

1)      nm:name

2)      c:color

3)      o:opacity

4)      fillEnabled:fillEnabled,boolean類型

5)      r:fillTypeInt,int類型,之後會根據fillTypeInt的值設置fillType

最後根據解析的值生成ShapeFill

5.      gf:調用GradientFillParser.parse解析成GradientFill

1)      nm:name

2)      g:color,AnimatableGradientColorValue類型

3)      o:opacity

4)      t:gradientType

5)      s:startPoint

6)      e:endPoint

7)      r:fillType

6.      tr:調用AnimatableTransFormParser.parse解析成AnimatableTransform

7.      sh:調用ShapePathParser.parse解析成ShapePath,Shape的繪製路徑

1)      nm:name

2)      ind:ind

3)      ks:shape,調用AnimatableValueParser.parseShapeData解析

8.      el:調用CircleShapeParser.parse解析成CirCleShape

1)      nm:name

2)      p:position

3)      s:size

4)      d:reversed,boolean類型,通過d的值是否爲3確定

9.      rc:調用RectangleShapeParser.parse解析成RectangleShape

1)      nm:name

2)      p:position

3)      s:size

4)      r:roundedness,調用AnimatableValueParser.parseFloat解析

10.  tm:調用ShapeTrimPathParser.parse解析成ShapeTrimPath

1)      s:start,AnimatableValueParser.parseFloat解析

2)      e:end,AnimatableValueParser.parseFloat解析

3)      o:offset,AnimatableValueParser.parseFloat解析

4)      nm:name

5)      m:type,ShapeTrimPath.Type類型,附錄5

11.  sr:調用PolystarShapeParser.parse解析成PolystarShape

1)      nm:name

2)      sy:type,PolystarShape.Type,附錄6

3)      pt:points

4)      p:position

5)      r:totation

6)      or:outerRadius,AnimatableValueParser.parseFloat解析

7)      os:outerRoundedness,AnimatableValueParser.parseFloat解析

8)      ir:innerRadius,AnimatableValueParser.parseFloat解析

9)      is:innerRoundedness,AnimatableValueParser.parseFloat解析

12.  mm:調用MergePathParser.parse解析成MergePath,只支持KitKat及之後的版本

1)      nm:name

2)      mode:mode,MergePaths.MergePathsMode類型,附錄7

13.  rp:調用RepeaterParser.parse解析成Repeater

1)      nm:name

2)      c:copies,AnimatableValueParser.parseFloat解析

3)      o:offset,AnimatableValueParser.parseFloat解析

4)      tr:transform

六、Assets解析(assets):

LottieCompositionParser中調用parseAssets方法解析assets中的內容。assets中內容分兩類,一類是圖層信息,一類是圖片信息:

1.      圖層信息:

圖層信息解析出的內容存放在precomps中,主要解析id與layers的內容。

assets中的layers與外層的layers一樣是調用LayerParser.parse解析

2.      圖片信息(解析出的值會生成LottieImageAsset並存入images中):

1)      id:解析成id

2)      w:解析成width

3)      h:解析成height

4)      u:解析成relativeFolder

5)      p:解析成imageFileName

七、LottieDrawable構建:

動畫json解析完成後,會生成LottieComposition,onCompositionLoaded方法中將LottieComposition設置給LottieDrawable。

LottieDrawable的setComposition方法會通過buildCompositionLayer、animator.setComposition、setScale、updateBounds、等方法重新構建LottieDrawable

buildCompositionLayer會重新構建LottieDrawable中的CompositionLayer。

animator.setComposition會重置animator(LottieValueAnimator)minFrame、maxFrame、frame與lastFrameTimeNs的信息,minFrame會取原minFrame與composition的startFrame(json中的ip值)中的最大值,maxFrame會取原maxFrame與composition的endFrame(json中的op值)中的最小值,frame會通過一系列比較獲取。

八、CompositionLayer構建:

CompositionLayer中存儲了動畫的所有層級的信息。

它在LottieDrawable中構建

compositionLayer = new CompositionLayer(this,LayerParser.parse(composition), composition.getLayers(), composition);

LayerParser.parse(composition)構建了最外層的Layer,高和寬是json最外層的h、w的值。

composition.getLayers()獲取的是json最外層layers中的內容。

CompositionLayer的構造方法會遍歷傳入的composition.getLayers中的Layer,並將Layer通過BaseLayer.forModel方法,根據layerType生成不同的BaseLayer,對應關係如下表:

layerType

BaseLayer子類

備註

Shape(ty=4)

ShapeLayer

 

PreComp(ty =0)

CompositionLayer

也就是Assets中的內容

Solid(ty=1)

SolidLayer

 

Image(ty=2)

ImageLayer

 

Null(ty=3)

NullLayer

 

Text(ty=5)

TextLayer

 

Unknown/default

null

 

生成的BaseLayer會存入layerMap。

之後會根據前一個BaseLayer的matteType(配置文件中的tt)值判斷是否爲mattedLayer,若是MattedLayer就將當前的BaseLayer設置爲前一個BaseLayer的MatteLayer,否則就添加到layers最前的位置。下表標識該layer是否爲MattedLayer

matteType

是否爲MattedLayer

 

Add/Invert(tt=1或2)

 

其他情況

 

最後會遍歷layerMap,找到每一個BaseLayer的parentLayer(根據BaseLayer的parentId查找,parentId對應於json中的parent),並設置到該BaseLayer中。

九、繪製:

Json解析完成後,會調用setComposition方法,該方法中會重新設置LottieComposition,並調用LottieDrawable.setComposition方法刷新LottieDrawable。

上面步驟完成後會調用setImageDrawable、requestLayout方法重繪LottieAnimationView。

LottieAnimationView的onDraw方法會調用LottieDrawable的draw方法(詳細步驟需要查看ImageView的繪製流程)。下面具體分析下LottieDrawable的draw流程。

首先會確定動畫的scale,scale是通過動畫外層的width與height與canvas的比例確定,取高、寬比例中較小的值。若scale後的動畫大於canvas,會調用canvas的translate、scale方法重置canvas。然後會將獲取的scale填入矩陣matrix。

之後會調用BaseLayer.draw方法繪製動畫中的全部Layer,具體步驟如下:

BaseLayer.draw()方法中有三個參數,分別是canvas(畫布)、parentMatrix(最外層動畫Matrix)、parentAlpha(最外層透明度)。

1.      調用buildParentLayerListIfNeeded方法構建出CompositionLayer的全部parentLayer並添加到parentLayers中。

2.      會將parentMatrix設置爲matrix,並將parentLayers中的Layer動畫Matrix與傳入的matrix相乘。

3.      然後,根據傳入的parentAlpha與該BaseLayer的transform的opacity屬性(即json中{“layers”:[{“ks” : {“o”: {…}}}]}中從o中解析出來的值,一般就是o中k的值)計算出透明度

4.      如果該BaseLayer沒有matteLayer與mask,就將canvas、matrix、alpha傳入drawLayer方法進一步繪製,LottieDrawalbe中調用的是CompositionLayer的drawLayer方法

十、CompositionLayer繪製:

1.      CompositionLayer的drawLayer中首先保存canvas狀態, 然後通過構建時生成的Layer的寬、高(具體分析見CompositionLayer構建)設置到newClipRect(RectF類型),然後將newClipRect按上步傳入的parentMatrix進行變換。

2.      之後,會循環CompositionLayer中的layers(見CompositionLayer的構建),並調用對應BaseLayer的draw方法將所有layer依次繪製出來,同時,會按照newClipRect重新裁剪canva(這段代碼可能會造成動畫顯示不全)。最後,將canvas設置回之前的狀態

十一、      ShapeLayer構建:

CompostionLayer構造方法中遍歷解析出的layers(見三),通過BaseLayer.forModel根據生成對應的BaseLayer。

ShapeLayer對應的type爲4,BaseLayer.forModel直接調用ShapeLayer構造函數生成ShapeLayer。

 ShapeLayer構造函數首先通過Layer中的shapes(List<ContentModel>)構建shapeGroup,然後通過shapeGroup構建出contentGroup。(lottie文件中也可能會配置ShapeGroup即”gr”。之後會調用ContentGroup的setContents,setContents會循環ContentGroup中的contents,並調用Content.setContents方法將其前後的contents傳入。

ContentGroup構造方法中:

1.      通過contentsFromModels方法將Layer中的shapes(即List<ContentModel>)通過toContent方法全部轉換成對應的Content(附錄2),並存入contents中

2.      通過findTransform方法取出該ShapeLayer對應的AnimatableTransform(”tr”),然後通過AnimatableTransform生成TransformKeyframeAnimation賦值給transformAnimation

3.      找出contents中全部的GreedyContent子類存入greedyContents中,並對greedyContents進行進一步操作。

十二、      ShapeLayer繪製:

ShapeLayer的drawLayer會委託給contentGroup.draw方法進行。contentGroup.draw中首先會處理動畫與透明度,之後遍歷構造時生成的contents,調用其中DrawingContent的子類的draw進行實際的繪製。

DrawingContent子類見附錄2

DrawingConteng實際上有3種:

1.      畫線圖(StrokeContentGradientStrokeContent):

StrokeContent與GradientStrokeContent的區別是線條的顏色是否爲漸變色。

2.      畫填充圖(FillContentGradientFillContent):

FillContent與GradientFillContent的區別是填充色是否爲漸變色。

3.      畫需要重複的圖(RepeaterContent):

十三、      StrokeContent構建與繪製:

StrokeContent是BaseStrokeContent的子類,大部分邏輯都在BaseStrokeContent中,以下是BaseStrokeContent的分析:

1.      構造函數:

構造函數中主要是完成的Paint以及Animation的初始化。

2.      setContents:

setContents會遍歷與其同處一個ContentGroup下的其他Content,找出其中的TrimPathContent與其對應的全部PathContent,然後生成PathGroup並存入pathGroups中

3.      draw:

1)      通過配置中的width、color、alpha對paint進行設置。

2)      遍歷pathGroups,對每一個PathGroup分情況處理:

(1)    若pathGroup中trimPath不爲空,則調用applyTrimPath方法,applyTrimPath方法中會通過PathMeasure根據TrimPathContent對PathContent構成的Path進行處理。

PathMeasure用法可以參考:

https://blog.csdn.net/u013831257/article/details/51565591

(2)    若pathGroup中trimPath爲空,直接通過canvas.drawPath繪製PathContent構成的Path

十四、      動畫過程:

Lottie動畫過程是通過LottieValueAnimator進行控制,animator中會維護兩個容器,一個存放向Lottie中註冊的全部ValueAnimator.AnimatorUpdateListener,一個存放向Lottie中註冊的全部AnimatorListener。

ValueAnimator.AnimatorUpdateListener用於動畫更新的監聽,回調接口是onAnimationUpdate。

AnimatorListener用於動畫開始、結束、取消、重複等監聽。

LottieDrawable構建的時候會向animator註冊一個AnimatorUpdateListener的監聽,這個監聽會收到animator發送的動畫更新的回調,在此回調中調用compositionLayer設置progress實現動畫的更新。

十五、      附錄:

1.      LayerType含義:

LayerType對應於json文件layers中的ty字段,映射關係如下:

ty

 

LayerType

含義

0

 

PreComp

 

1

 

Solid

 

2

 

Image

圖片

3

 

Null

 

4

 

Shape

繪製形狀

5

 

Text

文字

6

 

Unknown

 

 

2.      ContentModel(shape)中type含義,標黃的是DrawingConent的子類:

ty

ContentModel

toContent類型

備註

gr

ShapeGroup

ContentGroup

Shape組,裏面包含子Shape

st

ShapeStroke

StrokeContent

Shape描邊信息,如線的顏色、寬度、透明度等

gs

GradientStroke

GradientStrokeContent

 

fl

ShapeFill

FillContent

 

gf

GradientFill

GradientFillContent

 

tr

AnimatableTransform

null

Shape的動畫

sh

ShapePath

ShapeContent

Shape的繪製路徑

el

CircleShape

EllipseContent

 

rc

RectangleShape

RectangleContent

 

tm

ShapeTrimPath

TrimPathContent

修剪路徑

sr

PolystarShape

PolystarContent

 

mm

MergePaths

MergePathsContent

 

rp

Repeater

RepeaterContent

 

 

3.      ShapeStroke.LineCapType類型:

index

ShapeStroke.LineCapType類型

Paint.Cap(線帽子)

0

LineCapType.Butt

Paint.Cap.BUTT 無線帽

1

LineCapType.Round

Paint.Cap.ROUND 圓線帽

2

LineCapType.Unknown

Paint.Cap.SQUARE 方線帽

 

4.      ShapeStroke.LineJoinType類型:

index

ShapeStroke.LineJoinType類型

Paint.Join(線段連接樣式)

0

Miter

Paint.Join.MITER 銳角連接

1

Round

Paint.Join.ROUND 圓弧連接

2

Bevel

Paint.Join.BEVEL 斜接

 

5.      ShapeTrimPath.Type類型:

id

ShapeTrimPath.Type類型

備註

1

Simultaneously

 

2

Individually

 

 

6.      PolystarShape.Type類型:

value

PolystarShape.Type類型

備註

1

Star

 

2

Polygon

 

                  

7.      MergePaths.MergePathsMode類型:

id

MergePaths.MergePathsMode

備註

1

Merge

 

2

Add

 

3

Subtract

 

4

Intersect

 

5

ExcludeIntersections

 

 

8.       



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章