如何将 UIImage 从上到下缓慢过渡以将滤镜应用于图像?

How can I transition a UIImage slowly from top to bottom for applying filter to the image?

我想让它看起来好像我的图像正在从上到下慢慢过滤。我正在添加两个图像视图。我处理过的图像在后台,未处理的在前面。我正在将未处理图像的高度设置为 0。这是我的代码。

imageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.size.width, height: 400)
imageView.image = processedImage


let nonProcessedImageView = UIImageView()
nonProcessedImageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.size.width, height: 400)
nonProcessedImageView.image = nonProcessedImage
view.addSubview(nonProcessedImageView)

UIView.transition(with: nonProcessedImageView,
                  duration: 5.0,
                  animations: {
   nonProcessedImageView.frame = CGRect(x: 0, y: 500, width: self.view.bounds.size.width, height: 0)
   },
                  completion: {_ in
   })

未处理的图像甚至不会出现在已处理的图像之上。

问题似乎是更改动画块中帧的 y 坐标会导致使用 UIView.Animate 函数时出现问题。

看到这个answer

引用最精华的部分:

You should change the center property (to move the view) and bounds property (to change its size) instead. Those properties behave as expected.

因为你只想降低高度,你不需要对y坐标做任何事情

let nonProcessedImageView = UIImageView()

var newImageFrame = imageView.frame

nonProcessedImageView.frame = newImageFrame
nonProcessedImageView.clipsToBounds = true
nonProcessedImageView.contentMode = .scaleAspectFit
nonProcessedImageView.image = imageView.image
view.addSubview(nonProcessedImageView)

// I set this to 1 instead of 0 as 0 does not show the image
// for some reason
newImageFrame.size.height = 1

// Update your processed image
imageView.image = processedImage

UIView.animate(withDuration: 5.0) {
    nonProcessedImageView.frame = newImageFrame
}
completion: { (isComplete) in
    if isComplete {
        nonProcessedImageView.removeFromSuperview()
    }
}

这给出了一些结果,但如您所见,动画不是很好,因为当您降低高度时,图像视图的 contentMode 开始并给出所见效果。

为获得最佳效果,请将新图像视图添加到 UIView 并减小 UIView 而不是 UIImageView 的高度

var newImageFrame = imageView.frame

let containerView = UIView(frame: newImageFrame)
containerView.clipsToBounds = true

let nonProcessedImageView = UIImageView()
nonProcessedImageView.frame = containerView.bounds
nonProcessedImageView.clipsToBounds = true
nonProcessedImageView.contentMode = .scaleAspectFit // same as original
nonProcessedImageView.image = imageView.image

containerView.addSubview(nonProcessedImageView)
view.addSubview(containerView)

newImageFrame.size.height = 1

imageView.image = processedImage

UIView.animate(withDuration: 3.0) {
    containerView.frame = newImageFrame
}
completion: { (isComplete) in
    if isComplete {
        containerView.removeFromSuperview()
    }
}

这应该能满足您的需求:

这适用于从上到下的过渡。

imageView.frame = CGRect(x: 0, y: 100, width: self.view.bounds.width, height: 400)
imageView.image = nonProcessedImage
view.addSubview(imageView)
    
let frontView = UIView(frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 0))
frontView.clipsToBounds = true
view.addSubview(frontView)

let nonProcessedImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: 400))
nonProcessedImageView.image = processedImage
nonProcessedImageView.clipsToBounds = true
frontView.addSubview(nonProcessedImageView)
    
UIView.transition(with: frontView, duration: 5, options: [.allowAnimatedContent], animations: {
    frontView.frame = CGRect(x: 0, y: 100, width: self.view.frame.width, height: 400)
}, completion: nil)