我有一个UIView类,我将其添加到主视图中,该类将除圆形以外的所有内容都屏蔽了。现在,我正在尝试为圈子设置动画。我决定使用CABasicAnimation来执行此操作,但是圆圈仍然很大并且没有动画。我不确定是否遗漏了什么,或者我想做什么是不可能的。
class SpotlightOverlay: UIView {
let overlayView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
}
init(frame: CGRect,
xOffset: CGFloat,
yOffset: CGFloat,
radius: CGFloat) {
super.init(frame: frame)
overlayView.frame = frame
overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
let path = CGMutablePath()
path.addArc(center: CGPoint(x: xOffset, y: yOffset),
radius: radius*5,
startAngle: 0.0,
endAngle: 2.0 * .pi,
clockwise: false)
path.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
let path2 = CGMutablePath()
path2.addArc(center: CGPoint(x: xOffset, y: yOffset),
radius: radius,
startAngle: 0.0,
endAngle: 2.0 * .pi,
clockwise: false)
path2.addRect(CGRect(origin: .zero, size: overlayView.frame.size))
let anim = CABasicAnimation(keyPath: "path")
anim.fromValue = path
anim.toValue = path2
anim.duration = 6.0
anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
let maskLayer = CAShapeLayer()
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.add(anim, forKey: nil)
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = path
CATransaction.commit()
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
overlayView.layer.mask = maskLayer
overlayView.clipsToBounds = true
self.addSubview(overlayView)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
答案 0 :(得分:0)
我没有使用CGMutablePath,而是通过UIBezierPath实现了我想要的。更具体地说,它显示为视图中可以设置动画的孔。
import UIKit
class SpotlightOverlay: UIView {
let overlayView = UIView()
let maskLayer = CAShapeLayer()
var initXOffset:CGFloat = 0
var initYOffset:CGFloat = 0
var initDiameter:CGFloat = 0
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clear
}
init(frame: CGRect,
xOffset: CGFloat,
yOffset: CGFloat,
startDiameter: CGFloat,
endDiameter:CGFloat,
duration:Double) {
super.init(frame: frame)
self.isUserInteractionEnabled = false
self.overlayView.isUserInteractionEnabled = false
overlayView.frame = frame
overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
let padding:CGFloat = 50
let startDiameter = startDiameter + padding
let endDiameter = endDiameter + padding
initXOffset = xOffset
initYOffset = yOffset
initDiameter = endDiameter
let ovalFrame1 = CGRect(x:xOffset-(startDiameter/2),
y:yOffset-(startDiameter/2),
width:startDiameter,
height:startDiameter)
let ovalFrame2 = CGRect(x:xOffset-(endDiameter/2),
y:yOffset-(endDiameter/2),
width:endDiameter,
height:endDiameter)
let path = UIBezierPath(ovalIn: ovalFrame1)
let path2 = UIBezierPath(ovalIn: ovalFrame2)
maskLayer.backgroundColor = UIColor.black.cgColor
path.append(UIBezierPath(rect: self.bounds))
path2.append(UIBezierPath(rect: self.bounds))
maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = path.cgPath
CATransaction.commit()
let anim = CABasicAnimation(keyPath: "path")
anim.fromValue = path.cgPath
anim.toValue = path2.cgPath
anim.duration = duration
anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
anim.fillMode = CAMediaTimingFillMode.forwards
anim.isRemovedOnCompletion = false
maskLayer.add(anim, forKey: nil)
overlayView.layer.mask = maskLayer
overlayView.clipsToBounds = true
self.addSubview(overlayView)
}
func animateTo(xOffset: CGFloat,
yOffset: CGFloat,
endDiameter:CGFloat,
duration:Double) {
let padding:CGFloat = 50
let startDiameter = initDiameter
let endDiameter = endDiameter + padding
let ovalFrame1 = CGRect(x:initXOffset-(startDiameter/2),
y:initYOffset-(startDiameter/2),
width:startDiameter,
height:startDiameter)
let ovalFrame2 = CGRect(x:xOffset-(endDiameter/2),
y:yOffset-(endDiameter/2),
width:endDiameter,
height:endDiameter)
initXOffset = xOffset
initYOffset = yOffset
let path = UIBezierPath(ovalIn: ovalFrame1)
let path2 = UIBezierPath(ovalIn: ovalFrame2)
path.append(UIBezierPath(rect: self.bounds))
path2.append(UIBezierPath(rect: self.bounds))
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = path.cgPath
CATransaction.commit()
let anim = CABasicAnimation(keyPath: "path")
anim.fromValue = path.cgPath
anim.toValue = path2.cgPath
anim.duration = duration
anim.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
anim.fillMode = CAMediaTimingFillMode.forwards
anim.isRemovedOnCompletion = false
maskLayer.add(anim, forKey: nil)
initDiameter = endDiameter
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
首先,初始化类,然后在要对孔移动进行动画处理的任何时候调用animateTo函数。