swiftswiftuiswiftui-charts

How to add some spacing on the left and right or X axis marks in LineMark


I have a LineMark where my X axis marks are too close to the edges and a bit hard to read:

Chart {
  ForEach(numberWorkouts) { numberworkouts in
    if dateState == .weeks {
      LineMark(
        x: .value("Date", numberworkouts.date, unit: .day),
        y: .value("Total", numberworkouts.numberOfWorkouts)
      )
      .interpolationMethod(.catmullRom)
      .symbol {
        Circle()
          .fill(.blue)
          .frame(width: 7, height: 7)
      }
    } else {
      LineMark(
        x: .value("Date", numberworkouts.date, unit: .month),
        y: .value("Total", numberworkouts.numberOfWorkouts)
      )
      .symbol {
        Circle()
          .fill(.blue)
          .frame(width: 7, height: 7)
      }
    }
  }
}
.chartYAxis {
  AxisMarks(position: .leading)
}
.chartYAxisLabel(position: .leading, alignment: .center) {
}
.chartYAxis {
  AxisMarks(stroke: StrokeStyle(lineWidth: 0))
}
.chartXAxis {
  if dateState == .weeks {
    AxisMarks(preset: .aligned, values: .stride(by: .day, count: 7)) {
      AxisValueLabel(format: .dateTime.month(.twoDigits).day())
    }
  } else {
    AxisMarks(values: .stride(by: .month)) {
      AxisValueLabel(format: .dateTime.month(.abbreviated), centered: true)
    }
  }
}
//.chartForegroundStyleScale(dataType == .MaxWeight ? ["Max Weight": Color.blue] : ["One Rep Max": Color.blue] )
.chartForegroundStyleScale(["No. of Workouts": Color.blue])
.chartLegend(.visible)
.aspectRatio(1.7, contentMode: .fit)
//.padding()

17/7 too close

how do I push the 17/7 and 07/08 a bit inside, I have tried applying padding to the chart but that applies padding to the outside of the LineMark and the LineMark wont accept padding as a modifier


Solution

  • You can add an anchor parameter to AxisValueLabel.

    If you want to use different anchors depending on whether it is the first, intermediate or last value, you can use the AxisValues initializer that supports a closure for defining the axis marker content: init(preset:position:values:content:).

    The content closure receives an AxisValue as parameter and this includes the properties index and count:

    AxisMarks(values: .stride(by: .day, count: 7)) { value in
        AxisValueLabel(
            format: .dateTime.month(.twoDigits).day(),
            anchor: value.index == 0
                ? .topLeading
                : value.index == value.count - 1 ? .topTrailing : .top
        )
    }
    

    Screenshot

    For more on formatting possibilities, see Customizing axes in Swift Charts.