Ищу способ оживить рисунок круга. Мне удалось создать круг, но он объединяет все вместе.
Вот мой CircleView
класс:
import UIKit
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = UIColor.clearColor()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func drawRect(rect: CGRect) {
// Get the Graphics Context
var context = UIGraphicsGetCurrentContext();
// Set the circle outerline-width
CGContextSetLineWidth(context, 5.0);
// Set the circle outerline-colour
UIColor.redColor().set()
// Create Circle
CGContextAddArc(context, (frame.size.width)/2, frame.size.height/2, (frame.size.width - 10)/2, 0.0, CGFloat(M_PI * 2.0), 1)
// Draw
CGContextStrokePath(context);
}
}
И вот как я добавляю его в иерархию представлений в моем контроллере представления:
func addCircleView() {
let diceRoll = CGFloat(Int(arc4random_uniform(7))*50)
var circleWidth = CGFloat(200)
var circleHeight = circleWidth
// Create a new CircleView
var circleView = CircleView(frame: CGRectMake(diceRoll, 0, circleWidth, circleHeight))
view.addSubview(circleView)
}
Есть ли способ оживить рисование круга за 1 секунду?
Пример, во время анимации он будет выглядеть примерно так, как синяя линия на этом изображении:
Ответы:
Самый простой способ сделать это - использовать мощь основной анимации, которая сделает большую часть работы за вас. Для этого нам нужно переместить код рисования круга из
drawRect
функции в файлCAShapeLayer
. Затем, мы можем использовать ,CABasicAnimation
чтобы оживитьCAShapeLayer
«sstrokeEnd
собственность от0.0
до1.0
.strokeEnd
здесь большая часть волшебства; из документов:Если мы устанавливаем ,
strokeEnd
чтобы0.0
она не будет ничего сделать. Если мы установим его1.0
, он будет рисовать полный круг. Если мы установим его0.5
, он будет рисовать полукруг. и т.п.Итак, для начала, позволяет создать
CAShapeLayer
в вашейCircleView
«sinit
функции и добавить этот слой к функции представленияsublayers
(также обязательно удалитьdrawRect
функцию , так как слой будет рисовать круг сейчас):Примечание: мы настраиваем
circleLayer.strokeEnd = 0.0
так, чтобы круг не рисовался сразу.Теперь давайте добавим функцию, которую мы можем вызвать для запуска круговой анимации:
Затем все, что нам нужно сделать, это изменить вашу
addCircleView
функцию так, чтобы она запускала анимацию, когда вы добавляетеCircleView
к нейsuperview
:Все вместе должно выглядеть примерно так:
Примечание. Так не будет повторяться, а после анимации останется полный круг.
источник
strokeEnd
self.view?.layer.addSublayer(circleLayer)
:-)startAngle:
и файла . - это позиция 3, поэтому позиция 12 будет на 90 ° меньше, чем позиция -π / 2 в радианах. Итак, параметры будут .endAngle:
UIBezierPath
0
startAngle: CGFloat(-M_PI_2), endAngle: CGFloat((M_PI * 2.0) - M_PI_2)
startAngle: (0 - (Double.pi / 2)) + 0.00001
иendAngle: 0 - (Double.pi / 2)
. ЕслиstartAngle
иendAngle
совпадают, круг не будет нарисован, поэтому вы вычитаете очень-очень маленькое смещение изstartAngle
Ответ Майка обновлен для Swift 3.0
Чтобы вызвать функцию:
источник
M_PI
устарело - используйтеCGFloat.pi
вместо него.Ответ Майка отличный! Другой хороший и простой способ сделать это - использовать drawRect в сочетании с setNeedsDisplay (). Вроде тормозит, но это не так :-)
Мы хотим нарисовать круг, начинающийся сверху, который составляет -90 ° и заканчивается 270 °. Центр круга (centerX, centerY) с заданным радиусом. CurrentAngle - это текущий угол конечной точки круга от minAngle (-90) до maxAngle (270).
В drawRect мы указываем, как должен отображаться круг:
Проблема в том, что прямо сейчас, поскольку currentAngle не меняется, круг статичен и даже не отображается, поскольку currentAngle = minAngle.
Затем мы создаем таймер, и всякий раз, когда он срабатывает, мы увеличиваем currentAngle. В верхней части класса добавьте время между двумя кострами:
В вашем init добавьте таймер:
Мы можем добавить функцию, которая будет вызываться при срабатывании таймера:
К сожалению, при запуске приложения ничего не отображается, потому что мы не указали систему, которую оно должно рисовать снова. Это делается путем вызова setNeedsDisplay (). Вот обновленная функция таймера:
_ _ _
Весь необходимый вам код обобщен здесь:
Если вы хотите изменить скорость, просто измените функцию updateTimer или скорость, с которой эта функция вызывается. Кроме того, вы можете захотеть отключить таймер, когда круг будет завершен, что я забыл сделать :-)
NB: Чтобы добавить круг в раскадровку, просто добавьте представление, выберите его, перейдите в его инспектор идентичности и в качестве класса укажите CircleClosing .
Ура! bRo
источник
Если вам нужен обработчик завершения, это еще одно решение, аналогичное решению Майка С., выполненному в Swift 3.0.
С помощью обработчика завершения вы можете снова запустить анимацию, рекурсивно вызывая ту же функцию, чтобы повторить анимацию заново (что будет не очень красиво), или у вас может быть обратная функция, которая будет непрерывно цепляться, пока не будет выполнено условие , например:
Чтобы сделать его еще интереснее, вы можете изменить направление анимации следующим образом:
источник
Вы можете не только создать подкласс
UIView
, но и пойти немного глубже, подклассифицироватьCALayer
Другими словами, strokeEnd в CoreAnimation в порядке. Также нормально вызывать рисование CALayer (в ctx :)
и крышка круглой линии хороша
Ключевым моментом является переопределение метода CALayer
action(forKey:)
Внутренний подкласс для CAShapeLayer
вспомогательные методы
использовать подкласс UIView с внутренним настраиваемым CALayer
Использование:
с изображением индикатора для установки угла
источник
обновление ответа @Mike S для Swift 5
работает для
frame manually
、storyboard setup
、autolayout setup
Использование :
пример кода для
frame manually
、storyboard setup
、autolayout setup
источник