如何为拼接图像制作动画?
How to animate a stitched image?
我不知道如何制作这个动画。你会以某种方式将 1 jpg
文件平均分成 3 部分并制作动画吗?还是您必须制作 jpg
的多个副本并对其进行处理?
任何帮助都会很棒!
更新
由于您想要交叉淡入淡出,将图像拆分为单独的 cel 图像可能是最简单的方法:
import UIKit
import PlaygroundSupport
extension UIImage {
func subImage(inUnitRect unitRect: CGRect) -> UIImage? {
guard imageOrientation == .up, let cgImage = self.cgImage else { return nil }
let cgImageWidth = CGFloat(cgImage.width)
let cgImageHeight = CGFloat(cgImage.height)
let scaledRect = CGRect(x: unitRect.origin.x * cgImageWidth, y: unitRect.origin.y * cgImageHeight, width: unitRect.size.width * cgImageWidth, height: unitRect.size.height * cgImageHeight)
guard let croppedCgImage = cgImage.cropping(to: scaledRect) else { return nil }
return UIImage(cgImage: croppedCgImage, scale: scale, orientation: .up)
}
}
let image = #imageLiteral(resourceName: "image.png")
let celCount: CGFloat = 3
let cels = stride(from: 0, to: celCount, by: 1).map({ (i) -> UIImage in
image.subImage(inUnitRect: CGRect(x: i / celCount, y: 0, width: 1/3, height: 1))!
})
然后我们可以使用关键帧动画来淡化图层内容:
let imageView = UIImageView(image: cels[0])
PlaygroundPage.current.liveView = imageView
let animation = CAKeyframeAnimation(keyPath: "contents")
var values = [CGImage]()
var keyTimes = [Double]()
for (i, cel) in cels.enumerated() {
keyTimes.append(Double(i) / Double(cels.count))
values.append(cel.cgImage!)
// The 0.9 means 90% of the time will be spent *outside* of crossfade.
keyTimes.append((Double(i) + 0.9) / Double(cels.count))
values.append(cel.cgImage!)
}
values.append(cels[0].cgImage!)
keyTimes.append(1.0)
animation.keyTimes = keyTimes.map({ NSNumber(value: [=11=]) })
animation.values = values
animation.repeatCount = .infinity
animation.duration = 5
imageView.layer.add(animation, forKey: animation.keyPath)
结果:
原创
有多种方法可以做到这一点。一种是通过设置或动画化图像视图层的 the contentsRect
property。
在你的图像中,有三个cel,每个占据图像的1/3。 contentsRect
在单位坐标space内,计算方便。 cel i
的 contentsRect
是 CGRect(x: i/3, y: 0, width: 1/3, height: 0)
.
您想要在 cels 之间离散跳跃,而不是平滑的滑动过渡,因此您需要使用具有 kCAAnimationDiscrete
calculationMode
.
的关键帧动画
import UIKit
import PlaygroundSupport
let image = #imageLiteral(resourceName: "image.png")
let celSize = CGSize(width: image.size.width / 3, height: image.size.height)
let imageView = UIImageView()
imageView.frame = CGRect(origin: .zero, size: celSize)
imageView.image = image
PlaygroundPage.current.liveView = imageView
let animation = CAKeyframeAnimation(keyPath: "contentsRect")
animation.duration = 1.5
animation.calculationMode = kCAAnimationDiscrete
animation.repeatCount = .infinity
animation.values = [
CGRect(x: 0, y: 0, width: 1/3.0, height: 1),
CGRect(x: 1/3.0, y: 0, width: 1/3.0, height: 1),
CGRect(x: 2/3.0, y: 0, width: 1/3.0, height: 1)
] as [CGRect]
imageView.layer.add(animation, forKey: animation.keyPath!)
结果:
我不知道如何制作这个动画。你会以某种方式将 1 jpg
文件平均分成 3 部分并制作动画吗?还是您必须制作 jpg
的多个副本并对其进行处理?
任何帮助都会很棒!
更新
由于您想要交叉淡入淡出,将图像拆分为单独的 cel 图像可能是最简单的方法:
import UIKit
import PlaygroundSupport
extension UIImage {
func subImage(inUnitRect unitRect: CGRect) -> UIImage? {
guard imageOrientation == .up, let cgImage = self.cgImage else { return nil }
let cgImageWidth = CGFloat(cgImage.width)
let cgImageHeight = CGFloat(cgImage.height)
let scaledRect = CGRect(x: unitRect.origin.x * cgImageWidth, y: unitRect.origin.y * cgImageHeight, width: unitRect.size.width * cgImageWidth, height: unitRect.size.height * cgImageHeight)
guard let croppedCgImage = cgImage.cropping(to: scaledRect) else { return nil }
return UIImage(cgImage: croppedCgImage, scale: scale, orientation: .up)
}
}
let image = #imageLiteral(resourceName: "image.png")
let celCount: CGFloat = 3
let cels = stride(from: 0, to: celCount, by: 1).map({ (i) -> UIImage in
image.subImage(inUnitRect: CGRect(x: i / celCount, y: 0, width: 1/3, height: 1))!
})
然后我们可以使用关键帧动画来淡化图层内容:
let imageView = UIImageView(image: cels[0])
PlaygroundPage.current.liveView = imageView
let animation = CAKeyframeAnimation(keyPath: "contents")
var values = [CGImage]()
var keyTimes = [Double]()
for (i, cel) in cels.enumerated() {
keyTimes.append(Double(i) / Double(cels.count))
values.append(cel.cgImage!)
// The 0.9 means 90% of the time will be spent *outside* of crossfade.
keyTimes.append((Double(i) + 0.9) / Double(cels.count))
values.append(cel.cgImage!)
}
values.append(cels[0].cgImage!)
keyTimes.append(1.0)
animation.keyTimes = keyTimes.map({ NSNumber(value: [=11=]) })
animation.values = values
animation.repeatCount = .infinity
animation.duration = 5
imageView.layer.add(animation, forKey: animation.keyPath)
结果:
原创
有多种方法可以做到这一点。一种是通过设置或动画化图像视图层的 the contentsRect
property。
在你的图像中,有三个cel,每个占据图像的1/3。 contentsRect
在单位坐标space内,计算方便。 cel i
的 contentsRect
是 CGRect(x: i/3, y: 0, width: 1/3, height: 0)
.
您想要在 cels 之间离散跳跃,而不是平滑的滑动过渡,因此您需要使用具有 kCAAnimationDiscrete
calculationMode
.
import UIKit
import PlaygroundSupport
let image = #imageLiteral(resourceName: "image.png")
let celSize = CGSize(width: image.size.width / 3, height: image.size.height)
let imageView = UIImageView()
imageView.frame = CGRect(origin: .zero, size: celSize)
imageView.image = image
PlaygroundPage.current.liveView = imageView
let animation = CAKeyframeAnimation(keyPath: "contentsRect")
animation.duration = 1.5
animation.calculationMode = kCAAnimationDiscrete
animation.repeatCount = .infinity
animation.values = [
CGRect(x: 0, y: 0, width: 1/3.0, height: 1),
CGRect(x: 1/3.0, y: 0, width: 1/3.0, height: 1),
CGRect(x: 2/3.0, y: 0, width: 1/3.0, height: 1)
] as [CGRect]
imageView.layer.add(animation, forKey: animation.keyPath!)
结果: