{"id":13465404,"url":"https://github.com/willdale/SwiftUICharts","last_synced_at":"2025-03-25T16:31:40.007Z","repository":{"id":37014999,"uuid":"328331242","full_name":"willdale/SwiftUICharts","owner":"willdale","description":"A charts / plotting library for SwiftUI. Works on macOS, iOS, watchOS, and tvOS and has accessibility features built in.","archived":false,"fork":false,"pushed_at":"2024-02-13T09:45:18.000Z","size":4730,"stargazers_count":828,"open_issues_count":56,"forks_count":101,"subscribers_count":17,"default_branch":"main","last_synced_at":"2024-07-31T15:01:27.242Z","etag":null,"topics":["bar-chart","chart","charts","doughnut-chart","filled-line-chart","graph","grouped-bar-chart","ios","line-chart","macos","multi-line-chart","pie-chart","range-bar-chart","stacked-bar-chart","swift","swiftui","tvos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/willdale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"willdale"}},"created_at":"2021-01-10T07:53:19.000Z","updated_at":"2024-07-27T16:42:53.000Z","dependencies_parsed_at":"2024-07-31T15:01:16.913Z","dependency_job_id":"de33ee32-b8ed-4f6e-98db-3839bb59c14f","html_url":"https://github.com/willdale/SwiftUICharts","commit_stats":null,"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willdale%2FSwiftUICharts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willdale%2FSwiftUICharts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willdale%2FSwiftUICharts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/willdale%2FSwiftUICharts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/willdale","download_url":"https://codeload.github.com/willdale/SwiftUICharts/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245500241,"owners_count":20625531,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bar-chart","chart","charts","doughnut-chart","filled-line-chart","graph","grouped-bar-chart","ios","line-chart","macos","multi-line-chart","pie-chart","range-bar-chart","stacked-bar-chart","swift","swiftui","tvos"],"created_at":"2024-07-31T15:00:29.098Z","updated_at":"2025-03-25T16:31:39.676Z","avatar_url":"https://github.com/willdale.png","language":"Swift","readme":"# SwiftUICharts\n\nA charts / plotting library for SwiftUI. Works on macOS, iOS,  watchOS, and tvOS and has accessibility and Localization features built in.\n\n[Demo Project](https://github.com/willdale/SwiftUICharts-Demo)\n\n[Documentation](https://willdale.github.io/SwiftUICharts/index.html)\n\nWorking on a [Version 3](https://github.com/willdale/SwiftUICharts/tree/release/3) with a more SwiftUI feel to the API. \n\n## Chart Types\n\n- [Line Chart](#Line-Chart)\n- [Filled Line Chart](#Filled-Line-Chart)\n- [Multi Line Chart](#Multi-Line-Chart)\n- [Ranged Line Chart](#Ranged-Line-Chart)\n\n- [Bar Chart](#Bar-Chart)\n- [Ranged Bar Chart](#Ranged-Bar-Chart)\n- [Grouped Bar Chart](#Grouped-Bar-Chart)\n- [Stacked Bar Chart](#Stacked-Bar-Chart)\n\n- [Pie Chart](#Pie-Chart)\n- [Doughnut Chart](#Doughnut-Chart)\n\n\n### Line Charts\n\n#### Line Chart\n![Example of Line Chart](Resources/images/LineCharts/LineChart.png)\n\nUses `LineChartData` data model.\n\n```swift\nLineChart(chartData: LineChartData)\n```\n\n---\n\n\n#### Filled Line Chart\n![Example of Filled Line Chart](Resources/images/LineCharts/FilledLineChart.png)\n\nUses `LineChartData` data model.\n\n```swift\nFilledLineChart(chartData: LineChartData)\n```\n\n\n---\n\n\n#### Multi Line Chart\n![Example of Multi Line Chart](Resources/images/LineCharts/MultiLineChart.png)\n\nUses `MultiLineChartData` data model.\n\n```swift\nMultiLineChart(chartData: MultiLineChartData)\n```\n\n\n---\n\n\n#### Ranged Line Chart\n![Example of Ranged Line Chart](Resources/images/LineCharts/RangedLineChart.png)\n\nUses `RangedLineChart` data model.\n\n```swift\nRangedLineChart(chartData: RangedLineChartData)\n```\n\n\n---\n\n\n### Bar Charts\n\n#### Bar Chart\n![Example of Bar Chart](Resources/images/BarCharts/BarChart.png)\n\nUses `BarChartData` data model.\n\n```swift\nBarChart(chartData: BarChartData)\n```\n\n\n---\n\n\n#### Range Bar Chart\n![Example of Range Bar Chart](Resources/images/BarCharts/RangeBarChart.png)\n\nUses `RangedBarChartData` data model.\n\n```swift\nRangedBarChart(chartData: RangedBarChartData)\n```\n\n\n---\n\n\n\n#### Grouped Bar Chart\n![Example of Grouped Bar Chart](Resources/images/BarCharts/GroupedBarChart.png)\n\nUses `GroupedBarChartData` data model.\n\n```swift\nGroupedBarChart(chartData: GroupedBarChartData)\n```\n\n\n---\n\n\n#### Stacked Bar Chart\n![Example of Stacked Bar Chart](Resources/images/BarCharts/StackedBarChart.png)\n\nUses `StackedBarChartData` data model.\n\n```swift\nStackedBarChart(chartData: StackedBarChartData)\n```\n\n---\n\n\n### Pie Charts\n\n#### Pie Chart\n![Example of Pie Chart](Resources/images/PieCharts/PieChart.png)\n\nUses `PieChartData` data model.\n\n```swift\nPieChart(chartData: PieChartData)\n```\n\n\n---\n\n\n#### Doughnut Chart\n![Example of Doughnut Chart](Resources/images/PieCharts/DoughnutChart.png)\n\nUses `DoughnutChartData` data model.\n\n```swift\nDoughnutChart(chartData: DoughnutChartData)\n```\n\n\n---\n\n## Documentation\n### Installation\n\nSwift Package Manager\n\n```\nFile \u003e Swift Packages \u003e Add Package Dependency...\n```\n```swift\nimport SwiftUICharts\n```\n\nIf you have trouble with views not updating correctly, add `.id()` to your View.\n```swift\nLineChart(chartData: LineChartData)\n    .id(LineChartData.id)\n```\n\n---\n\n\n## View Modifiers\n\n- [Touch Overlay](#Touch-Overlay)\n- [Info Box](#Info-Box) \n- [Floating Info Box](#Floating-Info-Box) \n- [Header Box](#Header-Box) \n- [Legends](#Legends) \n\n- [Average Line](#Average-Line) \n- [Y Axis Point Of Interest](#Y-Axis-Point-Of-Interest) \n- [X Axis Grid](#X-Axis-Grid) \n- [Y Axis Grid](#Y-Axis-Grid) \n- [X Axis Labels](#X-Axis-Labels) \n- [Y Axis Labels](#Y-Axis-Labels) \n- [Linear Trend Line](#Linear-Trend-Line) \n\n- [Point Markers](#Point-Markers) \n\nThe order of the view modifiers is some what important as the modifiers are various types of stacks that wrap around the previous views.\n\n\n---\n\n\n### All Chart Types\n\n#### Touch Overlay\n\nDetects input either from touch of pointer. Finds the nearest data point and displays the relevent information where specified. \n\nThe location of the info box is set in `ChartStyle -\u003e infoBoxPlacement`.\n\n```swift\n.touchOverlay(chartData: CTChartData, specifier: String, unit: TouchUnit)\n```\n- chartData: Chart data model.\n- specifier: Decimal precision for labels.\n- unit: Unit to put before or after the value.\n\nSetup within  Chart Data --\u003e Chart Style\n\n\n---\n\n\n#### Info Box\n\nDisplays the information from [Touch Overlay](#Touch-Overlay) if `InfoBoxPlacement` is set to `.infoBox`.\n\nThe location of the info box is set in `ChartStyle -\u003e infoBoxPlacement`.\n\n```swift\n.infoBox(chartData: CTChartData)\n```\n- chartData: Chart data model.\n\n\n---\n\n\n#### Floating Info Box\n\nDisplays the information from [Touch Overlay](#Touch-Overlay) if `InfoBoxPlacement` is set to `.floating`.\n\nThe location of the info box is set in `ChartStyle -\u003e infoBoxPlacement`.\n\n```swift\n.floatingInfoBox(chartData: CTChartData)\n```\n- chartData: Chart data model.\n\n\n---\n\n\n#### Header Box\n\nDisplays the metadata about the chart, set in `Chart Data -\u003e ChartMetadata`\n\nDisplays the information from [Touch Overlay](#Touch-Overlay) if `InfoBoxPlacement` is set to `.header`.\n\nThe location of the info box is set in `ChartStyle -\u003e infoBoxPlacement`.\n\n```swift\n.headerBox(chartData: CTChartData)\n```\n\n\n---\n\n\n#### Legends\n\nDisplays legends.\n\n```swift\n.legends()\n```\nLays out markers over each of the data point.\n\n\n---\n\n\n### Line and Bar Charts\n\n#### Average Line\n\nShows a marker line at the average of all the data points.\n\n```swift\n.averageLine(chartData: CTLineBarChartDataProtocol,\n             markerName: \"Average\",\n             labelPosition: .yAxis(specifier: \"%.0f\"),\n             lineColour: .primary,\n             strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))\n```\n- chartData: Chart data model.\n- markerName: Title of marker, for the legend.\n- labelPosition: Option to display the markers’ value inline with the marker.\n- labelColour: Colour of the Text.\n- labelBackground: Colour of the background.\n- lineColour: Line Colour.\n- strokeStyle: Style of Stroke.\n\n\n---\n\n\n#### Y Axis Point Of Interest\n\nConfigurable Point of interest\n\n```swift\n.yAxisPOI(chartData: CTLineBarChartDataProtocol,\n          markerName: \"Marker\",\n          markerValue: 123,\n          labelPosition: .center(specifier: \"%.0f\"),\n          labelColour: Color.black,\n          labelBackground: Color.orange,\n          lineColour: Color.orange,\n          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))\n```\n- chartData: Chart data model.\n- markerName: Title of marker, for the legend.\n- markerValue: Value to mark\n- labelPosition: Option to display the markers’ value inline with the marker.\n- labelColour: Colour of the Text.\n- labelBackground: Colour of the background.\n- lineColour: Line Colour.\n- strokeStyle: Style of Stroke.\n- Returns: A  new view containing the chart with a marker line at a specified value.\n\n\n---\n\n\n#### X Axis Grid\n\nAdds vertical lines along the X axis.\n\n```swift\n.xAxisGrid(chartData: CTLineBarChartDataProtocol)\n```\nSetup within  `ChartData -\u003e ChartStyle`.\n\n\n---\n\n\n#### Y Axis Grid\n\nAdds horizontal lines along the Y axis.\n\n```swift\n.yAxisGrid(chartData: CTLineBarChartDataProtocol)\n```\nSetup within  `ChartData -\u003e ChartStyle`.\n\n\n---\n\n\n#### X Axis Labels\n\nLabels for the X axis.\n\n```swift\n.xAxisLabels(chartData: CTLineBarChartDataProtocol)\n```\nSetup within  `ChartData -\u003e ChartStyle`.\n\n\n---\n\n\n#### Y Axis Labels\n\nAutomatically generated labels for the Y axis\n\n```swift\n.yAxisLabels(chartData: CTLineBarChartDataProtocol, specifier: \"%.0f\")\n```\n- specifier: Decimal precision specifier.\n\nSetup within  `ChartData -\u003e ChartStyle`.\n\nyAxisLabelType: \n```swift\ncase numeric // Auto generated, numeric labels.\ncase custom // Custom labels array\n```\nCustom is set from `ChartData -\u003e yAxisLabels`\n\n---\n\n\n#### Linear Trend Line\n\nA line across the chart to show the trend in the data.\n\n```swift\n.linearTrendLine(chartData: CTLineBarChartDataProtocol,\n                 firstValue: Double,\n                 lastValue: Double,\n                 lineColour: ColourStyle,\n                 strokeStyle: StrokeStyle)\n```\n\n\n---\n\n\n### Line Charts\n\n#### Point Markers\n\nLays out markers over each of the data point.\n\n```swift\n.pointMarkers(chartData: CTLineChartDataProtocol)\n```\nSetup within `Data Set -\u003e PointStyle`.\n\n\n---\n\n\n#### Filled Top Line\n\nAdds an independent line on top of FilledLineChart.\n\n```swift\n.filledTopLine(chartData: LineChartData,\n               lineColour: ColourStyle,\n               strokeStyle: StrokeStyle)\n```\nAllows for a hard line over the data point with a semi opaque fill.\n\n\n---\n\n\n## Examples\n\n### Line Chart\n\n```swift\nstruct LineChartDemoView: View {\n    \n    let data : LineChartData = weekOfData()\n    \n    var body: some View {\n        VStack {\n            LineChart(chartData: data)\n                .pointMarkers(chartData: data)\n                .touchOverlay(chartData: data, specifier: \"%.0f\")\n                .yAxisPOI(chartData: data,\n                          markerName: \"Step Count Aim\",\n                          markerValue: 15_000,\n                          labelPosition: .center(specifier: \"%.0f\"),\n                          labelColour: Color.black,\n                          labelBackground: Color(red: 1.0, green: 0.75, blue: 0.25),\n                          lineColour: Color(red: 1.0, green: 0.75, blue: 0.25),\n                          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))\n                .yAxisPOI(chartData: data,\n                          markerName: \"Minimum Recommended\",\n                          markerValue: 10_000,\n                          labelPosition: .center(specifier: \"%.0f\"),\n                          labelColour: Color.white,\n                          labelBackground: Color(red: 0.25, green: 0.75, blue: 1.0),\n                          lineColour: Color(red: 0.25, green: 0.75, blue: 1.0),\n                          strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))\n                .averageLine(chartData: data,\n                             strokeStyle: StrokeStyle(lineWidth: 3, dash: [5,10]))\n                .xAxisGrid(chartData: data)\n                .yAxisGrid(chartData: data)\n                .xAxisLabels(chartData: data)\n                .yAxisLabels(chartData: data)\n                .infoBox(chartData: data)\n                .headerBox(chartData: data)\n                .legends(chartData: data, columns: [GridItem(.flexible()), GridItem(.flexible())])\n                .id(data.id)\n                .frame(minWidth: 150, maxWidth: 900, minHeight: 150, idealHeight: 250, maxHeight: 400, alignment: .center)\n        }\n        .navigationTitle(\"Week of Data\")\n    }\n    \n    static func weekOfData() -\u003e LineChartData {\n        let data = LineDataSet(dataPoints: [\n            LineChartDataPoint(value: 12000, xAxisLabel: \"M\", description: \"Monday\"),\n            LineChartDataPoint(value: 10000, xAxisLabel: \"T\", description: \"Tuesday\"),\n            LineChartDataPoint(value: 8000,  xAxisLabel: \"W\", description: \"Wednesday\"),\n            LineChartDataPoint(value: 17500, xAxisLabel: \"T\", description: \"Thursday\"),\n            LineChartDataPoint(value: 16000, xAxisLabel: \"F\", description: \"Friday\"),\n            LineChartDataPoint(value: 11000, xAxisLabel: \"S\", description: \"Saturday\"),\n            LineChartDataPoint(value: 9000,  xAxisLabel: \"S\", description: \"Sunday\")\n        ],\n        legendTitle: \"Steps\",\n        pointStyle: PointStyle(),\n        style: LineStyle(lineColour: ColourStyle(colour: .red), lineType: .curvedLine))\n        \n        let metadata   = ChartMetadata(title: \"Step Count\", subtitle: \"Over a Week\")\n        \n        let gridStyle  = GridStyle(numberOfLines: 7,\n                                   lineColour   : Color(.lightGray).opacity(0.5),\n                                   lineWidth    : 1,\n                                   dash         : [8],\n                                   dashPhase    : 0)\n        \n        let chartStyle = LineChartStyle(infoBoxPlacement    : .infoBox(isStatic: false),\n                                        infoBoxBorderColour : Color.primary,\n                                        infoBoxBorderStyle  : StrokeStyle(lineWidth: 1),\n                                        \n                                        markerType          : .vertical(attachment: .line(dot: .style(DotStyle()))),\n                                        \n                                        xAxisGridStyle      : gridStyle,\n                                        xAxisLabelPosition  : .bottom,\n                                        xAxisLabelColour    : Color.primary,\n                                        xAxisLabelsFrom     : .dataPoint(rotation: .degrees(0)),\n                                        \n                                        yAxisGridStyle      : gridStyle,\n                                        yAxisLabelPosition  : .leading,\n                                        yAxisLabelColour    : Color.primary,\n                                        yAxisNumberOfLabels : 7,\n                                        \n                                        baseline            : .minimumWithMaximum(of: 5000),\n                                        topLine             : .maximum(of: 20000),\n                                        \n                                        globalAnimation     : .easeOut(duration: 1))\n        \n        return LineChartData(dataSets       : data,\n                             metadata       : metadata,\n                             chartStyle     : chartStyle)\n        \n    }\n}\n```\n\n# Accessibility\n\nInside certain elements are additional tags to help describe the chart for VoiceOver.\n\nSee [Localization of Accessibility](#Localization-of-Accessibility)\n\n# Localization\n\nAll labels support localization. There are, however, some hidden labels that are there to support VoiceOver. See [Localization of Accessibility](#Localization-of-Accessibility)\n\n# Localization of Accessibility\n\nSee the localization demo in the [Demo Project](https://github.com/willdale/SwiftUICharts-Demo).\n\n---\n\nVoice over description of a datapoint when the user touches the area closest to the data point.\nThe VoiceOver will say `\u003cchart title\u003e, \u003cdata point value\u003e, \u003cdata point description\u003e`.\n```swift\n\"%@ \u003clocal_description_of_a_data_point\u003e\" = \"%@, \u003cDescription of a data point\u003e\";\n```\n\n\nRead out before a `poiMarker`.\nThe VoiceOver will say `\u003cp o i marker\u003e, \u003cmarker legend title\u003e, \u003cmarker value\u003e`.\n```swift\n\"P-O-I-Marker\" = \"P O I Marker\";\n\"Average\" = \"Average\";\n```\n\nVoice over description of a `poiMarker`.\nThe VoiceOver will say `\u003cP-O-I-Marker\u003e, \u003cmarker legend title\u003e, \u003cmarker value\u003e`.\n```swift\n\"\u003clocal_marker_legend_title\u003e %@\" = \"local_marker_legend_title, %@\";\n```\n\n\n\nRead out before a `axisLabel`.\nThe VoiceOver will say `\u003caxisLabel\u003e, \u003cmarker value\u003e`.\n```\n\"X-Axis-Label\" = \"X Axis Label\";\n\"Y-Axis-Label\" = \"Y Axis Label\";\n```\n\nRead out before a `legend`.\nThe VoiceOver will say `\u003cchart type legend\u003e, \u003clegend title\u003e`.\n```swift\n\"Line-Chart-Legend\" = \"Line Chart Legend\";\n\"P-O-I-Marker-Legend\" = \"P O I Marker Legend\";\n\"Bar-Chart-Legend\" = \"Bar Chart Legend\";\n\"P-O-I-Marker-Legend\" = \"P O I Marker Legend\";\n\"Pie-Chart-Legend\" = \"Pie Chart Legend\";\n\"P-O-I-Marker-Legend\" = \"P O I Marker Legend\";\n```\n","funding_links":["https://github.com/sponsors/willdale"],"categories":["Libs","Swift"],"sub_categories":["Chart"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilldale%2FSwiftUICharts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwilldale%2FSwiftUICharts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwilldale%2FSwiftUICharts/lists"}