How can I specify min space between bars in bar chart using SwiftChars library ?
- Here is my code sample for using SwiftCharts to display bars chart:
// xAxis let labelSettings = ChartLabelSettings(font: .systemFont(ofSize: 13.0), fontColor: .aiduBlue) var xValues = [ChartAxisValue]() xValues.append(ChartAxisValueString(order: -1)) for (index, point) in barsDataSource.enumerated() { let dateString = DateFormatter.shortDayOfWeekDayOnTwoLinesFormatter.string(from: point.departureDate) xValues.append(ChartAxisValueString(dateString, order: index, labelSettings: labelSettings)) } xValues.append(ChartAxisValueString(order: xValues.count - 1)) let xModel = ChartAxisModel(axisValues: xValues, lineColor: .aiduSkyBlue, axisTitleLabel: ChartAxisLabel(text: "", settings: labelSettings)) // yAxis let yAxisMinSpaceBetweenPoints: CGFloat = 10.0 let yAxisTopBottomMargin = (((barsMaxPrice - barsMinPrice) / Double(barsDataSource.count)) + Double(yAxisMinSpaceBetweenPoints)) + 10 let yAxisGenerator = ChartAxisValuesGeneratorNice(minValue: barsMinPrice - yAxisTopBottomMargin, maxValue: barsMaxPrice + yAxisTopBottomMargin, preferredDividers: 1, minSpace: yAxisMinSpaceBetweenPoints, maxTextSize: CGFloat.greatestFiniteMagnitude, multiplierUpdateMode: .nice) let yLabelsGenerator = ChartAxisLabelsGeneratorFunc {scalar in return ChartAxisLabel(text: "", settings: ChartLabelSettings()) } let yModel = ChartAxisModel(lineColor: UIColor.white.withAlphaComponent(0), firstModelValue: barsMinPrice, lastModelValue: barsMaxPrice, axisTitleLabels: [], axisValuesGenerator: yAxisGenerator, labelsGenerator: yLabelsGenerator) // Char Bars layer let frame = chartFrame(containerView.bounds) let coordsSpace = ChartCoordsSpaceLeftBottomSingleAxis(chartSettings: chartSettings, chartFrame: frame, xModel: xModel, yModel: yModel) let (xAxisLayer, yAxisLayer, innerFrame) = (coordsSpace.xAxisLayer, coordsSpace.yAxisLayer, coordsSpace.chartInnerFrame) let barsModels: [ChartBarModel] = barsDataSource.enumerated().flatMap { index, item in [ ChartBarModel(constant: ChartAxisValueInt(index), axisValue1: ChartAxisValueDouble(0), axisValue2: ChartAxisValueDouble(item.price), bgColor: barColor(price: item.price, minPrice: barsMinPrice)) ] } let chartBarSettings = ChartBarViewSettings(animDuration: 0, animDelay: 0, cornerRadius: 0, roundedCorners: .allCorners, selectionViewUpdater: nil, delayInit: false) let chartBarsLayer = ChartBarsLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, bars: barsModels, horizontal: false, barWidth: 40, settings: chartBarSettings, mode: .translate, tapHandler: { [weak self] (tappedBar) in self?.chartBarTapHandler(tappedBar: tappedBar) }, viewGenerator: { [weak self] (p1, p2, barWidth, color, settings, model, index) -> ChartPointViewBar in var barBGColor = color if let s = self, let lastTappedBarModel = s.lastTappedBarModel { let currentBarModel = s.dataSource[index] barBGColor = currentBarModel.departureDate == lastTappedBarModel.departureDate && currentBarModel.duration == lastTappedBarModel.duration ? s.barSelectionBgColor : color } let view = ChartPointViewBar(p1: p1, p2: p2, width: barWidth, bgColor: barBGColor, settings: settings) return view }) // Price labels layer let labelToBarSpace: Double = 20 let labelChartPoints = barsModels.map { bar in ChartPoint(x: bar.constant, y: bar.axisValue2.copy(bar.axisValue2.scalar + labelToBarSpace)) } let priceLabelsLayer = ChartPointsViewsLayer(xAxis: xAxisLayer.axis, yAxis: yAxisLayer.axis, chartPoints: labelChartPoints, viewGenerator: {(chartPointModel, layer, chart) -> UIView? in let label = HandlingLabel() label.text = PriceFormatter.string(fromPrice: Float(chartPointModel.chartPoint.y.scalar - labelToBarSpace)) label.font = .boldSystemFont(ofSize: 10.0) label.textColor = UIColor.aiduBlue label.sizeToFit() let pos = chartPointModel.chartPoint.y.scalar > 0 label.center = CGPoint(x: chartPointModel.screenLoc.x, y: pos ? innerFrame.origin.y : innerFrame.origin.y + innerFrame.size.height) label.alpha = 0 label.isUserInteractionEnabled = false label.movedToSuperViewHandler = {[weak label] in label?.alpha = 1 label?.center.y = chartPointModel.screenLoc.y } return label }, displayDelay: 0, mode: .translate) return Chart( frame: frame, innerFrame: innerFrame, settings: chartSettings, layers: [ xAxisLayer, yAxisLayer, chartBarsLayer, priceLabelsLayer ] ) private var chartSettings: ChartSettings { var chartSettings = ChartSettings() chartSettings.leading = 2 chartSettings.top = 2 chartSettings.trailing = 2 chartSettings.bottom = 2 chartSettings.axisStrokeWidth = 0.4 chartSettings.spacingBetweenAxesX = 2 chartSettings.spacingBetweenAxesY = 2 chartSettings.labelsSpacing = 10 chartSettings.labelsToAxisSpacingY = 0 chartSettings.spacingBetweenAxesY = 0 chartSettings.axisTitleLabelsToLabelsSpacing = 0 chartSettings.zoomPan.panEnabled = true chartSettings.zoomPan.zoomEnabled = false chartSettings.zoomPan.maxZoomX = 3 chartSettings.zoomPan.minZoomX = 3 chartSettings.zoomPan.minZoomY = 1 chartSettings.zoomPan.maxZoomY = 1 return chartSettings }
When data source contains around (10 for ex) points, chart working without overlapping, but without fixed space between bars if you changed (increase/decrease) data source:
When data source contains around (35 for ex) points, bars overlapped:
SwiftCharts version 0.6.5 Swift version 5
Finally I found solution:
I had to set the minZoomX and maxZoomX (in chart settings) with fixed value which the number of pages for the chart (or number of scrollable area than the original width). why x ? because I want chart to scroll horizontally.
here is code: