ios - 如何对拼接图像进行动画处理?

标签 ios objective-c swift core-animation uiviewanimation

我不知道如何创建这个动画。你会以某种方式将 1 个 jpg 文件均匀地分成 3 block 并为其制作动画吗?或者您是否必须制作 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: $0) })
animation.values = values
animation.repeatCount = .infinity
animation.duration = 5
imageView.layer.add(animation, forKey: animation.keyPath)

结果:

animation with crossfade

原版

有多种方法可以做到这一点。一种是通过设置或动画 the contentsRect property ImageView 层的。

在您的图像中,有三个单元,每个单元恰好占据图像的 1/3。 contentsRect位于单位坐标空间中,这使得计算变得容易。 cel icontentsRectCGRect(x: i/3, y: 0, width: 1/3, height: 0)

您想要在单元格之间进行离散跳跃,而不是平滑的滑动过渡,因此您需要使用带有 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!)

结果:

animation demo

关于ios - 如何对拼接图像进行动画处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41603981/

相关文章:

objective-c - rootViewController 魔法

ios - 在方法 objective-c 之外保留数组数据

Swift:在不使用索引的情况下从数组中删除有限数量的对象

ios - 我的iOS项目中的GPUImage cocoapod触发了“找不到'OpenGL/OpenGL.h'文件”

ios - 多个查询返回错误结果

swift - 在 Swift 4 中访问 AnyClass 变量上的 Class var

android - 我可以完全更改我的移动应用程序的基本代码并仍然保留我在 Google Play 和 Apple 商店中的下载次数吗?

ios - iOS 13+ 中的后台通知被破坏

objective-c - NSDateFormatter 不格式化(返回 nil)

ios - 无法打开 Main.strings,因为没有这样的文件