{"id":13995061,"url":"https://github.com/DominikButz/SwiftUIGraphs","last_synced_at":"2025-07-22T21:31:59.025Z","repository":{"id":37965862,"uuid":"336158384","full_name":"DominikButz/SwiftUIGraphs","owner":"DominikButz","description":"As replacement for SwiftUI Charts, SwiftUIGraphs features a multi-line chart, stacked bar chart and pie chart with many customisable properties.","archived":false,"fork":false,"pushed_at":"2023-07-30T03:06:43.000Z","size":24518,"stargazers_count":48,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-08-10T14:17:56.460Z","etag":null,"topics":["barchart","chart","charts","graph","grid","ios","ipados","linechart","macos","pie-chart","piechart","plotting","swift","swiftui"],"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/DominikButz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-02-05T03:57:43.000Z","updated_at":"2024-08-03T13:09:04.000Z","dependencies_parsed_at":"2024-01-18T05:35:49.111Z","dependency_job_id":null,"html_url":"https://github.com/DominikButz/SwiftUIGraphs","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DominikButz%2FSwiftUIGraphs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DominikButz%2FSwiftUIGraphs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DominikButz%2FSwiftUIGraphs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DominikButz%2FSwiftUIGraphs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DominikButz","download_url":"https://codeload.github.com/DominikButz/SwiftUIGraphs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227177751,"owners_count":17743157,"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":["barchart","chart","charts","graph","grid","ios","ipados","linechart","macos","pie-chart","piechart","plotting","swift","swiftui"],"created_at":"2024-08-09T14:03:13.958Z","updated_at":"2024-11-29T17:30:55.374Z","avatar_url":"https://github.com/DominikButz.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# SwiftUIGraphs (v1.1.2)\n\n\nSwiftUIGraphs is a Swift package for iOS, iPadOS (14.0 and later) as well as MacOS (11.0 and later). It features a line chart, bar chart and pie chart for data visualization and has many customization options. \n \n\n## Feature Overview\n\n* **NEW**: from v1.1 SwiftUIGraphs supports MacOS (from v11) natively - in the included example project , simply select the macOS target and try it out!\n* From v1.0 DYLineChartView and DYBarChartView support muliple data series by default (multi-line charts and stacked bar charts).\n* Create an interactive line chart with a moving data selector point. The package also allows setting separate data point colors and line section colors.\n* Create an area chart by adding a gradient area below the line chart.\n* Create a stacked bar chart with positive and negative fraction values\n* line and bar charts feature cool appear animations \n* Create a pie chart or doughnut chart with customizable colors and a cool pop out effect to present a detail pie chart.\n* The chart views feature separate header / info / legend views that can be replaced by custom solutions easily. \n* Add drop shadows to the line chart, gradient, bars and selected pie slice.\n* Many more features - check out details below. \n\nThe folder SwiftUIGraphsExample contains an example project, make sure to check it out for more implementation details. All public structs / classes include in-code-documentation.\n    \n    \n## Installation\n\n\nInstallation through the Swift Package Manager (SPM) is recommended. \n\nSPM:\nSelect your project (not the target) and then select the Swift Packages tab. Clicking + and typing SwiftUIGraphs should find the package on github. Otherwise copy and paste the URL of this repo.\n\n\nCheck out the version history below for the current version.\n\n\nMake sure to import SwiftUIGraphs in every file where you use SwiftUIGraphs. \n\n```Swift\n    import SwiftUIGraphs\n```\n\n## Usage\n\nCheck out the following examples. This repo also contains an example project to illustrate how to implement all three chart types. Check the in-code documentation for more details.\n\n\n### Line Charts\n\nDYLineChartView supports the following modifiers:\n\n* background(gradient...)\n* selectorLine\n* markerGridLine\n* userInteraction\n* showXAxis\n* xAxisViewHeight\n* xAxisGridLines\n* xAxisLabelStringValue\n* xAxisLabelFont(_ font: UIFont)\n* xAxisScalerOverride\n* showYaxis\n* yAxisPosition\n* yAxisViewWidth\n* yAxisGridLines\n* yAxisLabelStringValue\n* yAxisLabelFont(_ font: UIFont)\n* yAxisScalerOverride\n\nPass in one or several DYLineViews into DYLineChartView's lineViews closure. You can attach the following modifiers to DYLineView:\n\n* lineStyle\n* animation\n* userInteraction\n* area\n* selectedPointIndicatorLineStyle\n* colorPerLineSegment\n\n#### Code Example: Multi-line chart\n\n![SwiftUIGraphs example](gitResources/MultiLineChartExample0.gif) \n\n```Swift\n\nstruct MultiLineChartExample: View {\n    \n    let colors: [Color] = [.blue, .orange, .green]\n    @State private var dataPointArrays: Array\u003c[DYDataPoint]\u003e = []\n    \n    @State private var blueSelectedDataPoint: DYDataPoint?\n    @State private var orangeSelectedDataPoint: DYDataPoint?\n    @State private var greenSelectedDataPoint: DYDataPoint?\n\n    var body: some View {\n  \n        GeometryReader { proxy in\n            VStack {\n                \n                DYLineChartView(allDataPoints: Array(self.dataPointArrays.joined()), lineViews: { parentProps in\n                    let selectedPoints = [$blueSelectedDataPoint, $orangeSelectedDataPoint, $greenSelectedDataPoint]\n                    ForEach(0..\u003cdataPointArrays.count, id:\\.self) { i in\n                        \n                        DYLineView(dataPoints: dataPointArrays[i], selectedDataPoint: selectedPoints[i], pointView: { _ in\n                            self.pointViewFor(index: i)\n                        }, selectorView: self.selectorPointViewFor(index: i), parentViewProperties: parentProps)\n                        .lineStyle(color: colors[i])\n                        .selectedPointIndicatorLineStyle(xLineColor: colors[i], yLineColor: colors[i])\n                         \n                    }\n              \n                    \n                })\n                .markerGridLine(coordinate: 0, color: .red)\n                .yAxisLabelFontSize(UIDevice.current.userInterfaceIdiom == .phone ? 8 : 10)\n                .yAxisLabelStringValue({ yValue in\n                    self.stringified(value:yValue)\n                })\n                .xAxisLabelFontSize(UIDevice.current.userInterfaceIdiom == .phone ? 8 : 10)\n                .xAxisLabelStringValue({ xValue in\n                    self.stringified(value: xValue)\n                })\n                .frame(height: self.chartHeight(proxy: proxy))\n                .padding()\n\n                self.legendView.padding()\n                \n                \n                Spacer()\n            }\n\n        }.navigationTitle(\"Some Random Data Sets\")\n            .onAppear {\n                generateDataPoints()\n            }\n\n    }\n    \n    func chartHeight(proxy: GeometryProxy)-\u003eCGFloat {\n        return proxy.size.height \u003e proxy.size.width ? proxy.size.height * 0.4 : proxy.size.height * 0.75\n    }\n    \n    var legendView: some View {\n\n        return HStack(spacing:15) {\n            let selectedPoints = [blueSelectedDataPoint, orangeSelectedDataPoint, greenSelectedDataPoint]\n            ForEach(0..\u003cselectedPoints.count, id:\\.self) { i in\n                if let dataPoint =  selectedPoints[i] {\n                    HStack {\n                        self.pointViewFor(index: i)\n                        Text(\"X: \\(self.stringified(value: dataPoint.xValue))\")\n                        Text(\"Y: \\(self.stringified(value: dataPoint.yValue))\")\n                        \n                    }.font(UIDevice.current.userInterfaceIdiom == .pad ? .body : .caption)\n                }\n            }\n            Spacer()\n        }\n    }\n    \n    func stringified(value: Double)-\u003eString {\n        let formatter = NumberFormatter()\n        formatter.maximumFractionDigits = 1\n        return formatter.string(for: value)!\n    }\n    \n    \n    func generateDataPoints() {\n        var dataPointArrays: Array\u003c[DYDataPoint]\u003e = []\n        for _ in 0..\u003c3 {\n            \n            var dataPoints: [DYDataPoint] = []\n            var xValue = Double.random(in: 1...1.5)\n            for _ in 0..\u003c12 {\n                \n                let yValue = Double.random(in: -10...40)\n                let dataPoint = DYDataPoint(xValue: xValue, yValue: yValue)\n                dataPoints.append(dataPoint)\n                xValue += Double.random(in: 0.5...1)\n            }\n            dataPointArrays.append(dataPoints)\n        }\n        self.dataPointArrays = dataPointArrays\n    }\n    \n\n    \n    func pointViewFor(index: Int)-\u003e some View {\n        Group {\n            switch index {\n                case 0:\n                DYLinePointView(borderColor: colors[index])\n           \n                case 1:\n                DYLinePointView(shape: Rectangle(), borderColor: colors[index], edgeLength: 10)\n          \n                default:\n                DYLinePointView(shape: Triangle(), borderColor: colors[index])\n                \n            }\n        }\n    }\n    \n    func selectorPointViewFor(index: Int)-\u003e some View {\n        Group {\n            switch index {\n                case 0:\n                DYSelectorPointView()\n                case 1:\n                DYSelectorPointView(shape: Rectangle(), shapeSize: 12, shapeHaloSize: 24)\n                default:\n                DYSelectorPointView(shape: Triangle(), haloOffset: CGSize(width: 0, height: -14 / 6))\n                \n            }\n        }\n    }\n\n}\n```\n\n#### Other examples\n\nCheck out the example project for details (included in the package).\n\n![SwiftUIGraphs example](gitResources/LineChartExample0.gif) \n\nIn order to try out the stock price example, you need to sign up with https://iexcloud.io for free to get an authentication token. \n\n\n\n**Area Chart with different color per line segment example**: \n\n\n![SwiftUIGraphs example](gitResources/LineChartExampleColorPerPoint.gif) \n\nAdditionally, you can add a drop shadow underneath the gradient (and / or the line):\n\n![SwiftUIGraphs example](gitResources/LineChartExampleShadow.gif) \n\n\n\n### Bar Charts\n\nDYBarChartView supports multiple data series from version 1.0. Each bar is represented by a DYBarDataSet - check out the example below for details.\n\nDYBarChartView supports the following modifiers:\n\n* background(gradient: LinearGradient)\n* userInteraction(enabled: Bool = true)\n* animation(_ showAppearAnimation: Bool)\n* barDropShadow(_ shadow: Shadow)\n* labelViewOffset( _ offset: CGSize)\n* selectedBar(borderColor: Color, dropShadow: Shadow? = nil)\n* barLabelMinimumEdgeMargin(top: CGFloat = 0, bottom: CGFloat = 10)\n* showXaxis(_ show: Bool)\n* xAxisViewHeight(_ height: CGFloat)\n* xAxisLabelFont(_ font: UIFont)\n* showYaxis(_ show: Bool)\n* yAxisPosition(_ position: Edge.Set)\n* yAxisViewWidth(_ height: CGFloat)\n* yAxisLabelStringValue(_ stringValue: @escaping (Double)-\u003eString)\n* yAxisLabelFont(_ font: UIFont)\n* yAxisGridLines(showGridLines: Bool = true, gridLineColor: Color = Color.secondary.opacity(0.5), gridLineStrokeStyle: StrokeStyle = StrokeStyle(lineWidth: 1, dash: [3]))\n* markerGridLine(yCoordinate: Double, color: Color, strokeStyle: StrokeStyle = StrokeStyle(lineWidth: 1, dash: [3]))\n* yAxisScalerOverride(minMax: (min:Double?, max:Double?)? = nil, interval: Double? = nil, maxTicks: Int = 10)\n\n\n\n#### Code Example: Stacked Bar Chart\n\n![SwiftUIGraphs example](gitResources/StackedBarChartExample0.gif) \n\n\n``` Swift \nstruct MultiBarChartExample: View {\n    \n    let colors: [Color] = [.blue, .orange, .green]\n    let titles = [\"Energy\", \"Pharmaceutical\", \"Agriculture\"]\n    @State var barDataSets: [DYBarDataSet] = []\n    @State var selectedBarDataSet: DYBarDataSet?\n    \n    var body: some View {\n        GeometryReader { proxy in\n            VStack {\n                DYBarChartView(barDataSets: barDataSets, selectedBarDataSet: $selectedBarDataSet)\n                .barDropShadow(Shadow(color: .gray, radius:8, x:-4, y:-3))\n                .selectedBar(borderColor: .purple, dropShadow: Shadow(color: .black.opacity(0.7), radius:10, x:-7, y:-5))\n                .yAxisLabelFontSize(UIDevice.current.userInterfaceIdiom == .phone ? 8 : 10)\n                .markerGridLine(yCoordinate: 0, color: .red)\n                .xAxisLabelFontSize(UIDevice.current.userInterfaceIdiom == .phone ? 8 : 10)\n                .frame(height:chartHeight(proxy: proxy))\n                \n            \n                if self.barDataSets.isEmpty == false {\n                    HStack {\n                        self.selectedDataSetDetailView()\n                        Spacer()\n                    }\n                }\n                \n                Spacer()\n            }.padding()\n\n        }.navigationTitle(\"Profits \u0026 Losses Mio. USD per Division per Year\")\n            .onAppear {\n                self.generateExampleData()\n            }\n    }\n\n    \n    func chartHeight(proxy: GeometryProxy)-\u003eCGFloat {\n        return proxy.size.height \u003e proxy.size.width ? proxy.size.height * 0.4 : proxy.size.height * 0.65\n    }\n    \n    func selectedDataSetDetailView()-\u003esome View {\n        Group {\n            if let barDataSet = selectedBarDataSet {\n                VStack(alignment: .leading) {\n                    \n                    Text(barDataSet.xAxisLabel).font(.callout).bold()\n                    HStack {\n                        if barDataSet.netValue \u003e= 0 {\n                            Text(\"Net Profit:\")\n                        } else {\n                            Text(\"Net Loss:\").foregroundColor(.red).bold()\n                        }\n                        Text(abs(barDataSet.netValue).toCurrencyString(maxDigits:1) + \" million\").foregroundColor(barDataSet.netValue \u003e= 0 ? .primary : .red)\n                        Spacer()\n                    }\n                    \n                    VStack(spacing: 0) {\n                        ForEach(0..\u003cbarDataSet.fractions.count, id:\\.self) { i in\n                            let fraction = barDataSet.fractions[i]\n                            HStack(spacing: 0) {\n                                HStack {\n                                    Rectangle().fill(colors[i]).frame(width: 15, height: 15)\n                                    Text(fraction.title + \": \")\n                                    Spacer()\n                                }\n                                \n                                Text(fraction.value.toCurrencyString(maxDigits:1) + \" million\").foregroundColor(fraction.value \u003e= 0 ? .primary : .red)\n                                Spacer()\n                            }.font(.callout)\n                            \n                        }\n\n                    }.transition(AnyTransition.opacity)\n                    \n                    \n                }.frame(maxWidth: 300).padding()\n \n            }\n        }\n    }\n    \n    \n    func generateExampleData() {\n        var barDataSets: [DYBarDataSet] = []\n        var currentYear = 2012\n        \n        for _ in 0..\u003c10 {\n            let firstValue = Double.random(in: -10 ..\u003c 50)\n            let secondValue = Double.random(in: -20 ..\u003c 40)\n            let thirdValue = Double.random(in: -30 ..\u003c 30)\n            let values = [firstValue, secondValue, thirdValue]\n            let xValueLabel = \"\\(currentYear)\"\n            var fractions: [DYBarDataFraction] = []\n            for i in 0..\u003cvalues.count {\n                let fraction = DYBarDataFraction(value: values[i], title:titles[i], gradient: LinearGradient(colors: [colors[i]], startPoint: .top, endPoint: .bottom)) {\n                    Text(values[i].toDecimalString(maxFractionDigits: 1)).font(.footnote).lineLimit(1).foregroundColor(.white).eraseToAnyView()\n                }\n                fractions.append(fraction)\n            }\n            \n            let dataSet = DYBarDataSet(fractions: fractions, xAxisLabel: xValueLabel, labelView: { value in\n                let text = value != 0 ? value.toDecimalString(maxFractionDigits: 1) : \"\"\n                return Text(text).font(.footnote).eraseToAnyView()\n            })\n            barDataSets.append(dataSet)\n\n            currentYear += 1\n        }\n        self.barDataSets = barDataSets\n    }\n}\n\n```\n\n***Simple bar chart example:***\n\n![SwiftUIGraphs example](gitResources/BarChartExample0.gif) \n\n### Pie Charts\n\nDYPieChartView supports the following modifiers:\n\n*  innerCircleRadiusFraction(_ fraction: CGFloat)\n*  userInteraction(enabled: Bool)\n*  sliceBorderLine(width: CGFloat = 1, color: Color = .primary)\n*  selectedSlice(scaleEffect: CGFloat = 1.05, dropShadow: Shadow = Shadow(color: .gray.opacity(0.7), radius: 10, x: 0, y: 0))\n*  minimumFractionForSliceLabelOffset(_ fraction: CGFloat = 0.1)\n*  hideMultiFractionSliceOnSelection(_ hide: Bool = false)\n\n\n\n#### Code example: Ring Chart with detail pie chart (pop-out effect)\n\nSet the innerCircleRadiusFraction(_ fraction: CGFloat = 0) modifier to a value larger than 0 and smaller than 1 to turn a pie chart into a ring chart. Details below. \n\n![SwiftUIGraphs example](gitResources/PieChartExample0.gif) \n\n```Swift\n\nstruct RingChartAndDetailPieChartExample: View {\n\n    @State var detailChartSelectedSlice: DYPieFraction?\n    @State private var pieScale:CGSize = .zero\n    @StateObject var chartModel: ChartModel = ChartModel()\n    @Namespace var animationNamespace\n    \n    \n    var body: some View {\n        GeometryReader { proxy in\n            if proxy.size.height \u003e proxy.size.width {\n                VStack {\n                    self.contentView(isPortrait: true)\n                }\n            } else {\n                HStack {\n                    self.contentView(isPortrait: false)\n                }\n            }\n        }.navigationTitle(\"Sales by Country\")\n    }\n    \n    func contentView(isPortrait: Bool)-\u003e some View {\n        Group {\n            self.mainPieChart(isPortrait: isPortrait)\n\n            if detailChartVisibleCondition {\n                self.otherCategoryDetailsPieChart()\n            }\n        }\n    }\n    \n    func mainPieChart(isPortrait: Bool)-\u003esome View {\n        VStack(spacing: 10) {\n            DYPieChartView(data: chartModel.data, selectedSlice: $chartModel.selectedSlice, sliceLabelView: { (fraction)  in\n                self.sliceLabelContentView(fraction: fraction, data:self.chartModel.data, textColor: .white)\n            }, animationNamespace: animationNamespace)\n            .hideMultiFractionSliceOnSelection(true)\n            .innerCircleRadiusFraction(0.3)\n            .background(Circle().fill(Color(.systemBackground)).shadow(color: detailChartVisibleCondition ? .clear : .gray, radius:5))\n            .rotationEffect(detailChartVisibleCondition ? Angle(degrees: isPortrait ? 45 : -40) : Angle(degrees: 0))\n\n        }\n        .scaleEffect(self.pieScale)\n        .padding()\n        .onAppear {\n            withAnimation(.spring()) {\n                self.pieScale = CGSize(width: 1, height: 1)\n            }\n        }\n        \n\n    }\n    \n    func otherCategoryDetailsPieChart()-\u003esome View {\n        VStack(spacing: 5) {\n            DYPieChartView(data: chartModel.data[1].detailFractions, selectedSlice: $detailChartSelectedSlice, sliceLabelView: { (fraction) in\n                self.detailChartSliceLabelView(fraction: fraction, data: chartModel.data[1].detailFractions)\n   \n            }, animationNamespace: animationNamespace)\n            .minimumFractionForSliceLabelOffset(0.11)\n            .background(Circle().fill(Color(.systemBackground)).shadow(radius: 10))\n            .padding(50)\n            .matchedGeometryEffect(id: self.chartModel.data[1].id, in: self.animationNamespace)\n\n        }\n    }\n    \n\n    \n    func detailChartSliceLabelView(fraction: DYPieFraction, data: [DYPieFraction])-\u003esome View {\n        Group {\n            if fraction.value / data.reduce(0, { $0 + $1.value}) \u003e= 0.11 || self.detailChartSelectedSlice == fraction {\n                self.sliceLabelContentView(fraction: fraction, data:data, textColor: fraction.value / data.reduce(0, { $0 + $1.value}) \u003e= 0.11 ? .white : .primary)\n            }\n        }\n    }\n    \n    func sliceLabelContentView(fraction: DYPieFraction, data:[DYPieFraction], textColor: Color)-\u003e some View {\n        VStack {\n            Text(fraction.title).font(sliceLabelViewFont).lineLimit(2).frame(maxWidth: 85)\n            Text(String(format:\"%.0f units\", fraction.value)).font(sliceLabelViewFont).bold()\n            Text(fraction.value.percentageString(totalValue: data.reduce(0) { $0 + $1.value})).font(sliceLabelViewFont)\n            \n        }.foregroundColor(textColor)\n    }\n    \n    var sliceLabelViewFont: Font {\n       return UIDevice.current.userInterfaceIdiom == .pad ? .callout : .caption\n    }\n    \n    var detailChartVisibleCondition: Bool {\n        self.chartModel.selectedSlice == chartModel.data[1]\n    }\n}\n```\n\n## References \u0026 special thanks\n\n- DYLineChartView was inspired by [this great tutorial](https://trailingclosure.com/recreating-the-strava-activity-graph/) by Jean-Marc Boullianne on how to implement the Strava line chart. DYLineChart however is a generic implementation of a line chart and not limited to 12 weeks running workout data. \n- Special thanks to Roman Baitaliuk for his implementation of a \"nice number\" algorithm for the y-axis. This algorithm can be found elsewhere but apparently not in Swift\n- Special thanks to xspyhack for the implementation of a SwiftUI Path and CGPoint extensions. \n- Special thanks to David Malan and his team of Harvard's CS50 Introduction to Computer Science. There is no better course to learn programming basics. \n\n## Change log\n\n#### [Version 1.1.2](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.1.2)\nFixes a critical bug in DYLineView. \n\n#### [Version 1.1.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.1.1)\nVarious minor updates:\n\n* Fixes a bug that could lead to a crash when displaying a bar chart with bar fraction labels on MacOS. \n* Adds an animation modifier for DYBarChartView. \n* Added MacOS icon images to assets\n\n\n#### [Version 1.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.1)\nVarious updates for MacOS native support. \n\n#### [Version 1.0.3](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.0.3)\nMinor update: Renaming selectorView parameter in DYLineView to selectorPointView.\n\n#### [Version 1.0.2](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.0.2)\nYou can now set a label font (UIFont) for the x- and y-axis tick labels (default is UIFont.systemFont(ofSize: 8)). \nThe default color of the line in a line chart is now primary instead of orange. \nBug fix: setting userInteraction to false in a DYLineView now works properly when the userInteraction property is set to true in the DYLineChartView modifier. \n\n#### [Version 1.0.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/1.0.1)\nBREAKING changes:\n\n* DYLineChartView and DYBarChartView now support multiple data series by default.\n* no more bulky settings objects to pass into the initialisers: simply attach modifiers. \n* no more chart height parameter in the initialisers: simply attach a .frame modifier like with any other SwiftUI view.\n* DYLineChartView x-axis ticks are now calculated in the same way as the y-axis. In order to override the min and max x-axis values as well as the tick interval, simply attach the xAxisScalerOverride modifier (for the y-axis, attach the yAxisScalerOverride modifier).\n* use the markerGridLine-modifier to add one or several marker lines (e.g. as target line) to the plot area.\n\n#### [Version 0.9.3](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.9.3)\nBug fix: in the line chart, user interaction (provided it is switched on) works again if showAppearAnimation set to false\n\n#### [Version 0.9.2](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.9.2)\nAdded showAppearAnimation parameter to settings of DYLineChartView and DYBarChartView. If it is set to false, the line, line gradient (if any) and the bars will appear instantly without any transition animation.\n\n#### [Version 0.9.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.9.1)\nBug fixes: \n\n* DYBarChart yAxis labels are now positioned more precisely\n* lateral padding works correctly in DYBarChartView\n* bars won't surpass the bounds of the chart area any more when device orientation is changed.\n* DYPieChart: if the sum of detailFractions' values is not equal to the parent chart fraction value, an assertionFailure is thrown.\n\n#### [Version 0.9](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.9)\n\"Shady update\": You can now set drop shadows to show underneath the line and line gradient and underneath each bar and pie chart slice.\nMoreover, in the DYGridChartHeaderView you can now set the selected y-value text label to a different text color. \nBug fixes:\n\n* lateral padding should work properly now and should not shift subviews any more.\n* the y-axis labels are now positioned more precisely.\n\n#### [Version 0.8.2](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.8.2)\nAdded allowUserInteration parameter to all three chart type settings (default is true).\n\n#### [Version 0.8.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.8.1)\nAdded lineAnimationDuration property to DYLineChartSettings. \n\n#### [Version 0.8](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.8)\n* added labelView paramenter (closure) to DYLineChartView and DYBarChartView initialisers to display custom label views above data points / bars if required.\n* added (optional) additional grid line properties to x-axis and y-axis settings (currently for DYLineChartView only). \n\n#### [Version 0.7.2](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.7.2)\n  Added DYLineChartSettings property that allows switching the interpolation type for path drawing between points to linear instead of quadCurve. \n  \n#### [Version 0.7.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.7.1)\n* A segmented line with several color-segments now appears with a continuous draw-style animation from left to right.\n* Added selectedBarGradient property to DYBarSettings. Setting this value will apply a separate linear gradient to the selected bar.\n* Code optimisation\n\n#### [Version 0.7](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.7)\nIt is now possible to set individual colors per data point and per line section using closures in the initialiser of DYLineChartView. Additionally, it is possible to set a different color per each bar in the DYBarChartView initialiser. Special thanks to SAleksiev for his suggestion and help. \n\n#### [Version 0.6.1](https://github.com/DominikButz/SwiftUIGraphs/releases/tag/0.6.1)\nInitial public release. Added documentation to all public struct and class initializers. Minor visual improvements.\n\n\n## Author\n\ndominikbutz@gmail.com\n\n## License\n\nSwiftUIGraphs is available under the MIT license. See the LICENSE file for more info.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDominikButz%2FSwiftUIGraphs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDominikButz%2FSwiftUIGraphs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDominikButz%2FSwiftUIGraphs/lists"}