Skip to content

Commit

Permalink
fix: 馃悰 fix x axis ui update issue
Browse files Browse the repository at this point in the history
  • Loading branch information
shengxu7 authored and MarcoEidinger committed Sep 28, 2020
1 parent fe7783f commit 1ec70b0
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 79 deletions.
2 changes: 1 addition & 1 deletion Sources/FioriCharts/Charts/BarChart/BarChart.swift
Expand Up @@ -199,7 +199,7 @@ class BarAxisDataSource: DefaultAxisDataSource {
var startIndex = Int(startPosY / unitHeight).clamp(low: 0, high: maxDataCount - 1)
var startOffset = unitHeight * CGFloat(startIndex) - startPosY

if abs(startOffset) >= clusterHeight {
if abs(startOffset) >= clusterHeight && startIndex < maxDataCount - 1 {
startIndex += 1
startOffset = unitHeight * CGFloat(startIndex) - startPosY
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/FioriCharts/Charts/ColumnChart/ColumnChart.swift
Expand Up @@ -168,7 +168,7 @@ class ColumnAxisDataSource: DefaultAxisDataSource {

var startIndex = Int(model.startPos.x / unitWidth).clamp(low: 0, high: maxDataCount - 1)
var startOffset = unitWidth * CGFloat(startIndex) - model.startPos.x
if abs(startOffset) >= clusterWidth {
if abs(startOffset) >= clusterWidth && startIndex < maxDataCount - 1 {
startIndex += 1
startOffset = unitWidth * CGFloat(startIndex) - model.startPos.x
}
Expand Down
9 changes: 4 additions & 5 deletions Sources/FioriCharts/Charts/Common/AxisDataSource.swift
Expand Up @@ -295,14 +295,13 @@ class DefaultAxisDataSource: AxisDataSource {
}

func displayCategoryIndexesAndOffsets(_ model: ChartModel, rect: CGRect) -> (startIndex: Int, endIndex: Int, startOffset: CGFloat, endOffset: CGFloat) {
//return (0, 0, 0, 0)
let width = rect.size.width
let startPosIn = model.startPos.x
let maxDataCount = model.numOfCategories(in: 0)
let unitWidth: CGFloat = max(width * model.scale / CGFloat(max(maxDataCount - 1, 1)), 1)
let startIndex = Int(startPosIn / unitWidth).clamp(low: 0, high: maxDataCount - 1)

let unitWidth: CGFloat = max(width * model.scale / CGFloat(max(ChartUtility.numOfDataItems(model) - 1, 1)), 1)
let startIndex = Int(startPosIn / unitWidth)

var endIndex = Int(((startPosIn + width) / unitWidth).rounded(.up))
var endIndex = Int(((startPosIn + width) / unitWidth).rounded(.up)).clamp(low: 0, high: maxDataCount - 1)
let startOffset: CGFloat = -startPosIn.truncatingRemainder(dividingBy: unitWidth)

let endOffset: CGFloat = (CGFloat(endIndex) * unitWidth - startPosIn - width).truncatingRemainder(dividingBy: unitWidth)
Expand Down
42 changes: 19 additions & 23 deletions Sources/FioriCharts/Charts/Common/XAxisView.swift
Expand Up @@ -10,15 +10,12 @@ import SwiftUI

struct XAxisView: View {
@EnvironmentObject var model: ChartModel
@Environment(\.axisDataSource) var axisDataSource

let isShowBaselineOnly: Bool
let isShowLabelsOnly: Bool

weak var axisDataSource: AxisDataSource? = nil

@State private var xAxisSize: CGSize = CGSize(width: 0, height: 24)

init(axisDataSource: AxisDataSource? = nil, isShowBaselineOnly: Bool = false, isShowLabelsOnly: Bool = false) {
self.axisDataSource = axisDataSource
init(isShowBaselineOnly: Bool = false, isShowLabelsOnly: Bool = false) {
self.isShowBaselineOnly = isShowBaselineOnly
self.isShowLabelsOnly = isShowLabelsOnly
}
Expand All @@ -30,10 +27,7 @@ struct XAxisView: View {
}

func makeBody(in rect: CGRect) -> some View {
var xAxisLabels: [AxisTitle] = []
if let res = axisDataSource?.xAxisLabels(model, rect: rect) {
xAxisLabels = res
}
let xAxisLabels: [AxisTitle] = axisDataSource.xAxisLabels(model, rect: rect)

var baselineYPos: CGFloat = model.categoryAxis.baseline.width / 2
var labelYPos: CGFloat = model.categoryAxis.baseline.width + 3 + (rect.size.height - model.categoryAxis.baseline.width - 3) / 2
Expand All @@ -48,18 +42,16 @@ struct XAxisView: View {
}

let axis = model.chartType == .bar || model.chartType == .stackedBar ? model.numericAxis : model.categoryAxis

return ZStack {
if !xAxisLabels.isEmpty && (axisDataSource?.isEnoughSpaceToShowXAxisLables ?? true) && !axis.labels.isHidden && !isShowBaselineOnly {
ForEach(xAxisLabels) { title in
if !axis.labels.isHidden {
// category labels
Text(title.title)
.font(.system(size: axis.labels.fontSize))
.foregroundColor(axis.labels.color)
.frame(maxWidth: rect.size.width / 2)
.position(x: title.pos.x, y: labelYPos)
}
if !xAxisLabels.isEmpty && axisDataSource.isEnoughSpaceToShowXAxisLables && !axis.labels.isHidden && !isShowBaselineOnly {
ForEach(xAxisLabels) { label in
// category labels
Text(label.title)
.font(.system(size: axis.labels.fontSize))
.foregroundColor(axis.labels.color)
.frame(maxWidth: rect.size.width / 2)
.position(x: label.pos.x, y: labelYPos)
}
}

Expand All @@ -84,13 +76,17 @@ struct XAxisView_Previews: PreviewProvider {

return Group {
ForEach(Tests.lineModels) {
XAxisView(axisDataSource: axisDataSource).environmentObject($0)
XAxisView()
.environmentObject($0)
.environment(\.axisDataSource, axisDataSource)
}
.frame(width: 300, height: 20, alignment: .topLeading)
.previewLayout(.sizeThatFits)

ForEach(Tests.stockModels) {
XAxisView(axisDataSource: axisStockDataSource).environmentObject($0)
XAxisView()
.environmentObject($0)
.environment(\.axisDataSource, axisStockDataSource)
}
.frame(width: 300, height: 20, alignment: .topLeading)
.previewLayout(.sizeThatFits)
Expand Down
55 changes: 8 additions & 47 deletions Sources/FioriCharts/Charts/Common/XYAxisChart.swift
Expand Up @@ -146,18 +146,18 @@ struct XYAxisChart<Content: View, Indicator: View>: View {
GridLinesAndChartView(chartView: chartView, indicatorView: indicatorView)
.frame(width: chartRect.width, height: chartRect.height)

XAxisView(axisDataSource: axisDataSource)
XAxisView()
.frame(height: xAxisRect.height)
} else if model.valueType == .allNegative {
XAxisView(axisDataSource: axisDataSource, isShowBaselineOnly: model.xAxisLabelsPosition == .fixedBottom ? true : false)
XAxisView(isShowBaselineOnly: model.xAxisLabelsPosition == .fixedBottom ? true : false)
.frame(height: xAxisRect.height)
.zIndex(1)

GridLinesAndChartView(chartView: chartView, indicatorView: indicatorView)
.frame(width: chartRect.width, height: chartRect.height)

if model.xAxisLabelsPosition == .fixedBottom {
XAxisView(axisDataSource: axisDataSource, isShowLabelsOnly: true)
XAxisView(isShowLabelsOnly: true)
.frame(height: xAxisLabelsRect.height)
.zIndex(1)
}
Expand All @@ -166,13 +166,13 @@ struct XYAxisChart<Content: View, Indicator: View>: View {
GridLinesAndChartView(chartView: chartView, indicatorView: indicatorView)
.frame(width: chartRect.width, height: chartRect.height)

XAxisView(axisDataSource: axisDataSource, isShowBaselineOnly: model.xAxisLabelsPosition == .fixedBottom ? true : false)
XAxisView(isShowBaselineOnly: model.xAxisLabelsPosition == .fixedBottom ? true : false)
.frame(height: xAxisRect.height)
.position(x: xAxisRect.size.width / 2, y: xAxisRect.origin.y + xAxisRect.size.height / 2)
}

if model.xAxisLabelsPosition == .fixedBottom {
XAxisView(axisDataSource: axisDataSource, isShowLabelsOnly: true)
XAxisView(isShowLabelsOnly: true)
.frame(height: xAxisLabelsRect.height)
.zIndex(1)
}
Expand Down Expand Up @@ -223,52 +223,13 @@ struct XYAxisChart<Content: View, Indicator: View>: View {
if model.chartType != .stock && model.categoryAxis.labelLayoutStyle == .allOrNothing && totalWidth > rect.size.width {
axisDataSource.isEnoughSpaceToShowXAxisLables = false
height = 0
} else {
axisDataSource.isEnoughSpaceToShowXAxisLables = true
}

return height > 0 ? height + 3 : 0
}

func xAxisMaxHeight(_ rect: CGRect) -> CGFloat {
let labels = axisDataSource.xAxisLabels(model, rect: rect)
if labels.isEmpty || (model.categoryAxis.baseline.isHidden && model.categoryAxis.labels.isHidden) {
return 0
}

if !model.categoryAxis.baseline.isHidden && model.categoryAxis.labels.isHidden {
return max(0, model.categoryAxis.baseline.width)
}

var height: CGFloat = 16
var totalWidth: CGFloat = 0
var prevXPos: CGFloat = -100000
var prevLabelWidth: CGFloat = 0
for label in labels {
let size: CGSize = label.title.isEmpty ? .zero : label.title.boundingBoxSize(with: model.categoryAxis.labels.fontSize)
// spacing btw baseline and labels are 3pt
height = max(height, size.height + model.categoryAxis.baseline.width + 3)

// check if the gap btw two adjacent labels is greater than 4pt
if label.pos.x < prevXPos + prevLabelWidth / 2.0 + size.width / 2.0 + 4 {
totalWidth += rect.size.width
}
// min spacing btw labels are 4pt
if size.width > 0 {
totalWidth += size.width + 4
prevXPos = label.pos.x
prevLabelWidth = size.width
}
}
totalWidth -= 4

// show nothing
if model.chartType != .stock && model.categoryAxis.labelLayoutStyle == .allOrNothing && totalWidth > rect.size.width {
axisDataSource.isEnoughSpaceToShowXAxisLables = false
height = 0
}

return height + model.categoryAxis.baseline.width + 3
}

/**
Minimum: 20px from left edge of content area
Maximum: 35% of content area
Expand Down
Expand Up @@ -205,7 +205,7 @@ class StackedBarAxisDataSource: DefaultAxisDataSource {
var startIndex = Int(startPosY / unitHeight).clamp(low: 0, high: maxDataCount - 1)
var startOffset = unitHeight * CGFloat(startIndex) - startPosY

if abs(startOffset) >= clusterHeight {
if abs(startOffset) >= clusterHeight && startIndex < maxDataCount - 1 {
startIndex += 1
startOffset = unitHeight * CGFloat(startIndex) - startPosY
}
Expand Down
Expand Up @@ -171,7 +171,7 @@ class StackedColumnAxisDataSource: DefaultAxisDataSource {

var startIndex = Int(model.startPos.x / unitWidth).clamp(low: 0, high: maxDataCount - 1)
var startOffset = unitWidth * CGFloat(startIndex) - model.startPos.x
if abs(startOffset) >= clusterWidth {
if abs(startOffset) >= clusterWidth && startIndex < maxDataCount - 1 {
startIndex += 1
startOffset = unitWidth * CGFloat(startIndex) - model.startPos.x
}
Expand Down

0 comments on commit 1ec70b0

Please sign in to comment.