iOS - 在视图控制器中绘制一个甜甜圈
iOS - Draw a donut in an view controller
这真的很简单,但我不知道我做错了什么。
我有一个视图控制器,中间有一个视图。我想画像下面的圆圈:
我遇到的主要问题是我无法在视图中显示任何内容。我现在只是想画一条线,但显然缺少一些关键的东西。这是我的代码:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *centerView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[UIColor brownColor] set];
CGContextRef currentContext =UIGraphicsGetCurrentContext();
CGContextSetLineWidth(currentContext,5.0f);
CGContextMoveToPoint(currentContext,50.0f, 10.0f);
CGContextAddLineToPoint(currentContext,100.0f, 200.0f);
CGContextStrokePath(currentContext);
}
你可以用 CAShapeLayer 来做。这是一个 playground,说明了如何做到这一点。作为额外的奖励,我加入了动画。
import UIKit
import PlaygroundSupport
class AnimatedRingView: UIView {
private static let animationDuration = CFTimeInterval(2)
private let π = CGFloat.pi
private let startAngle = 1.5 * CGFloat.pi
private let strokeWidth = CGFloat(8)
var proportion = CGFloat(0.5) {
didSet {
setNeedsLayout()
}
}
private lazy var circleLayer: CAShapeLayer = {
let circleLayer = CAShapeLayer()
circleLayer.strokeColor = UIColor.gray.cgColor
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineWidth = self.strokeWidth
self.layer.addSublayer(circleLayer)
return circleLayer
}()
private lazy var ringlayer: CAShapeLayer = {
let ringlayer = CAShapeLayer()
ringlayer.fillColor = UIColor.clear.cgColor
ringlayer.strokeColor = self.tintColor.cgColor
ringlayer.lineCap = kCALineCapRound
ringlayer.lineWidth = self.strokeWidth
self.layer.addSublayer(ringlayer)
return ringlayer
}()
override func layoutSubviews() {
super.layoutSubviews()
let radius = (min(frame.size.width, frame.size.height) - strokeWidth - 2)/2
let circlePath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: startAngle + 2 * π, clockwise: true)
circleLayer.path = circlePath.cgPath
ringlayer.path = circlePath.cgPath
ringlayer.strokeEnd = proportion
}
func animateRing(From startProportion: CGFloat, To endProportion: CGFloat, Duration duration: CFTimeInterval = animationDuration) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration
animation.fromValue = startProportion
animation.toValue = endProportion
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
ringlayer.strokeEnd = endProportion
ringlayer.strokeStart = startProportion
ringlayer.add(animation, forKey: "animateRing")
}
}
let v = AnimatedRingView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
PlaygroundPage.current.liveView = v
v.animateRing(From: 0, To: 0.5)
这真的很简单,但我不知道我做错了什么。
我有一个视图控制器,中间有一个视图。我想画像下面的圆圈:
我遇到的主要问题是我无法在视图中显示任何内容。我现在只是想画一条线,但显然缺少一些关键的东西。这是我的代码:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIView *centerView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[UIColor brownColor] set];
CGContextRef currentContext =UIGraphicsGetCurrentContext();
CGContextSetLineWidth(currentContext,5.0f);
CGContextMoveToPoint(currentContext,50.0f, 10.0f);
CGContextAddLineToPoint(currentContext,100.0f, 200.0f);
CGContextStrokePath(currentContext);
}
你可以用 CAShapeLayer 来做。这是一个 playground,说明了如何做到这一点。作为额外的奖励,我加入了动画。
import UIKit
import PlaygroundSupport
class AnimatedRingView: UIView {
private static let animationDuration = CFTimeInterval(2)
private let π = CGFloat.pi
private let startAngle = 1.5 * CGFloat.pi
private let strokeWidth = CGFloat(8)
var proportion = CGFloat(0.5) {
didSet {
setNeedsLayout()
}
}
private lazy var circleLayer: CAShapeLayer = {
let circleLayer = CAShapeLayer()
circleLayer.strokeColor = UIColor.gray.cgColor
circleLayer.fillColor = UIColor.clear.cgColor
circleLayer.lineWidth = self.strokeWidth
self.layer.addSublayer(circleLayer)
return circleLayer
}()
private lazy var ringlayer: CAShapeLayer = {
let ringlayer = CAShapeLayer()
ringlayer.fillColor = UIColor.clear.cgColor
ringlayer.strokeColor = self.tintColor.cgColor
ringlayer.lineCap = kCALineCapRound
ringlayer.lineWidth = self.strokeWidth
self.layer.addSublayer(ringlayer)
return ringlayer
}()
override func layoutSubviews() {
super.layoutSubviews()
let radius = (min(frame.size.width, frame.size.height) - strokeWidth - 2)/2
let circlePath = UIBezierPath(arcCenter: center, radius: radius, startAngle: startAngle, endAngle: startAngle + 2 * π, clockwise: true)
circleLayer.path = circlePath.cgPath
ringlayer.path = circlePath.cgPath
ringlayer.strokeEnd = proportion
}
func animateRing(From startProportion: CGFloat, To endProportion: CGFloat, Duration duration: CFTimeInterval = animationDuration) {
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.duration = duration
animation.fromValue = startProportion
animation.toValue = endProportion
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
ringlayer.strokeEnd = endProportion
ringlayer.strokeStart = startProportion
ringlayer.add(animation, forKey: "animateRing")
}
}
let v = AnimatedRingView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
PlaygroundPage.current.liveView = v
v.animateRing(From: 0, To: 0.5)