Swift Charts

RSS for tag

Visualize data with highly customizable charts across all Apple platforms using the compositional syntax of SwifUI.

Swift Charts Documentation

Posts under Swift Charts tag

53 Posts
Sort by:
Post not yet marked as solved
7 Replies
3k Views
Is there a way to create scrolling/paging behavior in the charts just like is done in the Health app? I have a similar app that also displays health data (such as heart rate and steps) and with my current custom charts the user can page back to see data from previous weeks (by default it shows the current week). Just like in the health app the user can go back as long as there is data, which can be several years (so hundreds go pages). I'd love to replace my custom implementation with Swift Charts but for that I do need this scrolling behavior.
Posted
by
Post not yet marked as solved
4 Replies
1.9k Views
I have a dataset I want to have split between past/historic data and future/predicted data. The values for the predicted data take the last value from pastData and apply a decay function to show how much of something is left. I have the data split into two arrays (sampleData_History and sampleData_Future); I have also attempted this with the data combined (sampleData) and tried a conditional in the .foregroundStyle property. Chart { ForEach(sampleData_History) { item in RuleMark(x: .value("Now", Date.now, unit: .hour)).foregroundStyle(.orange) LineMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ) .foregroundStyle(Color.blue) AreaMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ).foregroundStyle(Color.teal.opacity(0.2)) } ForEach(sampleData_Future) { item in LineMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ) .foregroundStyle(Color.red) AreaMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ).foregroundStyle(Color.red.opacity(0.2)) } } The above code yields the screenshot below. In the ideal case, I'd like to have everything AFTER the RuleMark line be a different color. Am I missing something? Where might I look to figure this out? EDIT: I have also tried separating them into series to no avail
Posted
by
Post not yet marked as solved
9 Replies
3.1k Views
I'm experiencing a problem where my NavigationLink hangs when on the same view as a somewhat complicated chart. Additional Context: My Swift Chart has a fair number of data points (2000+). I'm also doing custom modification using the .chartYAxis modifier. .chartYAxis { AxisMarks(values: .stride(by: 1)) { value in            AxisGridLine()            AxisTick()            // In my app I also put a value label here, but that doesn't seem to be the thing in particular that slows this down.      } } When I do this modifier along with having a big set of data points, if I have a NavigationLink elsewhere on the same view, it hangs when I press the NavigationLink. Notably, if I remove this modifier, it doesn't hang. (By hang I mean it takes about 1s to navigate to the next view). Here's a slightly contrived example that mirrors my actual app, minus the generation of data points: import SwiftUI import Charts struct ContentView: View {     var body: some View {         NavigationStack {             NavigationLink(value: "NavigationKey") {                 Text("Link")             }             ChartView()             Text("Main View")                 .navigationDestination(for: String.self) { path in                     SomeView()                 }         }     } } struct ChartView: View {     var chartXY: [(x: Double, y: Double)] {         var entries: [(x: Double, y: Double)] = []         for i in 0..<2500             let y = Double.random(in: 0..<8000)             entries.append((x: Double(i), y: y))         }         return entries     }          var body: some View {         List {             Chart {                 ForEach(chartXY, id: \.x) {                     LineMark(x: .value("x", $0.x), y: .value("y", $0.y))                 }             }             .frame(minHeight: 100.0)             // Commenting out this block == no hang             .chartYAxis {                 AxisMarks(values: .stride(by: 1)) { value in                     AxisGridLine()                     AxisTick()                     // In my app I also put a value label here, but that doesn't seem to be the thing in particular that slows this down.                 }             }         }     } } struct SomeView: View {     var body: some View {         Text("hello")     } } Presumably, given commenting out the block solves the problem, SwiftUI is preparing some large amounts of AxisMarks/GridLines/AxisTicks for the view transition. Is there someway for me to indicate that it shouldn't do that to prevent this problem? Or is there some other reason this would be hanging?
Posted
by
Post not yet marked as solved
4 Replies
1.8k Views
In a Swift Chart that listens for drag gestures in order to display a RuleMark with an annotation, the y-axis scale changes while dragging which causes the entire chart to jump. I have a small code example that demonstrates this at https://github.com/mvolkmann/ChartJump. See the two screenshots there.
Posted
by
Post not yet marked as solved
1 Replies
1.5k Views
Hi, im building a swiftui chart for showing hours per day. it works fine. but I want to display a whole week even if there is no data on several days. it is based on core data. does anyone know how to modify x axis to show always the full week? thx Chris Chart { ForEach(zeiten, id: \.self.startdatum?.weekDay) { zeit in BarMark( x: .value("day", zeit.startdatum ?? Date(), unit: .day), yStart: .value("Low", zeit.startzeit?.timeDouble ?? 0), yEnd: .value("High", zeit.endzeit?.timeDouble ?? 0)) } .cornerRadius(8) .foregroundStyle(.userGreen) } .frame(width: geometry.size.width*0.75, height: 90) .padding() .chartYScale(domain: 0...24) .chartXAxis { AxisMarks(values: .stride(by: .day, count: 1)) { _ in AxisValueLabel(format: .dateTime.weekday(.narrow)) AxisGridLine() AxisTick() } }
Posted
by
Post not yet marked as solved
1 Replies
962 Views
Hi there, When using the AxisValueLabel in Swift Charts, the moment you add centered: true, the month or day on the right disappears. This has been a bug for over five months since I looked through other developer forums and they had the same issue. AxisValueLabel(format: .dateTime.weekday(), centered: true) leads to the following view: Now if we remove the centered: true, saturday will appear. It is probably a spacing issue, but since these are modifiers provided by Apple, it should do it correctly, right? If I am missing something and this is by desing, please enlighten me. Best Til
Posted
by
Post marked as solved
3 Replies
1.5k Views
I have a view that displays a chart based on an array. Each element in the array is all of the attributes associated with a core data entity. The data is properly displayed. I would like to animate the rendering of the charts data but cannot seem to figure out how to do it. If someone could point me in the right direction it would be appreciated. Below is the code. struct ClosingValuesChart: View { @State private var selectedDate: Date? = nil @State private var selectedClose: Float? = nil @State private var xAxisLabels: [Date] = [] var closingValues: [TradingDayClose] = [] var heading: String = "" init(fundName: String, numYears: Int, closingValues: [TradingDayClose]) { self.heading = fundName + String(" - \(numYears) Year") self.closingValues = closingValues } var body: some View { GroupBox (heading) { let xMin = closingValues.first?.timeStamp let xMax = closingValues.last?.timeStamp let yMin = closingValues.map { $0.close }.min()! let yMax = closingValues.map { $0.close }.max()! let xAxisLabels: [Date] = GetXAxisLabels(xMin: xMin!, xMax: xMax!) var yAxisLabels: [Float] { stride(from: yMin, to: yMax + ((yMax - yMin)/7), by: (yMax - yMin) / 7).map { $0 } } Chart { ForEach(closingValues) { value in LineMark( x: .value("Time", value.timeStamp!), y: .value("Closing Value", value.close) ) .foregroundStyle(Color.blue) .lineStyle(StrokeStyle(lineWidth: 1.25)) } } .chartXScale(domain: xMin!...xMax!) .chartXAxisLabel(position: .bottom, alignment: .center, spacing: 25) { Text("Date") .textFormatting(fontSize: 14) } .chartXAxis { AxisMarks(position: .bottom, values: xAxisLabels) { value in AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) AxisValueLabel(anchor: .top) { if value.as(Date.self) != nil { Text("") } } } } .chartYScale(domain: yMin...yMax) .chartYAxisLabel(position: .leading, alignment: .center, spacing: 25) { Text("Closing Value") .font(Font.custom("Arial", size: 14)) .foregroundColor(.black) } .chartYAxis { AxisMarks(position: .leading, values: yAxisLabels) { value in AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) AxisValueLabel() { if let labelValue = value.as(Double.self) { Text(String(format: "$ %.2f", labelValue)) .textFormatting(fontSize: 12) } } } } .chartOverlay { proxy in GeometryReader { geometry in ChartOverlayRectangle(selectedDate: $selectedDate, selectedClose: $selectedClose, proxy: proxy, geometry: geometry, xMin: xMin!, xMax: xMax!, closingValues: closingValues) } } .overlay { XAxisDates(dateLabels: xAxisLabels) } .overlay { DateAndClosingValue(selectedDate: selectedDate ?? Date(), selectedClose: selectedClose ?? 0.0) } } .groupBoxStyle(ChartGroupBoxStyle()) } }
Posted
by
Post not yet marked as solved
0 Replies
319 Views
Hi all, I'm trying to implement a dynamic chart to log weight over time for an espresso app. I've been struggling to find recourses to plot a continuously updating chart so, I'm currently using a timer to append new data to an array and then redraw the chart. Thats all working fine but, I'm getting 1GB< Memory usage after appending only 15 seconds worth of data at 10 datapoints/second. I would love to find a way to optimise this. Here is my main View Controller. There is some connect to scale stuff in there but, for testing I'm bypassing the scale data. All I'm doing is upon opening the view I'm: starting a counter, converting the counter to a min, sec ,millisec value, appending time information from my counter to the array, appending a random value from 1-10 as my mock weight data to the array, calling my chart view because it lives in a different file import UIKit import AcaiaSDK import SwiftUI import Charts var cList: [weight_time] = [] var timer: Timer! var count: Double! var timeInDouble: Double! var isCounting: Bool! var hideview: Bool = true class ChartVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { } override func viewDidAppear(_ animated: Bool) { timeInDouble = 0 count = 0 createTimer() print("Timer Started") isCounting = true } override func viewWillDisappear(_ animated: Bool) { if isCounting == true { timer.invalidate() print("Timer Stopped") isCounting == false } } func createTimer(){ cList.removeAll() timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(counter), userInfo: nil, repeats: true) } @objc func counter(){ count += 0.1 let minutes = Int(count) / 60 % 60 let seconds = Int(count) % 60 let mil = Int(count*10) % 10 //print(mil) let m_s = String(format:"%02i.%02i%01i", minutes, seconds,mil) timeInDouble = Double(m_s) //if mil == 1 { fillChart() // } print(timeInDouble!) } func fillChart(){ cList.append(weight_time(weight: Float(.random(in: 1...10)) , time: timeInDouble)) setupView() } // MARK: test Chart import func setupView(){ let controller = UIHostingController(rootView: chartvalues()) guard let chartView = controller.view else{ return } view.addSubview(chartView) controller.view.isHidden = false chartView.snp.makeConstraints{make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(15) make.trailing.equalToSuperview().inset(15) make.height.equalTo(300) } } } import Charts import Foundation import AcaiaSDK import UIKit struct weight_time:Identifiable { let id = UUID() let weight: Float let time: Double } struct chartvalues: View{ let testList = [ weight_time( weight: 0.0, time: 0.5), weight_time(weight: 0.5, time: 1.0), weight_time(weight: 1.2, time: 1.5), weight_time(weight: 1.72, time: 2.0), weight_time(weight: 2.8, time: 2.5), weight_time(weight: 3.0, time: 3.0), weight_time(weight: 4.25, time: 3.5), weight_time(weight: 4.94, time: 4.0), weight_time(weight: 5.62, time: 4.5), weight_time(weight: 6.6, time: 5.0) ] var body: some View{ if cList != nil { Chart(cList){ weight_time in LineMark( x: .value("Time", weight_time.time), y: .value("Weight", weight_time.weight) ).foregroundStyle(.red) } } //Text(cList) } }```
Posted
by
Post not yet marked as solved
2 Replies
1.2k Views
I have a scrollable barmark chart that is introduced in iOS 17 but I have problem to set the initial horizontal scroll position. I want to use the ".chartScrollPosition(initialX:..." but initialX needs to be of type Plottable I can't understand how I can define that. Here is an example, I want it to scroll to the far right (newest days). I show seven days at a time. import SwiftUI import Charts struct ContentView: View { let stepDays: [StepDay] = [ StepDay(date: Calendar.current.date(byAdding: .day, value: -10, to: Date())!, steps: 12342), StepDay(date: Calendar.current.date(byAdding: .day, value: -9, to: Date())!, steps: 8345), StepDay(date: Calendar.current.date(byAdding: .day, value: -8, to: Date())!, steps: 7656), StepDay(date: Calendar.current.date(byAdding: .day, value: -7, to: Date())!, steps: 4564), StepDay(date: Calendar.current.date(byAdding: .day, value: -6, to: Date())!, steps: 2344), StepDay(date: Calendar.current.date(byAdding: .day, value: -5, to: Date())!, steps: 7654), StepDay(date: Calendar.current.date(byAdding: .day, value: -4, to: Date())!, steps: 4532), StepDay(date: Calendar.current.date(byAdding: .day, value: -3, to: Date())!, steps: 6788), StepDay(date: Calendar.current.date(byAdding: .day, value: -2, to: Date())!, steps: 4567), StepDay(date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!, steps: 5678), StepDay(date: Date(), steps: 1234)] var body: some View { Chart { ForEach(stepDays, id: \.date) { stepDay in BarMark( x: .value("Day", stepDay.weekDay), y: .value("Steps", stepDay.steps) ) } } .chartScrollableAxes(.horizontal) .chartXVisibleDomain(length: 7) // .chartScrollPosition(initialX: <#T##Plottable#>) // I want to scroll to far right so that I can see the newest days, can I do that with chartScrollPosition(initialX:... ??? } } struct StepDay { var date: Date var weekDay: String var steps: Int init(date: Date, steps: Int) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "d/M" self.date = date self.weekDay = dateFormatter.string(from: date) self.steps = steps } }
Post not yet marked as solved
0 Replies
471 Views
I have created Swift Charts using Ready Made Data Like below static let last12Months = [ (month: date(year: 2022, month: 6), KW: 3952, dailyAverage: 127, dailyMin: 95, dailyMax: 345), (month: date(year: 2022, month: 7), KW: 8322, dailyAverage: 124, dailyMin: 55, dailyMax: 255), (month: date(year: 2022, month: 8), KW: 2952, dailyAverage: 245, dailyMin: 99, dailyMax: 673), (month: date(year: 2022, month: 9), KW: 3352, dailyAverage: 875, dailyMin: 92, dailyMax: 623), (month: date(year: 2022, month: 10), KW: 3252, dailyAverage: 257,dailyMin: 55, dailyMax: 675), (month: date(year: 2022, month: 11), KW: 3232, dailyAverage: 537,dailyMin: 65, dailyMax: 643), (month: date(year: 2022, month: 12), KW: 9871, dailyAverage: 253,dailyMin: 25, dailyMax: 987), (month: date(year: 2023, month: 1), KW: 8623, dailyAverage: 235, dailyMin: 96, dailyMax: 353), (month: date(year: 2023, month: 2), KW: 7612, dailyAverage: 276, dailyMin: 64, dailyMax: 765), (month: date(year: 2023, month: 3), KW: 2335, dailyAverage: 978, dailyMin: 36, dailyMax: 456), (month: date(year: 2023, month: 4), KW: 9087, dailyAverage: 667, dailyMin: 63, dailyMax: 675), (month: date(year: 2023, month: 5), KW: 2823, dailyAverage: 865, dailyMin: 100, dailyMax: 765), (month: date(year: 2023, month: 6), KW: 9762, dailyAverage: 544, dailyMin: 36, dailyMax: 999), ] `but now I want to create same charts with real world reading like Health App. For example aim taking the sensor value through bluetooth, I can show the reading from sensor to app but how can I store the data for months and show them in Charts Any Ideas where am I lagging`
Posted
by
Post not yet marked as solved
0 Replies
832 Views
@Apple: Would it be possible to get the source of the Sample app shown in WWDC 2023 session “Explore pie charts and interactivity in Swift Charts” https://developer.apple.com/wwdc23/10037 In particular I’m interested in learning how to get the dates of currently be viewed bar marks in a scroll view. You can see that in the video at 9:12 on the iPhone screen showing the demo app.
Posted
by
Post not yet marked as solved
2 Replies
1.2k Views
Hi There, Same data shows different line drawing. What I am missing here ? Each time I click to see chart, its drawing is different. Chart{ ForEach(data) { series in ForEach(series.data){ entry in LineMark( x: .value("Day", entry.day), y: .value("Amount", entry.amount) ) .foregroundStyle(by: .value("Doc", series.Doc)) .symbol(by: .value("Doc", series.Doc)) PointMark( x: .value("Day", entry.day), y: .value("Sales", entry.amount) ) .foregroundStyle(.purple) .symbolSize(symbolSize) } .lineStyle(StrokeStyle(lineWidth: lineWidth)) } } .chartLegend(position: .top) .chartYScale(domain: .automatic(includesZero: false)) .chartXAxis { AxisMarks(values: .automatic(roundLowerBound: false, roundUpperBound: false)) { value in if value.index < value.count - 1 { AxisValueLabel() } AxisTick() AxisGridLine() } }
Posted
by
Post not yet marked as solved
0 Replies
891 Views
I like to have a scrollable chart with chartXSelection. How can that be accomplished? As soon as I have .chartXSelection the chart doesn't really scroll any more. I'm looking for some sort of delayed chartXSelection gesture, where the chartXSelection kicks in after a short delay of 1-2 seconds. The Apple Heath App does support this very nicely.
Posted
by
Post not yet marked as solved
2 Replies
457 Views
When using charts framework to make a Bar Chart after creating my fake data and creating the chart in the contentView no x or y axis contents appeared I was following a tutorial and they appeared with him any one can help Bar Chart import SwiftUI import Charts struct Items : Identifiable { var id = UUID() let type : String let value : Double } struct ContentView: View { let items : [Items] = [ Items(type: "Medical", value: 10000), Items(type: "Engeneering", value: 5000), Items(type: "singing", value: 15000), Items(type: "pilot", value: 1000), Items(type: "athlete", value: 18000), ] ![]("https://developer.apple.com/forums/content/attachment/73dd58fb-2753-4d65-be30-ad4ae7ebb1be" "title=Screen Shot 2023-07-10 at 6.19.04 AM.png;width=854;height=1598") var body: some View { NavigationView{ ScrollView{ Chart(items){item in BarMark( x: .value("Job", item.type), y: .value("salary", item.value) ) .foregroundStyle(.brown) .cornerRadius(10) } .frame(height: 200) .padding() } .navigationTitle("Charts") } }
Posted
by
Post not yet marked as solved
3 Replies
1.5k Views
When using the new iOS “chartScrollableAxes” feature annotation that should show on top of the chart view no longer work. When disabling “chartScrollableAxes” everything works again. Filed as FB12584128 import SwiftUI import Charts class ChartDataEntry:Identifiable { var date:Date var value:Double init(date:Date, value: Double) { self.date=date self.value=value } } struct ContentView: View { @State var rawSelectedDate: Date? var chartData = [ChartDataEntry(date: Date().yesterday.yesterday.yesterday.yesterday.startOfDay, value: 10.0), ChartDataEntry(date: Date().yesterday.yesterday.yesterday.startOfDay, value: 20.0), ChartDataEntry(date: Date().yesterday.yesterday.startOfDay, value: 30.0), ChartDataEntry(date: Date().yesterday.startOfDay, value: 40.0), ChartDataEntry(date: Date().startOfDay, value: 50.0)] var body: some View { VStack { Chart(chartData) { entry in BarMark( x: .value("Day", entry.date, unit: .day), y: .value("Values", entry.value) ) if let selectedDate { RuleMark( x: .value("Selected", selectedDate, unit: .day)) .foregroundStyle(Color.gray.opacity(0.3)) .offset(yStart: -10) .zIndex(-1) .annotation(position: .top, spacing: -10, overflowResolution: .init( x: .fit(to: .chart), y: .disabled ) ) { Text("Longer Sample Text") } } } .chartScrollableAxes(.horizontal) // <<--- when this is disabled the annotation will be shown correctly .chartXSelection(value: $rawSelectedDate) .frame(height: 300) } .padding() } var selectedDate: Date? { guard let rawSelectedDate else { return nil } return chartData.first(where: { let endOfDay = $0.date.endOfDay return ($0.date ... endOfDay).contains(rawSelectedDate) })?.date } } #Preview { ContentView() } extension Date { var yesterday: Date { return Calendar.current.date(byAdding: .day, value: -1, to: self)! } var startOfDay: Date { return Calendar.current.startOfDay(for: self) } var endOfDay: Date { var components = DateComponents() components.day = 1 components.second = -1 return Calendar.current.date(byAdding: components, to: startOfDay)! } }
Posted
by
Post not yet marked as solved
0 Replies
616 Views
Does anyone know of to get the currently visible data items in chart (e.g. BarMarks) on iOS 17 when using chartScrollableAxes. From the WWDC23 video of session "Explore pie charts and interactivity in Swift Charts" at time 8:18 you see that the "Total sales" lists the visible time frame (e.g. May 4 - June 4, 2023) and a few seconds late when the chart scrolls the values do update.
Posted
by
Post not yet marked as solved
0 Replies
441 Views
How to scale LineMark to fill all chart automatically? Here is my sample: import SwiftUI import Charts struct EnergyView: View { var body: some View { VStack { Chart { ForEach(DailyEnergy.mockData) { dailyEnergy in LineMark(x: .value("Data", dailyEnergy.date), y: .value("Value", dailyEnergy.energy)) PointMark(x: .value("Data", dailyEnergy.date), y: .value("Value", dailyEnergy.energy)) .annotation(alignment: .center, spacing: 10) { Text("\(Int(dailyEnergy.energy))") .minimumScaleFactor(0.5) .scaledToFit() .frame(width: 40) } } .interpolationMethod(.monotone) } }.frame(height: 100) } } struct EnergyView_Previews: PreviewProvider { static var previews: some View { EnergyView() } } struct DailyEnergy: Identifiable { let id: UUID = .init() let date: Date let energy: Double } extension DailyEnergy { static var mockData: [Self] { [ .init(date: "2023-08-01".formattedDate, energy: 1376), .init(date: "2023-08-02".formattedDate, energy: 1576), .init(date: "2023-08-03".formattedDate, energy: 1875), .init(date: "2023-08-04".formattedDate, energy: 1676), .init(date: "2023-08-05".formattedDate, energy: 1475), .init(date: "2023-08-06".formattedDate, energy: 1574), .init(date: "2023-08-07".formattedDate, energy: 1674) ] } } and here is result what I have: and here is result what I'm expect: I want to build LineMark on full chart view, but how I can do this? I tried to use scalledToFill(), but it change all chart instead only LineMark, also I tried to use .chartYScale(domain: 1200...2800), but in this case I can't be sure that all chart line will be fitted to chart view including my PointMark. Maybe Charts has any function to do this?
Posted
by
Post not yet marked as solved
3 Replies
1.4k Views
I'm currently learning Swift and SwiftUI. I'm working at a MacOS app that will need to visualize a number of traces. The user must be able to scroll along the X axis of any of the traces and the other ones should be scrolling synchronously (think about a visualization similar to Apple's own "Instruments" app). I'm using SwiftUI Charts framework for visualizing the traces, this on MacOS 14.0 (beta at the time of writing) and Xcode 15 beta 6. The app is also built against the latest MacOS target (explicitly to use the new Charts functionalities). My implementation manages to correctly synchronize the scrolling of the separate charts using a binding in combination with the chartScrollPosition method, however the scrolling performance is really terrible (the scrolling movement is sluggish and jittery). If I disable the synchronization by removing the binding and chartScrollPosition calls, the charts can be scrolled independently with no performance issues. I have the feeling that I'm making some mistake in the way I used the binding, which is causing some internal loop in the UI update/drawing process. This is also supported by the logging message I get in the console when I'm scrolling: onChange(of: Optional\<CGRect\>) action tried to update multiple times per frame. I included below the code for a test app that reproduces the issue: ContentView.swift import SwiftUI struct ContentView: View { @State private var markerValue = 0.0 var body: some View { VStack { DataTraceView(markerValue: $markerValue) } .padding() } } DataTraceView.swift import SwiftUI import Charts private let SAMPLES = 10000 func generateRandomDataPoints(count: Int) -> [DataPoint] { return (0..<count).map { idx in DataPoint(id: idx, xValue: Double(idx), yValue: Double.random(in: 0..<1)) } } struct DataPoint: Identifiable { var id: Int var xValue: Double var yValue: Double } struct DataTraceView: View { @State var testVector1: [DataPoint] = generateRandomDataPoints(count: SAMPLES) @State var testVector2: [DataPoint] = generateRandomDataPoints(count: SAMPLES) @Binding var markerValue: Double var body: some View { VStack { Chart(testVector1) { LineMark( x: .value("Time", $0.xValue), y: .value("Speed", $0.yValue) ) } .chartScrollPosition(x: $markerValue) .chartXVisibleDomain(length: 15) .chartScrollableAxes(.horizontal) Chart(testVector2) { LineMark( x: .value("Time", $0.xValue), y: .value("LatG", $0.yValue) ) } .chartScrollPosition(x: $markerValue) .chartXVisibleDomain(length: 15) .chartScrollableAxes(.horizontal) } } } Any ideas about what am I doing wrong?
Posted
by
Post marked as solved
1 Replies
760 Views
I've encountered an animation glitch affecting the text for AxisMarks and AxisLabels in the SwiftUI Chart framework. Below are the sample project code and animated gif for reference: (I'm not being able to attach the gif for some reason. Here's my StackOverflow post with a the gift: https://stackoverflow.com/questions/77007744/swiftui-chart-text-animation-glitch-with-axismarks-and-axislabels) struct ContentView: View { @State var isDisplayingAge = true var body: some View { ChartView(data: ChartDataSample, isDisplayingAge: isDisplayingAge) .onTapGesture { withAnimation { isDisplayingAge.toggle() } } } } struct ChartData: Identifiable { let age: Int let presence: Int let grade: Int let id = UUID() } struct ChartView: View { let data: [ChartData] let isDisplayingAge: Bool let xAxis = [0, 50, 100] var body: some View { VStack { Chart { ForEach(data) { chartData in BarMark(x: .value("X Axis", isDisplayingAge ? chartData.age : chartData.presence), y: .value("Y Axis", chartData.grade)) } } .chartXAxis(content: { AxisMarks(position: .bottom, values: xAxis.map{$0}) { data in AxisValueLabel(String(xAxis[data.index]) + (isDisplayingAge ? " years" : " days")) } }) .chartXAxisLabel(content: { Text(isDisplayingAge ? "Data: age" : "Data: presence") }) } .padding(.horizontal, 13) } } As you can observe, when I tap the chart to trigger a content change with animation, the text for AxisMarks (e.g., x years / x days) and AxisLabels (e.g., Data: age / Data: presence) animates unusually. A portion of the text is temporarily replaced by an ellipsis ("...") during the animation. Interestingly, this issue occurs only in one direction of the animation. When transitioning from "year" to "day" or from "presence" to "age," the text simply gets replaced without any noticeable animation. Can anyone explain what's happening here? Ideally, I'd like the texts to either fade into each other or be replaced without any animation. Thank you.
Posted
by