Saya mencari cara untuk menganimasikan gambar lingkaran. Saya sudah bisa membuat lingkaran, tapi itu menyatukan semuanya.
Ini CircleView
kelas saya :
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);
}
}
Dan inilah cara saya menambahkannya ke hierarki tampilan di pengontrol tampilan saya:
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)
}
Adakah cara untuk menganimasikan gambar lingkaran selama 1 detik?
Contoh, sebagian animasi akan terlihat seperti garis biru pada gambar ini:
Jawaban:
Cara termudah untuk melakukannya adalah dengan menggunakan kekuatan animasi inti untuk melakukan sebagian besar pekerjaan untuk Anda. Untuk melakukan itu, kita harus memindahkan kode gambar lingkaran dari
drawRect
fungsi Anda ke aCAShapeLayer
. Kemudian, kita bisa menggunakanCABasicAnimation
untuk menghidupkanCAShapeLayer
'sstrokeEnd
properti dari0.0
ke1.0
.strokeEnd
adalah bagian besar dari keajaiban di sini; dari dokumen:Jika kita mengatur
strokeEnd
untuk0.0
, itu tidak akan menarik apa pun. Jika kita mengaturnya1.0
, itu akan menggambar lingkaran penuh. Jika kita mengaturnya menjadi0.5
, itu akan menggambar setengah lingkaran. dll.Jadi, untuk memulai, mari kita membuat
CAShapeLayer
di AndaCircleView
'sinit
fungsi dan menambahkan bahwa lapisan ke tampilan inisublayers
(juga pastikan untuk menghapusdrawRect
fungsi karena lapisan akan menggambar lingkaran sekarang):Catatan: Kami mengatur
circleLayer.strokeEnd = 0.0
agar lingkaran tidak langsung digambar.Sekarang, mari tambahkan fungsi yang bisa kita panggil untuk memicu animasi lingkaran:
Kemudian, yang perlu kita lakukan adalah mengubah
addCircleView
fungsi Anda sehingga memicu animasi saat Anda menambahkanCircleView
kesuperview
:Semua yang disatukan akan terlihat seperti ini:
Catatan: Ini tidak akan berulang seperti itu, itu akan tetap menjadi lingkaran penuh setelah dianimasikan.
sumber
strokeEnd
self.view?.layer.addSublayer(circleLayer)
:-)startAngle:
dan . adalah posisi ke-3, sehingga posisi ke-12 akan menjadi 90 ° lebih kecil dari itu, yaitu -π / 2 dalam radian. Jadi, parameternya adalah .endAngle:
UIBezierPath
0
startAngle: CGFloat(-M_PI_2), endAngle: CGFloat((M_PI * 2.0) - M_PI_2)
startAngle: (0 - (Double.pi / 2)) + 0.00001
danendAngle: 0 - (Double.pi / 2)
. JikastartAngle
danendAngle
sama, lingkaran tidak akan digambar, itulah sebabnya Anda mengurangi offset yang sangat kecil kestartAngle
Jawaban Mikes diperbarui untuk Swift 3.0
Untuk memanggil fungsi:
sumber
M_PI
tidak digunakan lagi - gunakanCGFloat.pi
saja.Jawaban Mike bagus! Cara lain yang bagus dan sederhana untuk melakukannya adalah menggunakan drawRect yang dikombinasikan dengan setNeedsDisplay (). Tampaknya lamban, tetapi tidak :-)
Kami ingin menggambar lingkaran mulai dari atas, yaitu -90 ° dan berakhir pada 270 °. Pusat lingkaran adalah (centerX, centerY), dengan radius tertentu. CurrentAngle adalah sudut saat ini dari titik akhir lingkaran, mulai dari minAngle (-90) ke maxAngle (270).
Di drawRect, kami menentukan bagaimana lingkaran seharusnya ditampilkan:
Masalahnya adalah saat ini, karena currentAngle tidak berubah, lingkarannya statis, dan bahkan tidak muncul, karena currentAngle = minAngle.
Kami kemudian membuat timer, dan setiap kali timer itu menyala, kami meningkatkan currentAngle. Di bagian atas kelas Anda, tambahkan waktu antara dua kebakaran:
Di init Anda, tambahkan timer:
Kita dapat menambahkan fungsi yang akan dipanggil saat pengatur waktu menyala:
Sayangnya, saat menjalankan aplikasi, tidak ada yang ditampilkan karena kami tidak menentukan sistem yang harus digambar lagi. Ini dilakukan dengan memanggil setNeedsDisplay (). Berikut adalah fungsi pengatur waktu yang diperbarui:
_ _ _
Semua kode yang Anda butuhkan diringkas di sini:
Jika Anda ingin mengubah kecepatan, cukup ubah fungsi updateTimer, atau kecepatan pemanggilan fungsi ini. Juga, Anda mungkin ingin membatalkan pengatur waktu setelah lingkaran selesai, yang saya lupa lakukan :-)
NB: Untuk menambahkan lingkaran di storyboard Anda, cukup tambahkan tampilan, pilih, buka Identity Inspector , dan sebagai Class , tentukan CircleClosing .
Bersulang! bRo
sumber
Jika Anda menginginkan penangan penyelesaian, ini adalah solusi lain yang serupa dengan yang dilakukan oleh Mike S, dilakukan di Swift 3.0
Dengan penangan penyelesaian, Anda dapat menjalankan animasi lagi baik dengan memanggil fungsi yang sama secara rekursif untuk melakukan animasi lagi (yang tidak akan terlihat bagus), atau Anda dapat memiliki fungsi terbalik yang akan terus berantai hingga kondisi terpenuhi , sebagai contoh:
Untuk membuatnya lebih menarik, Anda dapat mengubah arah animasi seperti ini:
sumber
Tidak hanya Anda yang dapat membuat subkelas
UIView
, Anda juga bisa sedikit lebih dalam, subkelasCALayer
Dengan kata lain, strokeEnd CoreAnimation baik-baik saja. Untuk memanggil undian CALayer (di ctx :) sering juga OK
dan topi garis bundar bagus
Poin kuncinya adalah mengganti metode CALayer
action(forKey:)
Subkelas internal untuk CAShapeLayer
metode pembantu
menggunakan subclass UIView, dengan CALayer kustom internal
Pemakaian:
dengan gambar indikator untuk mengatur sudut
sumber
memperbarui jawaban @Mike S untuk Swift 5
bekerja untuk
frame manually
、storyboard setup
、autolayout setup
Penggunaan:
kode contoh untuk
frame manually
、storyboard setup
、autolayout setup
sumber