Open markjeschke opened 7 years ago
If you're curious, here's my JsonDataExtractor class:
import UIKit
class JsonDataExtractor: KFVector {
func loadVectorFromDisk(assetName:String) throws -> KFVector {
let filePath : String = Bundle(for: type(of: self)).path(forResource: assetName, ofType: "json")!
let data : Data = try String(contentsOfFile: filePath).data(using: .utf8)!
let vectorDictionary : Dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
return KFVectorFromDictionary(vectorDictionary)
}
}
Hi @markjeschke,
I would do pretty much the same as you did. Maybe encapsulate do catch
into your extractor too?
or have a func keyframesLayerFromAsset(assetName:String) -> KFVectorLayer
if those layers share the same setup such as frame
, repeatCount
etc.
All steps are required though.
Thanks for your help. How would you encapsulate the do
catch
into the extractor? It would be great if that could also be included in the keyFramesLayerFromAsset
function that you proposed.
For instance, if I added a new animation via a UIButton action, couldn't a single method call could create an object that handles the KFVector, the JSON File path, and the KFVectorLayers, all in one declaration with tuples or instanceType arguments? I'm sorry if this is trivial.
Thanks in advance, Mark
I finally came up with a solution, based upon @LazyChild's recommendations. I still need to optimize the code's functionality into separate classes or extensions and remove the print statements. But, I'm hoping that it will help others. Any advice on making the code more efficient is welcome. Here's the ViewController:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let shortSide = min(self.view.bounds.width, self.view.bounds.height)
let longSide = max(self.view.bounds.width, self.view.bounds.height)
// ===== Top Animation
let topKeyframeVector = keyframesLayerFromAsset(assetName: "sample_logo",
repeatCount: 2,
x: shortSide / 4 + 25,
y: 20,
width: 100,
height: 100)
// Add the animation layer to the view.
self.view.layer.addSublayer(topKeyframeVector)
topKeyframeVector.startAnimation()
// ===== Middle Animation
let sVector = keyframesLayerFromAsset(assetName: "keyframes",
repeatCount: 3,
x: shortSide / 4,
y: longSide / 2 - shortSide / 4,
width: shortSide / 2,
height: shortSide / 2)
// Add the animation layer to the view.
self.view.layer.addSublayer(sVector)
sVector.startAnimation()
// ===== Bottom Animation
let bottomKeyframeVector = keyframesLayerFromAsset(assetName: "sample_logo",
repeatCount: 1,
x: shortSide / 4 + 20,
y: longSide - 140,
width: 120,
height: 120)
// Add the animation layer to the view.
self.view.layer.addSublayer(bottomKeyframeVector)
bottomKeyframeVector.startAnimation()
}
// ===== Extract JSON data
func loadVectorFromDisk(assetName:String) throws -> KFVector {
let filePath : String = Bundle(for: type(of: self)).path(forResource: assetName, ofType: "json")!
let data : Data = try String(contentsOfFile: filePath).data(using: .utf8)!
let vectorDictionary : Dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:Any]
return KFVectorFromDictionary(vectorDictionary)
}
// ===== Call the animation layer and pass in parameters
func keyframesLayerFromAsset(assetName: String,
repeatCount: Float,
x: CGFloat,
y: CGFloat,
width: CGFloat,
height: CGFloat) -> KFVectorLayer {
var myVector : KFVector!
do {
myVector = try loadVectorFromDisk(assetName: assetName)
print("assetName: \(assetName)")
} catch {
print("Vector file could not be loaded, aborting")
}
let myVectorLayer = KFVectorLayer()
myVectorLayer.frame = CGRect(x: x, y: y, width: width, height: height)
// For some reason setting a repeatCount = 0 doesn't work on its own.
if repeatCount != 0 {
myVectorLayer.repeatCount = repeatCount
}
myVectorLayer.faceModel = myVector!
print("repeatCount: \(repeatCount)\n-----")
return myVectorLayer
}
}
@lozzle Please feel free to close this issue if it shouldn't be in the Issues section. :)
Below is my code for instantiating three KFVectorLayer animations, which you can check out in my Keyframes-Test repo. There must be a more efficient way to do this dynamically, and with fewer lines of code, right?