[英]animating a CALayer
I have a CALayer on top of a UIView. 我在UIView上有一个CALayer。
The UIView animates exactly how I want it to, however the PlayerView that is on top of it seems to "spawn" offscreen then animate to the position that the UIView started in and then it will animate to the UIViews frame. UIView的动画正是我想要它,但是这是在它之上的PlayerView似乎“重生”离屏幕动画,然后到了UIView中开始,然后它会以动画的UIViews帧中的位置。
I was wondering if there was any property of CALayers that could handle this issue automatically but I haven't found anything. 我想知道是否有CALayers的任何属性可以自动处理此问题,但我什么都没找到。
Here's the code for this: 这是此代码:
let window = UIApplication.shared.keyWindow!
v = UIView(frame: CGRect(x: window.frame.origin.x, y: window.frame.origin.y, width: window.frame.width, height: window.frame.height))
let v2 = UIView(frame: .zero)
window.addSubview(v!);
window.addSubview(v2)
v?.backgroundColor = UIColor.black
v2.backgroundColor = UIColor.clear
v?.layer.cornerRadius = (v?.frame.width)! * 0.025
guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
playerLayer = AVPlayerLayer(player: player)
// playerLayer.frame = playerView.frame
playerLayer?.frame = (playerView?.bounds)!
playerLayer?.masksToBounds = true
playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
v?.layer.addSublayer(playerLayer!)
player?.play()
player?.isMuted = true
//looper
NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil)
{ notification in
let t1 = CMTimeMake(5, 100)
self.player?.seek(to: t1)
self.player?.play()
}
let superview = playerView?.superview
v2.frame = (v2.convert((playerView?.frame)!, from: superview))
v?.frame = (v?.convert((playerView?.frame)!, from: superview))!
window.addConstraintsWithFormat("H:|[v0]|", views: v!)
window.addConstraintsWithFormat("V:|[v0]|", views: v!)
playerLayer?.frame = (v?.frame)!
self.playerLayer?.frame = (self.v?.frame)!
UIView.animate(withDuration: 4, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.window?.layoutIfNeeded()
}, completion: { (completed) in
self.playerLayer?.frame = (self.v?.frame)!
})
}
any suggestions? 有什么建议么?
EDIT: 编辑:
I have included the updated code 我已包含更新的代码
let window = UIApplication.shared.keyWindow!
v = UIView(frame: CGRect(x: window.frame.origin.x, y: window.frame.origin.y, width: window.frame.width, height: window.frame.height))
let v2 = UIView(frame: .zero)
window.addSubview(v!);
v?.addSubview(playerView2!)
window.addSubview(v2)
v?.backgroundColor = UIColor.black
v2.backgroundColor = UIColor.clear
v?.layer.cornerRadius = (v?.frame.width)! * 0.025
playerView2?.layer.cornerRadius = (playerView2?.bounds.width)! * 0.025
guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
playerLayer = AVPlayerLayer(player: player)
// playerLayer.frame = playerView.frame
playerLayer?.frame = (playerView2?.bounds)!
playerLayer?.masksToBounds = true
playerLayer?.cornerRadius = (playerView2?.bounds.width)! * 0.025
playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
self.playerView2?.layer.addSublayer(playerLayer!)
// player?.play()
player?.isMuted = true
//looper
NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem, queue: nil)
{ notification in
let t1 = CMTimeMake(5, 100)
self.player?.seek(to: t1)
// self.player?.play()
}
self.playerView2?.frame = (self.v?.bounds)!
self.playerLayer?.frame = (self.playerView?.bounds)!
UIView.animate(withDuration: 5, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.v?.frame = window.frame
self.playerView2?.frame = (self.v?.frame)!
self.playerLayer?.frame = (self.playerView2?.frame)!
self.window?.layoutIfNeeded()
}, completion: { (completed) in
})
}
You're getting an implicit animation when you set playerLayer.frame
. 设置
playerLayer.frame
时,您将获得一个隐式动画。
If you don't want any animation, temporarily disable implicit animations like this: 如果您不想使用任何动画,请暂时禁用如下所示的隐式动画:
UIView.animate(withDuration: 4, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
self.window?.layoutIfNeeded()
}, completion: { (completed) in
let priorValue = CATransaction.disableActions()
CATransaction.setDisableActions(true)
self.playerLayer?.frame = self.v!.frame
CATransaction.setDisableActions(priorValue)
})
If you do want to animate playerLayer.frame
, then the best way is to create a UIView
subclass that uses an AVPlayerLayer
as its layer, like this: 如果您想为
playerLayer.frame
设置动画,那么最好的方法是创建一个使用AVPlayerLayer
作为其图层的UIView
子类,如下所示:
class PlayerView: UIView {
override class var layerClass: AnyClass { return AVPlayerLayer.self }
private(set) lazy var playerLayer: AVPlayerLayer = { self.layer as! AVPlayerLayer }()
}
Then you can use a PlayerView
instead of a bare AVPlayerLayer
and use UIKit animations. 然后,您可以使用
PlayerView
代替裸露的AVPlayerLayer
并使用UIKit动画。 Since you can't initialize the AVPlayerLayer
directly ( UIView
uses the default initializer to create its layer), you'll need to set the PlayerView
's player like this: 由于您无法直接初始化
AVPlayerLayer
( UIView
使用默认的初始化程序创建其图层),因此需要像这样设置PlayerView
的播放器:
playerView?.playerLayer = player
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.