Graphen in Swift

Inhaltsverzeichnis

In den letzten Tagen habe ich mich mit Graphen in Swift beschäftigt. Zuerst wollte ich mich mit Balken, Linien und Kreis Graphen beschäftigen. Nach kurzer Zeit habe ich aber festgestellt, dass das Thema schwieriger ist als gedacht und habe mich vorerst auf Balkendiagramme konzentriert. 

Meine erste Vermutung

Meine erste Vermutung war, dass Apple bereits eine Klasse oder ein Framework bereitgestellt hat, um Graphen einfach anzuzeigen. Beispielsweise als ein View in SwiftUI. Das hätte dann wie folgt aussehen können.

 
				
					struct Balkendiagramm: View {
    
    let daten: [Double]
    
    var body: some View {
        
        BarChart(
            data: daten,
            barWidth: 0.7,
            barHight: 0.4,
            barCornerRadius: 0.5
        )
        .foregroundColor(.blue)
    }
}
				
			

Leider konnte ich das aber nicht finden. Ich habe zuerst angefangen in der Dokumentation zu suchen. Dort habe ich nach Graphen und Diagrammen gesucht. Gefunden habe ich aber nichts Hilfreiches. Als ich in der Dokumentation nichts gefunden habe, habe ich Google gefragt. Dort habe ich viele Tutorials und Videos gefunden. Dieser haben aber meistens etwas von Github importiert und dann damit gearbeitet. Durch diesen Import aus Github konnte man dann einen Graphen, wie oben als Beispiel gezeigt erstellen. Der Nachteil dabei ist aber, dass man dann nichts mehr im Nachhinein verändern kann, wenn die Struktur dies nicht unterstützt. Wenn man beispielsweise keinen Parameter für die Farben der einzelnen Balken übergeben kann, kann man die Farbe auch nicht ändern. Möglicherweise würde sich etwas ändern lassen, dann müsste man aber etwas am importierten Code selbst ändern.

Da mir diese Herangehensweise nicht so gut gefallen hat, habe ich weiter gesucht. Ich habe dann auch Tutorials gefunden, wie man mithilfe von SwiftUI eigenen Elementen ein Balkendiagramm erstellen kann.

SwiftUI für Graphen

Wenn man nur mit SwiftUI ein Balkendiagramm erstellen möchte, kann man dazu Rechtecke nutzen.

Folgende Struktur habe ich nun genutzt, um ein allgemeines Balkendiagramm zu erstellen.

 
				
					struct Balkendiagramm: View {

    let daten: [Double]
    let balkenBreite: Double
    let eckenRadius: Double
    let balkenFarbe: Color
    
    var body: some View {
    
        GeometryReader{ geometry in
        
            ZStack(alignment: .bottom){
            
                ForEach(daten.indices, id: \.self){ datenIndex in
                
                    let datenPunkt = daten[datenIndex]
                    let bildschirmBreite = geometry.size.width
                    let bildschirmHöhe = geometry.size.height
                    
                    Rectangle()
                        .foregroundColor(balkenFarbe)
                        .cornerRadius(eckenRadius / 2 * berechneBreite(bildschirmBreite: bildschirmBreite))
                        .frame(width: berechneBreite(bildschirmBreite: bildschirmBreite), height: bildschirmHöhe * datenPunkt)
                        .offset(x: getOffset(datenIndex: datenIndex, bildschirmBreite: bildschirmBreite), y: 0)
                
                }
            }
        }
    }
    
    func berechneBreite(bildschirmBreite: Double) -> CGFloat{
        let platzZumTeilen = bildschirmBreite * balkenBreite
        let breiteEinesBalkens = platzZumTeilen / Double(daten.count)
        return breiteEinesBalkens
    }
    
    func getOffset(datenIndex: Int, bildschirmBreite: Double) -> CGFloat {
        let indivituellerPlatz = Double(datenIndex) / Double(daten.count)
        let ersterOffset = indivituellerPlatz * bildschirmBreite
        
        let summePlatz = bildschirmBreite * (1 - balkenBreite)
        let einzelnerPlatz = summePlatz / Double(daten.count)
        let halberPlatz = einzelnerPlatz / 2
        let zweiterOffset = halberPlatz
        
        let insgesamterOffset = ersterOffset + zweiterOffset
        return insgesamterOffset
    }
}
				
			

Das Ergebnis eines solchen Graphens sieht dann wie folgt aus. 

Dieser Graph nutzt normalisierte Daten. Das bedeutet, dass jedes Element in dem Double Array zwischen 0.0 und 1.0 sein muss. 0.0 sind dann 0 % und 1.0 sind 100 %. Dadurch können alle Werte angezeigt werden. Wäre das nicht der Fall, könnte es passieren, dass einzelne Balken höher als der Bildschirm sind. Der Eckenradius ist ebenfalls als ein Double zwischen 0.0 und 1.0 angegeben. Somit hat der Nutzer mit einem kleinen iPhone die gleiche Abrundung, wie ein Nutzer mit einem großen iPhone. Der Radius wird also wieder als ein prozentualer Wert genutzt. Die Balkenbreite ist ebenfalls ein prozentualer Wert. Ist ein Balken 100 % breit, so würden sich alle Balken berühren. Wäre ein Balken 0 % breit, könnte man ihn nicht sehen. 

Diesen View kann man nun in anderen Views nutzen. Gibt man dem ganzen einen kleineren Frame, nimmt der View beispielsweise nur noch 40 % der Bildschirmhöhe ein.

Apple Health Graphen

Apple selbst ist Herausgeber der App „Health“. Diese App verwaltet mit HealthKit alle Informationen über Gesundheit und Fitness. In der App stellt Apple auch all die Daten visuell dar. Dort gibt es viele Darstellungen, die mich interessieren. Beispielsweise kann man einen Graphen zurück scrollen und erhält dann Daten aus den letzten Wochen. Oder man kann auf einen Balken drücken und erhält dann den genauen Wert des Balkens. 

Wie man also aus einem Graphen einen interaktiven Graphen macht, weiß ich noch nicht. Das würde mich aber interessieren. 

 

Mich benachrichtigen, wenn es einen neuen Beitrag gibt.

 
 
Share on whatsapp
WhatsApp
Share on email
Email
Share on linkedin
LinkedIn
Share on facebook
Facebook