Skip to content

Commit

Permalink
Now it's time to move to Lottie 3.4, which solve the performance issue
Browse files Browse the repository at this point in the history
Pick back the code, and implements the bitmap frame extract using the new API
  • Loading branch information
dreampiggy committed Jul 8, 2022
1 parent 0e230d8 commit 7f1b50c
Show file tree
Hide file tree
Showing 34 changed files with 530 additions and 1,250 deletions.
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cartfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github "SDWebImage/SDWebImage" ~> 5.10
github "airbnb/lottie-ios" ~> 2.5
github "airbnb/lottie-ios" ~> 3.4
4 changes: 2 additions & 2 deletions Cartfile.resolved
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
github "SDWebImage/SDWebImage" "5.5.2"
github "airbnb/lottie-ios" "2.5.3"
github "SDWebImage/SDWebImage" "5.13.0"
github "airbnb/lottie-ios" "3.4.0"
14 changes: 7 additions & 7 deletions Example/SDWebImageLottiePlugin Example macOS/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//
// AppDelegate.swift
// SDWebImageLottiePlugin_Example macOS
//
// Created by 李卓立 on 2020/2/29.
// Copyright © 2020 CocoaPods. All rights reserved.
//
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import Cocoa

Expand Down
36 changes: 17 additions & 19 deletions Example/SDWebImageLottiePlugin Example macOS/ViewController.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
//
// ViewController.swift
// SDWebImageLottiePlugin_Example macOS
//
// Created by 李卓立 on 2020/2/29.
// Copyright © 2020 CocoaPods. All rights reserved.
//
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import Cocoa
import Lottie
import SDWebImageLottiePlugin

class ViewController: NSViewController {

let animationView = LOTAnimationView()
let animationView = AnimationView()

override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -22,17 +22,15 @@ class ViewController: NSViewController {
view.addSubview(animationView)

let lottieUrl = URL(string: "https://raw.githubusercontent.com/airbnb/lottie-web/master/demo/adrock/data.json")
animationView.sd_setImage(with: lottieUrl) { (image, error, cacheType, url) in
self.animationView.play(fromProgress: 0,
toProgress: 1,
withCompletion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
}
animationView.sd_setImage(with: lottieUrl, completed: { _,_,_,_ in
self.animationView.play(fromProgress: 0, toProgress: 1, loopMode: .repeat(5)) { finished in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
}
})
}

}
Expand Down
2 changes: 2 additions & 0 deletions Example/SDWebImageLottiePlugin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -781,6 +782,7 @@
"$(inherited)",
);
INFOPLIST_FILE = Tests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
1 change: 1 addition & 0 deletions Example/SDWebImageLottiePlugin/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import UIKit
import Lottie

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
Expand Down
27 changes: 13 additions & 14 deletions Example/SDWebImageLottiePlugin/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import UIKit
import Lottie
import SDWebImageLottiePlugin
import SDWebImage

class ViewController: UIViewController {

let animationView = LOTAnimationView()

let animationView = AnimationView()
override func viewDidLoad() {
super.viewDidLoad()
animationView.contentMode = .scaleAspectFit
Expand All @@ -22,18 +23,16 @@ class ViewController: UIViewController {
view.addSubview(animationView)

let lottieUrl = URL(string: "https://raw.githubusercontent.com/airbnb/lottie-web/master/demo/gatin/data.json")
animationView.sd_setImage(with: lottieUrl) { (image, error, cacheType, url) in
self.animationView.play(fromProgress: 0,
toProgress: 1,
withCompletion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
}
animationView.sd_setImage(with: lottieUrl, completed: { _,_,_,_ in
self.animationView.play(fromProgress: 0, toProgress: 1, loopMode: .repeat(5)) { finished in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
}
})
}

}

36 changes: 12 additions & 24 deletions Example/Tests/Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,44 +37,32 @@ class Tests: XCTestCase {

func testAnimatedImageViewLoad() {
let exception = self.expectation(description: "AnimationView load lottie URL")
let animationView = LOTAnimationView()
let animationView = AnimationView()
let lottieURL = URL(string: "https://raw.githubusercontent.com/airbnb/lottie-web/master/demo/happy2016/data.json")
animationView.sd_setImage(with: lottieURL) { (image, error, cacheType, url) in
animationView.sd_setImage(with: lottieURL, completed: { (image, error, cacheType, url) in
XCTAssertNil(error)
let lottieImage = try! XCTUnwrap(image)
XCTAssertTrue(lottieImage.isKind(of: LOTAnimatedImage.self))
let animation = try! XCTUnwrap((lottieImage as! LOTAnimatedImage).composition)
XCTAssertEqual(animation.compBounds.size, CGSize(width: 1920, height: 1080))
XCTAssertTrue(lottieImage.isKind(of: LottieImage.self))
let animation = try! XCTUnwrap((lottieImage as! LottieImage).animation)
XCTAssertEqual(animation.size, CGSize(width: 1920, height: 1080))
exception.fulfill()
}
})
self.waitForExpectations(timeout: 5, handler: nil)
}

func testAnimatedControlLoad() {
let exception = self.expectation(description: "AnimatedControl load lottie URL")
let animationView = LOTAnimatedSwitch()
let animationView = AnimatedSwitch()
let lottieURL = URL(string: "https://raw.githubusercontent.com/airbnb/lottie-web/master/demo/adrock/data.json")
animationView.sd_setImage(with: lottieURL) { (image, error, cacheType, url) in
animationView.sd_setImage(with: lottieURL, completed: { (image, error, cacheType, url) in
XCTAssertNil(error)
let lottieImage = try! XCTUnwrap(image)
XCTAssertTrue(lottieImage.isKind(of: LOTAnimatedImage.self))
let animation = try! XCTUnwrap((lottieImage as! LOTAnimatedImage).composition)
XCTAssertEqual(animation.compBounds.size, CGSize(width: 690, height: 913))
XCTAssertTrue(lottieImage.isKind(of: LottieImage.self))
let animation = try! XCTUnwrap((lottieImage as! LottieImage).animation)
XCTAssertEqual(animation.size, CGSize(width: 690, height: 913))
exception.fulfill()
}
})
self.waitForExpectations(timeout: 5, handler: nil)
}

func testLottieImageWithBundle() throws {
let bundle = Bundle(for: type(of: self))
let fileURL = bundle.url(forResource: "Assets", withExtension: "json")!
let lottieData = try Data(contentsOf: fileURL)
let context = [SDWebImageContextOption.lottieBundle : bundle]
let lottieImage = LOTAnimatedImage(data: lottieData, scale: 1, options: [.webImageContext: context])!
let posterFrame = try XCTUnwrap(lottieImage.animatedImageFrame(at: 0))
// Pick the color to check
let color = try XCTUnwrap(posterFrame.sd_color(at: CGPoint(x: 150, y: 150)))
XCTAssertEqual(color.toHexString(), "#00d1c1");
}

}
25 changes: 25 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"object": {
"pins": [
{
"package": "Lottie",
"repositoryURL": "https://github.com/airbnb/lottie-ios.git",
"state": {
"branch": null,
"revision": "246bab7ef72bad56abefb88e84a08871cecf9cb8",
"version": "3.4.0"
}
},
{
"package": "SDWebImage",
"repositoryURL": "https://github.com/SDWebImage/SDWebImage.git",
"state": {
"branch": null,
"revision": "c4b8660bb3ef543fe4bdcaac0db956b32dc5583f",
"version": "5.13.0"
}
}
]
},
"version": 1
}
36 changes: 36 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// swift-tools-version:5.1
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "SDWebImageLottiePlugin",
platforms: [
.iOS(.v11),
.tvOS(.v11),
.macOS(.v10_11)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "SDWebImageLottiePlugin",
targets: ["SDWebImageLottiePlugin"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.10.0"),
.package(url: "https://github.com/airbnb/lottie-ios.git", from: "3.4.0")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "SDWebImageLottiePlugin",
dependencies: ["SDWebImage", "Lottie"],
path: ".",
sources: ["SDWebImageLottiePlugin/Classes"],
publicHeadersPath: "SDWebImageLottiePlugin/Classes"
)
]
)
40 changes: 11 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ You can find more resource about Lottie in their [Official Site](https://airbnb.

## Requirements

+ iOS 9+
+ iOS 11+
+ macOS 10.11+
+ tvOS 9+
+ tvOS 11+
+ Xcode 11+

## Installation
Expand All @@ -38,30 +38,22 @@ SDWebImageLottiePlugin is available through [Carthage](https://github.com/Cartha
github "SDWebImage/SDWebImageLottiePlugin"
```

## Lottie 2 && 3
## Lottie 2 && Objective-C

Although Lottie already release 3.x with the full Swift-rewritten code, however, during the performance testing of demo project, the Lottie 3 render performance is 60% slower than Lottie 2, many animation can not render as 60 FPS, while Lottie 2 did. See compare result at [here](https://github.com/SDWebImage/SDWebImageLottiePlugin/issues/1).
Lottie 3.4 version's new `Lottie.RenderingEngine = .coreAnimation` solve the huge performance regression in the issue [here](https://github.com/airbnb/lottie-ios/issues/895) 🚀

So, to provide better performance on user, this plugin was written to support Lottie 2 currently, until Lottie community fix the performance problem. Track the issue [here](https://github.com/airbnb/lottie-ios/issues/895).
So from SDWebImageLottiePlugin v1.0.0, we drop the Lottie 2 support, as well as the Objective-C support because Lottie 3 use the pure Swift.

If you really want Lottie 3 support, please checkout [1.x branch](https://github.com/SDWebImage/SDWebImageLottiePlugin/tree/1.x), which provide the Lottie 3 and fully written in Swift. Once Lottie 3 fix the performance issue, we will upgrade this plugin's major version to 1.0 and release with Lottie 3 support.
For user who still use Lottie 2 and Objective-C, please check the 0.x version updated to [0.3.0](https://github.com/SDWebImage/SDWebImageLottiePlugin/releases/tag/0.3.0)

## Usage

### Load Lottie from remote JSON

+ Objective-C

```objective-c
LOTAnimationView *animationView;
NSURL *lottieJSONURL;
[animationView sd_setImageWithURL:lottieJSONURL];
```
+ Swift

```swift
let animationView: LOTAnimationView
let animationView: Lottie.AnimationView
let lottieJSONURL: URL
animationView.sd_setImage(with: lottieJSONURL)
```
Expand All @@ -73,30 +65,20 @@ Note:

### Advanced usage

This Lottie plugin use a wrapper class `LOTAnimatedImage` because of SDWebImage's [customization architecture design](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#customization). Typically you should not care about this, however this can allows some advanced usage.

+ Objective-C

```objective-c
LOTComposition *composition = [LOTComposition animationFromJSON:jsonDict];
LOTAnimatedImage *animatedImage = [[LOTAnimatedImage alloc] initWithComposition:composition];
// Snapshot Lottie animation frame
UIImage *posterFrame = [animatedImage animatedImageAtIndex:0];
NSTimeInterval duration = [animatedImage animatedImageDurationAtIndex: 0];
```
This Lottie plugin use a wrapper class `LottieImage` because of SDWebImage's [customization architecture design](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#customization). Typically you should not care about this, however this can allows some advanced usage.

+ Swift

```swift
let composition = LOTComposition(json: jsonDict)
let animatedImage = LOTAnimatedImage(composition: composition)
let animation = try? JSONDecoder().decode(Animation.self, from: data)
let animatedImage = LottieImage(animation: animation)
// Snapshot Lottie animation frame
UIImage *posterFrame = animatedImage.animatedImageFrame(at: 0)
TimeInterval duration = animatedImage.animatedImageDuration(at: 0)
```

Note:
+ The snapshot is a bitmap version and used for special cases, like thumbnail poster. You'd better not play it on SDAnimatedImageView. Because Lottie is a vector animation and LOTAnimationView use Core Animation for rendering, which is faster.
+ The snapshot is a bitmap version and used for special cases, like thumbnail poster. You'd better not play it on `SDAnimatedImageView`. Because Lottie is a vector animation and `Lottie.AnimationView` use Core Animation for rendering, which is faster.

## Demo

Expand Down
6 changes: 3 additions & 3 deletions SDWebImageLottiePlugin.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ SDWebImageLottiePlugin is a plugin for SDWebImage framework, which provide the L
s.author = { 'DreamPiggy' => 'lizhuoli1126@126.com' }
s.source = { :git => 'https://github.com/SDWebImage/SDWebImageLottiePlugin.git', :tag => s.version.to_s }

s.ios.deployment_target = '9.0'
s.ios.deployment_target = '11.0'
s.osx.deployment_target = '10.11'
s.tvos.deployment_target = '9.0'
s.tvos.deployment_target = '11.0'

s.source_files = 'SDWebImageLottiePlugin/Classes/**/*', 'SDWebImageLottiePlugin/Module/SDWebImageLottiePlugin.h'

Expand All @@ -32,5 +32,5 @@ SDWebImageLottiePlugin is a plugin for SDWebImage framework, which provide the L
}

s.dependency 'SDWebImage', '~> 5.10'
s.dependency 'lottie-ios', '~> 2.5'
s.dependency 'lottie-ios', '~> 3.4'
end
Loading

0 comments on commit 7f1b50c

Please # to comment.