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 でアニメーションを実行します。

そうは言っても、UIViewを介してAVPlayerLayerをアニメーション化する方法もわかりません。上で述べたのは、それがどのように機能するかということでしたが、現時点では機能させることもできません。へー。

于 2015-08-01T17:24:18.350 に答える
0

これは驚くべきことではありません。AVPlayerLayerフレームワーク内に存在しないQuartzCoreか、CAクラス接頭辞がないため、特別なレイヤークラスです。また、ビデオ フレームをディスプレイにレンダリングするように高度に最適化されています。AVPlayerLayerUIKit を介して間接的に、または Core Animation を介して直接的にアニメーションを に追加しようとすると、奇妙な動作が発生します。

おそらく、あらゆる種類のアニメーションを適用する唯一の方法AVPlayerLayerは、ホスト ビューのスナップショットを作成するか、レイヤーの内容をグラフィックス コンテキストに直接レンダリングすることです。AVPlayerLayerただし、 Core Animation がレンダリングできるバッキング ストアが含まれていない可能性があるため、後者が機能しなくても驚かないでしょう。

編集:これは、この問題のプレイグラウンド ソリューションですが、コア アニメーションだけではなく、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 レンダリングおよび合成パイプラインの外にあることです。AVFoundation は、UIKit のレンダリング ループによって制限されない画面への直接描画アクセスを必要とするため、 のような他の特別なレイヤ クラスとともにCAMetalLayer、は別のプロセスでレンダリングされます。AVPlayerLayerそのため、アニメーションをレイヤーに直接アタッチしようとしても機能しません。

ただし、そのレイヤーを に配置するとUIView、Core Animation をAVPlayerLayerビュー階層に合成できます。つまり、ビューに対するジオメトリの変更は、ビデオ プレーヤー レイヤーの表示に影響を与えます。AVFoundation は依然としてビデオ フレームを希望どおりにレンダリングする可能性が高いですが、必要に応じて合成する Core Animation のテクスチャを提供します。

以前は個別にレンダリングされていたビデオを UIKit のレンダリング ループに強制しているため、これにより微妙なプレーヤーのタイミング ジッターが発生する可能性があります。一般に、これらの特別なレイヤーを同期するのは難しいです。なぜなら、コア アニメーションは、さまざまなプロセスがレイヤーにレンダリングされたビットマップを提供し終えるのを必然的に待たなければならず、すべてを 1 回の画面更新に合成できるからです。

しかし、それはすべて私の側の憶測です。

于 2015-11-23T22:11:22.833 に答える