【发布时间】:2023-03-25 19:55:02
【问题描述】:
我在做什么:
我正在创建一个音乐应用程序。在这个音乐应用程序中,我有一个与 Apple Music 和 Spotify 链接的音乐播放器。音乐播放器在UIImageView 上显示当前歌曲的专辑封面。每当播放歌曲时,UIImageView 就会旋转(就像唱机上的唱片一样)。
我的问题是:
UIImageView 的专辑封面默认为方形。我将UIImageView 的layer 的角四舍五入并将UIImageView.clipsToBounds 设置为等于true 以使其显示为一个圆圈。
每当UIImageView 旋转时,UIImageView 的layer 之外的一些像素(对图像进行四舍五入后被切断的部分)就会渗出。
这是错误的样子: https://www.youtube.com/watch?v=OJxX5PQc7Jo&feature=youtu.be
我的代码:
UIImageView 通过将其layer 的cornerRadius 设置为等于UIImageView.frame.height / 2 并设置UIImageView.clipsToBounds = true 来进行舍入:
class MyViewController: UIViewController {
@IBOutlet var albumArtImageView: UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
albumArtImageView.layer.cornerRadius = albumArtImageView.frame.height / 2
albumArtImageView.clipsToBounds = true
//I've also tried the following code, and am getting the same behavior:
/*
albumArtImageView.layer.cornerRadius = albumArtImageView.frame.height / 2
albumArtImageView.layer.masksToBounds = true
albumArtImageView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner,.layerMinXMaxYCorner, .layerMaxXMaxYCorner]
*/
}
}
只要按下按钮,UIImageView 就会开始旋转。我使用了以下extension 来使UIView 旋转:
extension UIView {
func rotate(duration: Double = 1, startPoint: CGFloat) {
if layer.animation(forKey: UIView.kRotationAnimationKey) == nil {
let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotationAnimation.fromValue = startPoint
rotationAnimation.toValue = (CGFloat.pi * 2.0) + startPoint
rotationAnimation.duration = duration
rotationAnimation.repeatCount = Float.infinity
layer.add(rotationAnimation, forKey: UIView.kRotationAnimationKey)
}
}
}
我还有以下扩展来结束轮换:
extension UIView {
...
func stopRotating(beginTime: Double!, startingAngle: CGFloat) -> CGFloat? {
if layer.animation(forKey: UIView.kRotationAnimationKey) != nil {
let animation = layer.animation(forKey: UIView.kRotationAnimationKey)!
let elapsedTime = CACurrentMediaTime() - beginTime
let angle = elapsedTime.truncatingRemainder(dividingBy: animation.duration)/animation.duration
layer.transform = CATransform3DMakeRotation((CGFloat(angle) * (2 * CGFloat.pi)) + startingAngle, 0.0, 0.0, 1.0)
layer.removeAnimation(forKey: UIView.kRotationAnimationKey)
return (CGFloat(angle) * (2 * CGFloat.pi)) + startingAngle
} else {
return nil
}
}
}
这就是这些扩展函数在我的视图控制器上下文中的使用方式:
class MyViewController: UIViewController {
var songBeginTime: Double!
var currentRecordAngle: CGFloat = 0.0
var isPlaying = false
...
@IBAction func playButtonPressed(_ sender: Any) {
if isPlaying {
if let angle = albumArtImageView.stopRotating(beginTime: songBeginTime, startingAngle: currentRecordAngle) {
currentRecordAngle = angle
}
songBeginTime = nil
} else {
songBeginTime = CACurrentMediaTime()
albumArtImageView.rotate(duration: 3, startPoint: currentRecordAngle)
}
}
}
所以,MyViewController 看起来像这样:
class MyViewController: UIViewController {
@IBOutlet var albumArtImageView: UIImageView()
var songBeginTime: Double!
var currentRecordAngle: CGFloat = 0.0
var isPlaying = false
override func viewDidLoad() {
super.viewDidLoad()
albumArtImageView.layer.cornerRadius = albumArtImageView.frame.height / 2
albumArtImageView.clipsToBounds = true
}
@IBAction func playButtonPressed(_ sender: Any) {
if isPlaying {
if let angle = albumArtImageView.stopRotating(beginTime: songBeginTime, startingAngle: currentRecordAngle) {
currentRecordAngle = angle
}
songBeginTime = nil
} else {
songBeginTime = CACurrentMediaTime()
albumArtImageView.rotate(duration: 3, startPoint: currentRecordAngle)
}
}
}
【问题讨论】:
标签: ios swift uiview calayer cabasicanimation