class CircleView: UIView {
let borderWidth: CGFloat = 20
let startAngle = CGFloat(Double.pi)
let middleAngle = CGFloat(Double.pi + Double.pi / 2)
let endAngle = CGFloat(2 * Double.pi)
var primaryColor = UIColor.red
var secondaryColor = UIColor.blue
var currentStrokeValue = CGFloat(0)
override func draw(_ rect: CGRect) {
let center = CGPoint(x: self.frame.width / 2, y: self.frame.height / 2)
let radius = CGFloat(self.frame.width / 2 - borderWidth)
let path1 = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: middleAngle, clockwise: true)
let path2 = UIBezierPath(arcCenter: center, radius: radius, startAngle: middleAngle, endAngle: endAngle, clockwise: true)
path1.lineWidth = borderWidth
primaryColor.setStroke()
path1.stroke()
path2.lineWidth = borderWidth
secondaryColor.setStroke()
path2.stroke()
}
}
之后,我获取路径path3
,然后将其添加到一个图层中,并将该图层添加到视图中:
var path3 = UIBezierPath(arcCenter: center, radius: radius, startAngle: endAngle, endAngle: startAngle, clockwise: true)
Reynaldo Aguilar的回答很好。您可以通过创建一个遮罩层并动画化其框架来实现相同的效果。这种方法的好处是它适用于任何(和多彩的)背景。这种方法的缺点是,如果该线路不起作用,则可能无法正常工作,因为在该场景中可能会同时隐藏/揭示多个点(当您只希望其中之一时)。
为了方便使用,您可以子类化UIView并覆盖其绘制和init方法,如下所示添加行。
初始化:
init(frame: CGRect, path: [UIBezierPath], strokeColor: [UIColor], fillColor: [UIColor], lineWidth: [CGFloat]) {
// Initialize the view
super.init(frame: frame)
self.paths = path
self.strokeColors = strokeColor
self.fillColors = fillColor
self.lineWidths = lineWidth
self.backgroundColor = UIColor.clear // Background will always be clear by default
}
绘制:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard paths.count == strokeColors.count && strokeColors.count == fillColors.count && fillColors.count == lineWidths.count else {
print("ERROR: ARRAYS DON'T MATCH") // Stronger error handling recommended
return
}
for psfl in 0..<paths.count {
// Fill path if appropriate
self.fillColors[psfl].setFill()
self.paths[psfl].fill()
self.strokeColors[psfl].setStroke()
self.paths[psfl].lineWidth = self.lineWidths[psfl]
self.paths[psfl].stroke()
}
}
func animate(startingRect: CGRect, duration: Double, animationKey: String) {
// Create a path based on the starting rect
let maskPath = UIBezierPath(rect: startingRect)
// Create a path based on the final rect
let finalPath = UIBezierPath(rect: self.frame)
// Create a shapelayer for the animation block
let maskLayer = CAShapeLayer()
maskLayer.frame = startingRect
// Add the mask layer to the custom view
self.layer.mask = maskLayer
// Animation block
let animation = CABasicAnimation(keyPath: "path")
animation.delegate = self // (Optionaly) set the delegate so we can remove the mask when the animation completes
animation.fromValue = maskLayer.path
animation.toValue = finalPath.cgPath
animation.duration = duration
maskLayer.add(animation, forKey: animationKey) // Add the animation to the mask layer
// Necessary for the animation to work properly
CATransaction.begin()
CATransaction.setDisableActions(true)
maskLayer.path = maskPath.cgPath
CATransaction.commit()
}
import UIKit
import QuartzCore
import CoreGraphics
class ViewController: UIViewController,UIGestureRecognizerDelegate {
var btnview : UIButton!
var buttonCenter = CGPoint.zero
var firstlayerpoint = CGPoint.zero
var firstLayer = CAShapeLayer()
var secondLayer = CAShapeLayer()
var thirdLayer = CAShapeLayer()
var initialPosition = CGRect()
let label = UILabel()
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var blueLabel: UILabel!
@IBOutlet weak var greenLabel: UILabel!
@IBOutlet weak var redLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
firstLayer = self.createCircleWithBounds(bounds: CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.blue, LineWidth: 20.0)
firstLayer.strokeStart = 0.00
firstLayer.strokeEnd = 0.33
self.view.layer.addSublayer(firstLayer)
secondLayer = self.createCircleWithBounds(bounds: CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.red, LineWidth: 20.0)
secondLayer.strokeStart = 0.33
secondLayer.strokeEnd = 0.66
self.view.layer.addSublayer(secondLayer)
thirdLayer = self.createCircleWithBounds(bounds: CGRect(x:0, y:0, width:100,height:100), Position: self.view.center, StrokeColor: UIColor.green, LineWidth: 20.0)
thirdLayer.strokeStart = 0.66
thirdLayer.strokeEnd = 1.00
self.view.layer.addSublayer(thirdLayer)
btnview = UIButton(frame: CGRect(x: self.view.center.x - 20 , y: self.view.center.y - 20 , width: 40, height: 40))
btnview.backgroundColor = UIColor.gray
btnview.isUserInteractionEnabled = true
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panButton(panGesture:)))
// panGesture.minimumNumberOfTouches = 1
btnview.addGestureRecognizer(panGesture)
self.view.addSubview(btnview)
// Do any additional setup after loading the view, typically from a nib.
nameLabel.isHidden = true
blueLabel.isHidden = true
greenLabel.isHidden = true
redLabel.isHidden = true
}
func panButton(panGesture: UIPanGestureRecognizer) {
//let translation = panGesture.translation(in: self.btnview)
panGesture.view!.center = btnview.center
panGesture.setTranslation(CGPoint.zero, in: self.view)
// var point = CGPoint.zero
// point = firstLayer.frame.size.center
if panGesture.state == .began {
label.isHidden = false
buttonCenter = btnview.center // store old button center
}
else if panGesture.state == .ended || panGesture.state == .failed || panGesture.state == .cancelled {
print(btnview.frame.origin.x)
print(greenLabel.frame.origin.x)
if btnview.frame.origin.x > greenLabel.frame.origin.x
{
// lblflayer.isHidden = false
// lblsecondlayer.isHidden = true
// lblthirdlayer.isHidden = true
nameLabel.isHidden = false
nameLabel.text = "Blue"
nameLabel.backgroundColor = UIColor.blue
}
else if btnview.frame.origin.x > blueLabel.frame.origin.x
{
// print(btnview.frame.origin.x)
// print(lblsecondlayer.frame.origin.x)
// lblsecondlayer.isHidden = false
// lblflayer.isHidden = true
// lblthirdlayer.isHidden = true
nameLabel.isHidden = false
nameLabel.text = "Red"
nameLabel.backgroundColor = UIColor.red
}
else if btnview.frame.origin.x > redLabel.frame.origin.x
{
print(btnview.frame.origin.x)
print(redLabel.frame.origin.x)
greenLabel.isHidden = true
// lblsecondlayer.isHidden = true
// lblthirdlayer.isHidden = false
nameLabel.isHidden = false
nameLabel.text = "Green"
nameLabel.backgroundColor = UIColor.green
}
else
{
nameLabel.isHidden = true
// lblflayer.isHidden = true
// lblsecondlayer.isHidden = true
// lblthirdlayer.isHidden = true
}
btnview.center = buttonCenter // restore button center
}
else
{
let location = panGesture.location(in: view) // get pan location
btnview.center = location // set button to where finger is
}
}
func createCircleWithBounds(bounds: CGRect, Position position: CGPoint, StrokeColor color: UIColor, LineWidth lineWidth: CGFloat) -> CAShapeLayer {
//let shapelayer = CAShapeLayer.layer
let shapelayer = CAShapeLayer()
shapelayer.strokeColor = color.cgColor
shapelayer.fillColor = UIColor.clear.cgColor
shapelayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: bounds.width / 2).cgPath
shapelayer.bounds = bounds
shapelayer.position = position
shapelayer.lineCap = kCALineCapButt
shapelayer.lineWidth = lineWidth
return shapelayer
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}