Giter Club home page Giter Club logo

swiftuicharts's Introduction

SwiftUICharts

A charts / plotting library for SwiftUI. Works on macOS, iOS, watchOS, and tvOS and has accessibility and Localization features built in.

Demo Project

Documentation

Working on a Version 3 with a more SwiftUI feel to the API.

Chart Types

Line Charts

Line Chart

Example of Line Chart

Uses LineChartData data model.

LineChart(chartData: LineChartData)

Filled Line Chart

Example of Filled Line Chart

Uses LineChartData data model.

FilledLineChart(chartData: LineChartData)

Multi Line Chart

Example of Multi Line Chart

Uses MultiLineChartData data model.

MultiLineChart(chartData: MultiLineChartData)

Ranged Line Chart

Example of Ranged Line Chart

Uses RangedLineChart data model.

RangedLineChart(chartData: RangedLineChartData)

Bar Charts

Bar Chart

Example of Bar Chart

Uses BarChartData data model.

BarChart(chartData: BarChartData)

Range Bar Chart

Example of Range Bar Chart

Uses RangedBarChartData data model.

RangedBarChart(chartData: RangedBarChartData)

Grouped Bar Chart

Example of Grouped Bar Chart

Uses GroupedBarChartData data model.

GroupedBarChart(chartData: GroupedBarChartData)

Stacked Bar Chart

Example of Stacked Bar Chart

Uses StackedBarChartData data model.

StackedBarChart(chartData: StackedBarChartData)

Pie Charts

Pie Chart

Example of Pie Chart

Uses PieChartData data model.

PieChart(chartData: PieChartData)

Doughnut Chart

Example of Doughnut Chart

Uses DoughnutChartData data model.

DoughnutChart(chartData: DoughnutChartData)

Documentation

Installation

Swift Package Manager

File > Swift Packages > Add Package Dependency...
import SwiftUICharts

If you have trouble with views not updating correctly, add .id() to your View.

LineChart(chartData: LineChartData)
    .id(LineChartData.id)

View Modifiers

The order of the view modifiers is some what important as the modifiers are various types of stacks that wrap around the previous views.


All Chart Types

Touch Overlay

Detects input either from touch of pointer. Finds the nearest data point and displays the relevent information where specified.

The location of the info box is set in ChartStyle -> infoBoxPlacement.

.touchOverlay(chartData: CTChartData, specifier: String, unit: TouchUnit)
  • chartData: Chart data model.
  • specifier: Decimal precision for labels.
  • unit: Unit to put before or after the value.

Setup within Chart Data --> Chart Style


Info Box

Displays the information from Touch Overlay if InfoBoxPlacement is set to .infoBox.

The location of the info box is set in ChartStyle -> infoBoxPlacement.

.infoBox(chartData: CTChartData)
  • chartData: Chart data model.

Floating Info Box

Displays the information from Touch Overlay if InfoBoxPlacement is set to .floating.

The location of the info box is set in ChartStyle -> infoBoxPlacement.

.floatingInfoBox(chartData: CTChartData)
  • chartData: Chart data model.

Header Box

Displays the metadata about the chart, set in Chart Data -> ChartMetadata

Displays the information from Touch Overlay if InfoBoxPlacement is set to .header.

The location of the info box is set in ChartStyle -> infoBoxPlacement.

.headerBox(chartData: CTChartData)

Legends

Displays legends.

.legends()

Lays out markers over each of the data point.


Line and Bar Charts

Average Line

Shows a marker line at the average of all the data points.

.averageLine(chartData: CTLineBarChartDataProtocol,
             markerName: "Average",
             labelPosition: .yAxis(specifier: "%.0f"),
             lineColour: .primary,
             strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))
  • chartData: Chart data model.
  • markerName: Title of marker, for the legend.
  • labelPosition: Option to display the markers’ value inline with the marker.
  • labelColour: Colour of the Text.
  • labelBackground: Colour of the background.
  • lineColour: Line Colour.
  • strokeStyle: Style of Stroke.

Y Axis Point Of Interest

Configurable Point of interest

.yAxisPOI(chartData: CTLineBarChartDataProtocol,
          markerName: "Marker",
          markerValue: 123,
          labelPosition: .center(specifier: "%.0f"),
          labelColour: Color.black,
          labelBackground: Color.orange,
          lineColour: Color.orange,
          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))
  • chartData: Chart data model.
  • markerName: Title of marker, for the legend.
  • markerValue: Value to mark
  • labelPosition: Option to display the markers’ value inline with the marker.
  • labelColour: Colour of the Text.
  • labelBackground: Colour of the background.
  • lineColour: Line Colour.
  • strokeStyle: Style of Stroke.
  • Returns: A new view containing the chart with a marker line at a specified value.

X Axis Grid

Adds vertical lines along the X axis.

.xAxisGrid(chartData: CTLineBarChartDataProtocol)

Setup within ChartData -> ChartStyle.


Y Axis Grid

Adds horizontal lines along the Y axis.

.yAxisGrid(chartData: CTLineBarChartDataProtocol)

Setup within ChartData -> ChartStyle.


X Axis Labels

Labels for the X axis.

.xAxisLabels(chartData: CTLineBarChartDataProtocol)

Setup within ChartData -> ChartStyle.


Y Axis Labels

Automatically generated labels for the Y axis

.yAxisLabels(chartData: CTLineBarChartDataProtocol, specifier: "%.0f")
  • specifier: Decimal precision specifier.

Setup within ChartData -> ChartStyle.

yAxisLabelType:

case numeric // Auto generated, numeric labels.
case custom // Custom labels array

Custom is set from ChartData -> yAxisLabels


Linear Trend Line

A line across the chart to show the trend in the data.

.linearTrendLine(chartData: CTLineBarChartDataProtocol,
                 firstValue: Double,
                 lastValue: Double,
                 lineColour: ColourStyle,
                 strokeStyle: StrokeStyle)

Line Charts

Point Markers

Lays out markers over each of the data point.

.pointMarkers(chartData: CTLineChartDataProtocol)

Setup within Data Set -> PointStyle.


Filled Top Line

Adds an independent line on top of FilledLineChart.

.filledTopLine(chartData: LineChartData,
               lineColour: ColourStyle,
               strokeStyle: StrokeStyle)

Allows for a hard line over the data point with a semi opaque fill.


Examples

Line Chart

struct LineChartDemoView: View {
    
    let data : LineChartData = weekOfData()
    
    var body: some View {
        VStack {
            LineChart(chartData: data)
                .pointMarkers(chartData: data)
                .touchOverlay(chartData: data, specifier: "%.0f")
                .yAxisPOI(chartData: data,
                          markerName: "Step Count Aim",
                          markerValue: 15_000,
                          labelPosition: .center(specifier: "%.0f"),
                          labelColour: Color.black,
                          labelBackground: Color(red: 1.0, green: 0.75, blue: 0.25),
                          lineColour: Color(red: 1.0, green: 0.75, blue: 0.25),
                          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))
                .yAxisPOI(chartData: data,
                          markerName: "Minimum Recommended",
                          markerValue: 10_000,
                          labelPosition: .center(specifier: "%.0f"),
                          labelColour: Color.white,
                          labelBackground: Color(red: 0.25, green: 0.75, blue: 1.0),
                          lineColour: Color(red: 0.25, green: 0.75, blue: 1.0),
                          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))
                .averageLine(chartData: data,
                             strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))
                .xAxisGrid(chartData: data)
                .yAxisGrid(chartData: data)
                .xAxisLabels(chartData: data)
                .yAxisLabels(chartData: data)
                .infoBox(chartData: data)
                .headerBox(chartData: data)
                .legends(chartData: data, columns: [GridItem(.flexible()), GridItem(.flexible())])
                .id(data.id)
                .frame(minWidth: 150, maxWidth: 900, minHeight: 150, idealHeight: 250, maxHeight: 400, alignment: .center)
        }
        .navigationTitle("Week of Data")
    }
    
    static func weekOfData() -> LineChartData {
        let data = LineDataSet(dataPoints: [
            LineChartDataPoint(value: 12000, xAxisLabel: "M", description: "Monday"),
            LineChartDataPoint(value: 10000, xAxisLabel: "T", description: "Tuesday"),
            LineChartDataPoint(value: 8000,  xAxisLabel: "W", description: "Wednesday"),
            LineChartDataPoint(value: 17500, xAxisLabel: "T", description: "Thursday"),
            LineChartDataPoint(value: 16000, xAxisLabel: "F", description: "Friday"),
            LineChartDataPoint(value: 11000, xAxisLabel: "S", description: "Saturday"),
            LineChartDataPoint(value: 9000,  xAxisLabel: "S", description: "Sunday")
        ],
        legendTitle: "Steps",
        pointStyle: PointStyle(),
        style: LineStyle(lineColour: ColourStyle(colour: .red), lineType: .curvedLine))
        
        let metadata   = ChartMetadata(title: "Step Count", subtitle: "Over a Week")
        
        let gridStyle  = GridStyle(numberOfLines: 7,
                                   lineColour   : Color(.lightGray).opacity(0.5),
                                   lineWidth    : 1,
                                   dash         : [8],
                                   dashPhase    : 0)
        
        let chartStyle = LineChartStyle(infoBoxPlacement    : .infoBox(isStatic: false),
                                        infoBoxBorderColour : Color.primary,
                                        infoBoxBorderStyle  : StrokeStyle(lineWidth: 1),
                                        
                                        markerType          : .vertical(attachment: .line(dot: .style(DotStyle()))),
                                        
                                        xAxisGridStyle      : gridStyle,
                                        xAxisLabelPosition  : .bottom,
                                        xAxisLabelColour    : Color.primary,
                                        xAxisLabelsFrom     : .dataPoint(rotation: .degrees(0)),
                                        
                                        yAxisGridStyle      : gridStyle,
                                        yAxisLabelPosition  : .leading,
                                        yAxisLabelColour    : Color.primary,
                                        yAxisNumberOfLabels : 7,
                                        
                                        baseline            : .minimumWithMaximum(of: 5000),
                                        topLine             : .maximum(of: 20000),
                                        
                                        globalAnimation     : .easeOut(duration: 1))
        
        return LineChartData(dataSets       : data,
                             metadata       : metadata,
                             chartStyle     : chartStyle)
        
    }
}

Accessibility

Inside certain elements are additional tags to help describe the chart for VoiceOver.

See Localization of Accessibility

Localization

All labels support localization. There are, however, some hidden labels that are there to support VoiceOver. See Localization of Accessibility

Localization of Accessibility

See the localization demo in the Demo Project.


Voice over description of a datapoint when the user touches the area closest to the data point. The VoiceOver will say <chart title>, <data point value>, <data point description>.

"%@ <local_description_of_a_data_point>" = "%@, <Description of a data point>";

Read out before a poiMarker. The VoiceOver will say <p o i marker>, <marker legend title>, <marker value>.

"P-O-I-Marker" = "P O I Marker";
"Average" = "Average";

Voice over description of a poiMarker. The VoiceOver will say <P-O-I-Marker>, <marker legend title>, <marker value>.

"<local_marker_legend_title> %@" = "local_marker_legend_title, %@";

Read out before a axisLabel. The VoiceOver will say <axisLabel>, <marker value>.

"X-Axis-Label" = "X Axis Label";
"Y-Axis-Label" = "Y Axis Label";

Read out before a legend. The VoiceOver will say <chart type legend>, <legend title>.

"Line-Chart-Legend" = "Line Chart Legend";
"P-O-I-Marker-Legend" = "P O I Marker Legend";
"Bar-Chart-Legend" = "Bar Chart Legend";
"P-O-I-Marker-Legend" = "P O I Marker Legend";
"Pie-Chart-Legend" = "Pie Chart Legend";
"P-O-I-Marker-Legend" = "P O I Marker Legend";

swiftuicharts's People

Contributors

anivaros avatar ataias avatar laosb avatar simonmoser-bluesource avatar tinyjiyao avatar willdale avatar xremix avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftuicharts's Issues

Customize blank caption

So far the blank caption is "No Data" for table chart, can you make it customizable, so we can localize this hint.
截屏2021-05-18 上午11 09 10

Fix getXAxisLabels

Hi, I am using your library and found the bug on xAxisLabels at LineChartData: in case of data set like this [1,3,4,4,4], three last entries would be stacked to the end. To fix this it is better to change it to

case .chartData:
                if let labelArray = self.xAxisLabels {
                    HStack(spacing: 0) {
                        ForEach(labelArray.indices, id: \.self) { index in
                            YAxisChartDataCell(chartData: self, label: labelArray[index])
                                .foregroundColor(self.chartStyle.xAxisLabelColour)
                                .accessibilityLabel(Text("X Axis Label"))
                                .accessibilityValue(Text("\(labelArray[index])"))
                            if index != labelArray.count - 1 {
                                Spacer()
                                    .frame(minWidth: 0, maxWidth: 500)
                            }
                        }
                    }
                    .padding(.horizontal, -4)
                }
            }

P.S. sorry for posting it as an issue and not PR.

Wrong Y Label in StackedBarChart

Context

While using the library in my app, I noticed the Y Labels were odd. I investigated the demo add to see if I could reproduce the error and I noticed the following in StackedBarChartDemoView.swift:

For a given MultiBarDataSet, we can see the labels for each point just fine, but the overall Y Label has a wrong value. For instance, look at this code:

MultiBarDataSet(dataPoints: [
    MultiBarChartDataPoint(value: 100, description: "Q1 Sales", group: Group.england.data),
    MultiBarChartDataPoint(value: 500, description: "Q1 Sales", group: Group.scotland.data),
    MultiBarChartDataPoint(value: 300, description: "Q1 Sales", group: Group.wales.data),
], setTitle: "Q1"),

When I select the labels, I can see 100, 500 and 300 just fine:

image

But notice that if we sum 100 + 500 + 300, we get 900 for Q1, which does not match the chart above. For Q4, we should sum 400 + 800 + 200 = 1400, which definitely does not match the max Y Label of 800 there.

FWIW I reviewed wikipedia for Bar Charts and a random article to see if I was misunderstanding what a stacked bar chart should do, but I think I am understanding it correctly.

Metadata

This was on the demo repo on commit 75b2b878ad908b706eb8d6c10a8ecd7cef667af5 from Wed Mar 31 09:55:27 2021 +0100. I had commented a line with topLine: .maximum(of: 900), but you can see the same behaviour with this line enabled too.

Suggestion/Request - Pie Chart values < 0

When pie charts are fed values < 0 (e.g. decimals representing % summing to 1.0) the touch info box value is rounded to an int 0. Fixed by just multiplying by 100 in the case of a percentage in the view code.

Would be nice to be able to: 1) Feed in a specifier to allow for formatting of the info box number in the intended format.

Unrelated - would be nice to be able to label the slices in a way that did not require touch to display the slice value.

Food for thought.

Understanding .linearTrendLine?

Really enjoying this library! Thanks for such excellent work! 🙌

I am trying to understand .linearTrendLine. I see that it takes chartDate as a parameter, but then also takes a firstValue and lastValue. As far as I can tell the line is just a straight line drawn from firstValue to lastValue?

I was wondering if this was something you might come back to to add support for a trend line with curves more along the lines of a moving average? I also tried .averageLine but this just gave me a flat horizontal line across the data.

Thanks again for for a great library! 🍻

Set maximum baseline value.

I'd like to be able to set a maximum value for the baseline while computing the minimum value from the data points.

For example, if I set the maximum baseline value to 200, the baseline would be:

200 with data points of [250.0, 245.0, 238.0]

190 with data points of [250.0, 245.0, 238.0, 190.0]

Something like this:

enum Baseline {
    case minimum
    case minimumWithMaximum(of: Double) // New enum case
    case zero
}

var baseline: Baseline
var data = [250.0, 245.0, 238.0]
var minValue: Double

baseline = .minimumWithMaximum(of: 200)

switch baseline {
case .minimum:
minValue = data.min() ?? 0

case .minimumWithMaximum(let maximum):
    minValue = min(data.min() ?? 0, maximum)
    
case .zero:
    minValue = 0
}

print(minValue)

This would print 200.0.

Changing var data = [250.0, 245.0, 238.0] to var data = [250.0, 245.0, 238.0, 190.0] would print 190.0

Linechart not plotting correctly with large number of points

Is there some number of data points that are too much for a line chart? I'm loading 609 heart rates here, the first chart is using iOS charts and the 2nd is using SwiftUI Charts. It looks like the spike in the middle (a workout) should be tighter together). Anything I can do to fix this? 🤔
IMG_57212197C1E8-1
IMG_95BBF270A45B-1

Custom Legend for Bar Charts

Is it possible to draw a custom Legend for a bar chart?
I have many bars but only two conditions and want to place only those two conditions in a legend below the chart.
What I get is a Legend with one Item for each bar.

In the Docs it says that legends is part of BarChartData but I can't add id there.

Possible bug in Series 3 Watches?

I am seeing a crash on Apple Watch that seems to be limited to Series 3 (all running Watch OS 7) or higher. I can't tell what the cause is but it seems to be related to the metaData in SwiftUICharts, any ideas? 🤔

image

FilledLineChart inside of a NavigationView using .averageLine

Hi There,

I just wanted to say this is the best SwiftUI Chart module I've used so far. Thanks for sharing.

I am using a FilledLineChart which is wrapped inside of a navigationView. Once I use the .averageLine. The whole view starts animating from top left corner when it appears the first time. I am not sure if I made any sense but the video attached shows the behavior.

Screen.Recording.2021-04-19.at.9.23.41.PM.mov
FilledLineChart(chartData: chartData)
                                .touchOverlay(chartData: chartData, specifier: "%.0f")
                                .averageLine(chartData: chartData,strokeStyle: StrokeStyle(lineWidth: 1, dash: [5,10]))
                                .yAxisGrid(chartData: chartData)
                                .yAxisLabels(chartData: chartData)
                                .infoBox(chartData: chartData)
                                .floatingInfoBox(chartData: chartData)
                                .headerBox(chartData: chartData)
                                .legends(chartData: chartData, columns: [GridItem(.flexible()), GridItem(.flexible())])
                                .frame(minWidth: 150, maxWidth: 900, minHeight: 350, idealHeight: 350, maxHeight: 400, alignment: .center)
                                .padding()

Unable to find 'LineChartData' in Demo Code

I couldn't get once scenario to compile due to missing 'LineChartData'.

                Section(header: Text("Line Chart")) {
//                    NavigationLink(destination: LineChartDemoView()) {
//                        Text("Line Chart - Week")
//                    }

Modify text style on legend, labels etc..

If labels, legends or other string values can be modified on view layer, not the data model layer. Users may have ability to modify chart view to adapt their screen.
Also when I wanted to add price unit, near my touch overlay data but in this structure it is not easy.
I think there may be some improvements to move some properties to view layer and have a simple data model layer.

Customize dot and markerType

Please, provide an API to

customize markerType, especially color and stroke width.
customize DotStyle - ideally, accept view builder. At least change the way building dot. Now users could specify dot color and stroke. But it would be more flexible to set background color and radius and foreground color and radius.
Thanks

FloatingInfoBox was not working with MultiLineChart

This library is great! I try to use it in a current project but have some issues.

I tried to use the FloatingInfoBox with the MultiLineChart, but it made some trouble for me. For some reason it didn't show up, the Touch Overlay however worked like expected. Am I doing something wrong or is there an issue in the library? Here is my code:

MultiLineChart(chartData: MultiLineChartData(dataSets:
                                                MultiLineDataSet(dataSets: [
                                                    LineDataSet(
                                                        dataPoints:DataService.getData().monthlyWithoutIncrease,
                                                        style: LineStyle(lineColour: ColourStyle(colour: .gray), lineType: .curvedLine)
                                                    ),
                                                    LineDataSet(
                                                        dataPoints:DataService.getData().monthlyWithIncrease,
                                                        style: LineStyle(lineColour: ColourStyle(colour: Color(hex: "#54FFF2")), lineType: .curvedLine)
                                                    )
                                                ])))
    .touchOverlay(chartData: MultiLineChartData(dataSets: MultiLineDataSet(dataSets: [LineDataSet(
        dataPoints:DataService.getData().monthlyWithIncrease
        
    )])))
    .floatingInfoBox(chartData: LineChartData(dataSets: LineDataSet(dataPoints: DataService.getData().monthlyWithIncrease)))

I can only display LineChart once.

Environment: SwiftUI via Xcode 12.4

I tried to redisplay the LineChart graph with new data; but additional renderings didn't happen.

One band-aid approach is to launch another LineChart graph in place of the original for the new data.
This works; but is totally inefficient for multiple sets of data; and I still can't re-render already-rendered LineCharts().
Which means I have to have a LineChart() for EACH set of chartData.

The data is loaded from a class object and imported via @ObservedObject var dataSource = DataStuff()'s Published var.

Here's the code snippet with two different data sources:

...
 VStack {
                if dataSource.chartData != nil {
                    if graphToggle {
                    LineChart()
                        .touchOverlay(specifier: "%.2f")
                        .yAxisGrid()
                        .xAxisLabels()
                        .yAxisLabels()
                        .headerBox()
                        .legends()
                        .environmentObject(dataSource.chartData!)
                        .frame(minWidth: 300, maxWidth: 900, minHeight: 300, idealHeight: 400, maxHeight: 500, alignment: .center)
                        .padding(.all, 24)
                        .padding(.top, 12)
                    } else {
                        LineChart()
                            .touchOverlay(specifier: "%.2f")
                            .yAxisGrid()
                            .xAxisLabels()
                            .yAxisLabels()
                            .headerBox()
                            .legends()
                            .environmentObject(dataSource.chartData!)
                            .frame(minWidth: 300, maxWidth: 900, minHeight: 300, idealHeight: 400, maxHeight: 500, alignment: .center)
                            .padding(.all, 24)
                            .padding(.top, 12)
                    }
                    Spacer()
                }
                Spacer()
                ...

Do you know how I can reuse this code with fresh data within SwiftUI?

P.S. I tried to create a replacement instance of LineChart() for the new graph; doesn't work:

Button {
                   lineChart = nil
                   lineChart = LineChart()
                   dataSource.loadChartData1()
}

Left and right y-axis

Related to #67, if 2 data sets require different scales, either with a grouped bar chart or multi-line chart, supporting a left and right y-axis would be super handy.

Hey @UncleRic, I had a similar issue.

Hey @UncleRic, I had a similar issue.
Try @willdale's solution on the issue #5

@State var selectedGraph = ""  // <---- the binding of that wheel picker

@State var data = ChartData(dataPoints: []) 


func chartDataPoints() -> [dataPoint] {
   ....
}



....


LineChart()
            .touchOverlay(specifier: "%.2f")
            .yAxisGrid()
            .xAxisLabels()
            .yAxisLabels()
            .headerBox()
            .legends()
            .environmentObject(data)
            .id(UUID())     // <---- add an id to the chart

           // Re-Initialise data at `onAppear`
          .onAppear {
              data.dataPoints = chartDataPoints()
          }

          // Update the data of the chart whenever the user selects something else from the wheel picker.
          .onChange(of: selectedGraph, perform: { value in
            data.dataPoints = chartDataPoints()
          })

In addition to @willdale's solution, add an id to the chart to force it to refresh when something changes.

Originally posted by @USBA in #7 (comment)

Legend not showing all values on stacked bar chart

I have a chart where i stack 5 different values. On the demo app, I can see all 3 legends being displayed on the graph (England, Wales & Scotland). But when I try to adapt to my data, I can only show 2 of the 5 in the legend.

Note: This is the legend only, the stacked graph is showing all 5 correctly.

BarChartStyle xAxisLabelsFrom dataPoints not showing?

I noticed in your demo project for a ranged bar chart, you hard code the xAxisLabels xAxisLabels: ["00:00", "12:00", "00:00"] but I would like to load them dynamically from my data points as in xAxisLabelsFrom : .dataPoint(rotation: .degrees(0)) but they aren't showing up. Am I doing something wrong or is this not possible yet? Here is a gist of my code, apologies for the cruft, work in progress...

https://gist.github.com/gesabo/9dc3758cd167544c953953e70a31b4b6

Build inline docstrings into docs website

Much of this library has docstrings. It would be nice to be able to see those presented nicely in a docs website.

The actual publishing of that website for new versions of the library (using e.g. GitHub actions) can be a different piece of work

Feature Request: Table view

Sometimes it's good to display the data table under the graph. Is there a way to achieve this with this library?

Install issue

I'm getting an error when I install SwiftUICharts which is:

"the Package.resolved file is most likely severely out-of-date and is preventing correct resolution; delete the resolved file and try again."

X Axis labels overlapping

What would be the best solution to fit everything? The data I'm using has 12 data points with time increment of 5 mins. Is there a way to tilt the labels or use only a few labels out of the 12 spread out in the x-axis?

xAxisLables

Chart does not refresh on State change

My enter view refreshes on @State change except the chart.

@State var component: Calendar.Component = .month
@State var periodCount: Int = 0

The chart does not refresh until I drag on it.

Screen.Recording.2021-02-03.at.7.59.39.PM.mov
LineChart()
           .touchOverlay()
           .xAxisGrid()
           .yAxisGrid()
           .xAxisLabels()
           .yAxisLabels()
           .environmentObject(
                      ChartData(dataPoints : chartDataPoints(periodChange: periodCount, periodComponent: component) )
            )
            .frame(height: horizontalSizeClass == .compact ? 200 : 250)
            .padding()

Please fix this.
Thanks so much for this amazing SwiftUI library.

Top of bar charts have deformation

Because the corner radius is set before the stretching is applied, longer bars have more corner radius than shorter bars.

Not sure how to approach this, maybe stretch first, then apply the corner radius (if I tried this, I didn't get any rectangle). Other approach might be to apply a different corner radius for x and y, and not use a circle to make the corner, but use an ellipse?

Screenshot attached for clarity:

IMG_D14A82E2258D-1

FilledLineChart stroke

I am trying to draw FilledLineChart with a solid stroke on the top.
Something like this
image

Is it possible to do with your lib?

Space Between Bars (Issue with many Bars)

Hi,

first of all: Great Library! It's by far the most flexible out there in pure SwiftUI!

I ran into one issue with the bar chart, that is hopefully easy to fix although I didn't find the right place, yet.

If you have many data points the bars extend the space of the diagram. You can transform the bars as such by giving it a bar width <1 but that leads to huge spaces between the bars (of course). Is there a way to make the entire bars "thinner"?

Examples

Not so many bars
image

Bildschirmfoto 2021-05-05 um 19 08 50

Kind regards!

X-Axis labels truncate

The label text truncates, makes it a little harder to read at a glance as users would have to tap each bar to see the full text. Would be great to have an option to display X-axis labels rotated at n-degrees and showing full text (no truncating)

Combined bar and line chart

Working with 2 data sets that should be displayed with a bar chart the grouped chart is perfect. Is it possible with the current setup to display a bar chart with a line chart overlaid?

Grid disappears after navigating away and returning to a view containing a chart

SwiftUICharts-Grid.mp4
import SwiftUI
import SwiftUICharts

struct ProgressMain: View {
    let data : ChartData = weekOfData()
        
    var body: some View {

            LineChart()
                .xAxisGrid()
                .yAxisGrid()
                .xAxisLabels()
                .yAxisLabels()
                .environmentObject(data)
                .frame(height: 200, alignment: .center)
                .padding()
    }
}

extension ProgressMain {
    
    static func weekOfData() -> ChartData {
        
        let data : [ChartDataPoint] = [
            ChartDataPoint(value: 20, xAxisLabel: "Jun 18"),
            ChartDataPoint(value: 90),
            ChartDataPoint(value: 100),
            ChartDataPoint(value: 75),
            ChartDataPoint(value: 160),
            ChartDataPoint(value: 110),
            ChartDataPoint(value: 90, xAxisLabel: "Sep 20")
        ]
        
        let gridStyle = GridStyle(numberOfLines : 6,
                                  lineColour    : Color(.lightGray).opacity(0.25),
                                  dash          : [4])
        
        let chartStyle = ChartStyle(xAxisGridStyle      : gridStyle,
                                    yAxisGridStyle      : gridStyle,
                                    yAxisNumberOfLabels : 1)
        
        let lineStyle = LineStyle(colour      : .accent,
                                  lineType    : .line,
                                  strokeStyle : StrokeStyle(lineWidth: 3, lineCap: .round, lineJoin: .round))
        
        return ChartData(dataPoints : data,
                         chartStyle : chartStyle,
                         lineStyle  : lineStyle)
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.