0
  • 如何使用 SwiftChars 库指定条形图中条形之间的最小间距?

    • 这是我使用 SwiftCharts 显示条形图的代码示例:
    // 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
     }
    
    
    • 当数据源包含大约(前 10 个)点时,如果您更改(增加/减少)数据源,则图表不会重叠,但条形之间没有固定空间: 不重叠

    • 当数据源包含大约(前 35 个)点时,条形重叠: 重叠

SwiftCharts 版本 0.6.5 Swift 版本 5

4

1 回答 1

1

最后我找到了解决方案:

我必须将 minZoomX 和 maxZoomX(在图表设置中)设置为固定值,即图表的页数(或可滚动区域的数量比原始宽度)。为什么 x ?因为我希望图表水平滚动。

这是代码:

        let barWidth: CGFloat = 30.0
        let spaceBetweenBars: CGFloat = 80.0

        let zoomXValue = CGFloat(barsDataSource.count) / (UIScreen.main.bounds.width / (barWidth + spaceBetweenBars))
        chartSettings.zoomPan.minZoomX = zoomXValue
        chartSettings.zoomPan.maxZoomX = zoomXValue

于 2019-09-16T10:20:38.617 回答