3

我正在尝试在 AVPlayerLayer 上制作“缩小”动画,但只要我这样做,视频内容就会从屏幕上消失。动画持有 AVPlayerLayer 的 UIView 作品但不是 AVPlayerLayer。设置动画的正确方法是什么?

 CGRect oldBounds = playerLayer.bounds;
 CGRect newBounds = oldBounds;
 newBounds.size = CGSizeZero;
 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
 animation.duration = 5.f;
 animation.beginTime = CACurrentMediaTime();
 animation.fromValue = [NSValue valueWithCGRect:oldBounds];
 animation.toValue = [NSValue valueWithCGRect:newBounds];


[playerLayer addAnimation:animation forKey:@"shrink"];
4

2 回答 2

1

当一个层被一个视图控制时,iOS 默认关闭动画。但是,当您在 UIView 上为属性设置动画时,它会短暂打开图层的动画功能,并将动画参数发送到图层以执行,然后关闭图层上的动画功能。那就是:做动画是控制UIView,而不是图层。

也就是说,我也不知道如何让我的 AVPlayerLayer 通过我的 UIView 进行动画处理。我上面所说的是它应该如何工作,但我现在也无法让它工作。呵呵。

于 2015-08-01T17:24:18.350 回答
0

这不足为奇。AVPlayerLayer是一个特殊的层类,因为它不存在于QuartzCore框架中,也没有CA类前缀。它还经过高度优化,可将视频帧渲染到显示器。尝试AVPlayerLayer通过 UIKit 间接或直接通过 Core Animation 向我添加动画会导致奇怪的行为。

可能应用任何类型动画的唯一方法AVPlayerLayer是创建主机视图的快照或将图层内容直接渲染到图形上下文中。但是,如果后者不起作用,我不会感到惊讶,因为AVPlayerLayer可能不包含 Core Animation 能够渲染的后备存储。

编辑:这是针对此问题的 Playground 解决方案,尽管它确实依赖于使用 UIKit,而不是单独的核心动画。我没有在设备上或模拟器中测试过,但这似乎可行:

import UIKit
import AVFoundation
import PlaygroundSupport

let rootView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 600.0, height: 400.0))
rootView.backgroundColor = .white

let playerLayerView = UIView()
playerLayerView.frame.size = CGSize(width: 480.0, height: 270.0)
playerLayerView.center = CGPoint(x: rootView.bounds.midX, y: rootView.bounds.midY)

guard let videoUrl = Bundle.main.url(
    forResource: "HEVC_3_iPhone",
    withExtension: "m4v")
    else { fatalError() }

let player = AVPlayer(url: videoUrl)
player.play()

let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = playerLayerView.bounds

playerLayerView.layer.addSublayer(playerLayer)

rootView.addSubview(playerLayerView)

UIView.animate(
    withDuration: 1.0,
    delay: 0.0,
    options: [.autoreverse, .repeat],
    animations: {
        playerLayerView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2)
    },
    completion: nil
)

PlaygroundPage.current.liveView = rootView

这是它的样子:

如果我理解正确的话,“问题”——尽管这不像管道必要性那样严重——AVPlayerLayer是它位于标准 UIKit 渲染和合成管道之外。与其他特殊层类(如)一起CAMetalLayerAVPlayerLayer在不同的进程中渲染,因为 AVFoundation 需要直接绘制访问不受 UIKit 渲染循环限制的屏幕。所以试图将动画直接附加到图层是行不通的。

UIView然而,将该层放在AVPlayerLayer. AVFoundation 仍然很可能以它想要的方式渲染视频帧,但为 Core Animation 提供了一个纹理来合成它想要的任何东西。

这可能会导致微妙的播放器计时抖动,因为您将以前独立渲染的视频强制到 UIKit 的渲染循环中。一般来说,同步这些特殊层是很棘手的,因为 Core Animation 必须不可避免地等待各种进程都完成为它们的层提供渲染位图,以便它可以将所有内容组合在一起成为一个屏幕刷新。

但这都是我的猜测。

于 2015-11-23T22:11:22.833 回答