ios – How can I fashion a Swift Chart Axis to have ticks above backside grid line and at all times have a begin and finish tick

ios – How can I fashion a Swift Chart Axis to have ticks above backside grid line and at all times have a begin and finish tick


I am utilizing Swift Charts to create a line chart representing inventory values over time, and I am aiming for a design with inset ticks at each month. I would like the beginning, finish, and center ticks to be bigger and embrace a label under the tick.

enter image description here

I’ve been engaged on a fast POC in Swift Charts and have managed to make the axis appear like this:

enter image description here

It is near the design, however I’ve two excellent points:

1. Spacing Between the Backside Axis Grid Line and Worth Labels

I’ve set the vertical spacing to 0, however I discover there’s about 16 factors of spacing between the underside axis grid line and the axis worth label. Setting verticalSpacing to -16 provides me the consequence I need, nevertheless it doesn’t really feel like the appropriate answer.
The place does this additional spacing come from, and the way can I repair it?

2. First and Final X-Axis Ticks with Date Labels

I need to be sure that the primary and final X-axis ticks are main ticks with the corresponding date labels. How can I be certain that these ticks are marked as main and have labels?

Related code:

import SwiftUI
import Charts

struct PlanValue: Codable, Identifiable {
    let worth: Double
    let date: Date

    var id: Date { date }
}

// Date formatter to parse the date strings
let dateFormatter: ISO8601DateFormatter = {
    let formatter = ISO8601DateFormatter()
    formatter.formatOptions = [.withFullDate]
    return formatter
}()

let fundValues: [PlanValue] = [
    PlanValue(value: 100.58, date: dateFormatter.date(from: "2023-01-30")!),
    PlanValue(value: 200.22, date: dateFormatter.date(from: "2023-01-31")!),
    PlanValue(value: 505.66, date: dateFormatter.date(from: "2023-02-28")!),
    PlanValue(value: 399.33, date: dateFormatter.date(from: "2023-03-31")!),
    PlanValue(value: 5652.37, date: dateFormatter.date(from: "2023-04-30")!),
    PlanValue(value: 5755.66, date: dateFormatter.date(from: "2023-05-31")!),
    PlanValue(value: 5850.81, date: dateFormatter.date(from: "2023-06-30")!),
    PlanValue(value: 6002.82, date: dateFormatter.date(from: "2023-07-31")!),
    PlanValue(value: 5750.62, date: dateFormatter.date(from: "2023-08-31")!),
    PlanValue(value: 5699.93, date: dateFormatter.date(from: "2023-09-30")!),
    PlanValue(value: 5820.01, date: dateFormatter.date(from: "2023-10-31")!),
    PlanValue(value: 6105.03, date: dateFormatter.date(from: "2023-11-30")!),
    PlanValue(value: 6291.02, date: dateFormatter.date(from: "2023-12-31")!),
    PlanValue(value: 6399.48, date: dateFormatter.date(from: "2024-01-31")!),
    PlanValue(value: 6544.99, date: dateFormatter.date(from: "2024-02-29")!),
    PlanValue(value: 6700.69, date: dateFormatter.date(from: "2024-03-31")!),
    PlanValue(value: 6850.57, date: dateFormatter.date(from: "2024-04-30")!),
    PlanValue(value: 6998.78, date: dateFormatter.date(from: "2024-05-31")!),
    PlanValue(value: 6400.39, date: dateFormatter.date(from: "2024-06-30")!),
    PlanValue(value: 6450.33, date: dateFormatter.date(from: "2024-07-31")!),
    PlanValue(value: 29555.39, date: dateFormatter.date(from: "2024-08-31")!),
    PlanValue(value: 30300.39, date: dateFormatter.date(from: "2024-09-30")!),
    PlanValue(value: 30836.33, date: dateFormatter.date(from: "2024-10-31")!),
    PlanValue(value: 30750.06, date: dateFormatter.date(from: "2024-11-30")!),
    PlanValue(value: 31011.97, date: dateFormatter.date(from: "2024-12-31")!),
    PlanValue(value: 32500.24, date: dateFormatter.date(from: "2025-01-29")!)
]

struct ContentView: View {
    var physique: some View {
        Chart {
            // Fund Values
            ForEach(fundValues) { planValue in
                LineMark(x: .worth("Date", planValue.date),
                         y: .worth("Worth", planValue.worth)
                )
            }
        }
        .chartXAxis {
            let numberOfMajorTicks = 3
            // Main Ticks + Labels
            AxisMarks(preset: .aligned, values: .computerized(desiredCount: numberOfMajorTicks) ) { worth in
                AxisValueLabel(format: .dateTime.month().12 months(.twoDigits), verticalSpacing: 0)
            }
            AxisMarks(preset: .inset, values:  .computerized(desiredCount: numberOfMajorTicks)) { worth in
                AxisTick(size: 16, stroke: StrokeStyle(lineWidth: 1))
                    .foregroundStyle(Shade.black)
            }

            // Minor Ticks
            AxisMarks(preset: .inset, values: .stride (by: .month)) { worth in
                AxisTick(centered: true, size: 8, stroke: StrokeStyle(lineWidth: 1))
                    .foregroundStyle(Shade.black)
            }
        }
        .chartYAxis {
            AxisMarks(preset: .aligned, values: .computerized(desiredCount: 7) ) { worth in
                let isFirstLine = worth.index == 0
                AxisGridLine(stroke: StrokeStyle(lineWidth: 1, sprint: [isFirstLine ? 0 : 4], dashPhase: 0))
                    .foregroundStyle(isFirstLine ? .black : .grey)
                AxisValueLabel(format: .foreign money(code: "GBP").notation(.compactName))
            }
        }

        .body(top: 275)
        .padding()
    }
}

#Preview {
    ContentView()
}

Leave a Reply

Your email address will not be published. Required fields are marked *