【问题标题】:How to animate a stitched image?如何为拼接的图像设置动画?
【发布时间】:2017-05-27 00:25:11
【问题描述】:

我不知道如何制作这个动画。你会以某种方式将 1 jpg 文件平均分成 3 块并为其设置动画吗?或者您是否必须制作多个 jpg 副本并对其进行处理?

任何帮助都会很棒!

【问题讨论】:

  • 当你说“有图像移动”时,你指的是空间位移(框架在屏幕上移动)还是从一个图像到下一个图像的变化(从卡通图像到照片)?
  • 如果可以正确分割图片,可以使用this to animate it
  • @robmayoff 对不起,视频是我亲手录制的。我的意思是the change from one image to the next (from the cartoony image to the photo)
  • @Fonix 你认为是不是这样:1)将拼接的图像分成三部分 2)使用animationImages 在它们之间制作动画
  • 应该做的伎俩,问题是,如果拼接的图像具有可变数量的帧和/或不同的大小,我不确定你将如何知道在哪里分割图像。如果图像始终保持不变,那会很好

标签: ios objective-c swift core-animation uiviewanimation


【解决方案1】:

更新

由于您想要交叉淡入淡出,最简单的方法可能是将图像拆分为单独的 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)

结果:

原创

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

在您的图像中,有 3 个 cel,每个 cel 正好占图像的 1/3。 contentsRect在单位坐标空间中,计算容易。 cel icontentsRectCGRect(x: i/3, y: 0, width: 1/3, height: 0)

您希望在 cel 之间实现离散跳跃,而不是平滑的滑动过渡,因此您需要使用带有 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 并在它们之间制作动画更容易。我认为唯一不同的是过渡 - 有没有办法使过渡相同(似乎有一道淡入淡出的白色闪光)?在这里更容易看到vid.me/vWVw 询问,因为我不确定如何使用您的代码添加它
  • 您可以通过在图像视图后面放置一个纯白色视图并使用另一个关键帧动画为图像视图的不透明度设置动画来制作闪光灯。不透明动画将比我的答案中的代码多一点,但不是火箭科学。
  • 其实我不认为有白色的闪光。我认为 cels 之间只是交叉淡入淡出。
  • 嗯,好吧,如果它是交叉淡入淡出的话,这似乎更容易。这是否也会使用Core Animation 来进行褪色?
  • 后续,既然使用了Core Animation,那么交叉淡入淡出是否也必须使用Core Animation - 可能将这两个动画,移位和淡入淡出组合成一个组?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-24
  • 2013-11-08
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多