Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get legend or x and y labels #243

Open
dadixon opened this issue Jun 2, 2022 · 8 comments
Open

Can't get legend or x and y labels #243

dadixon opened this issue Jun 2, 2022 · 8 comments
Labels

Comments

@dadixon
Copy link

dadixon commented Jun 2, 2022

v2 ticket

Ticket description:

I'm having trouble getting the legend and labels to show in the ChartGrid with a LineChart. I'm passing in the tuple for the data but only the data is displayed

var demoData: [(String, Double)] = [
      ("M", 8),
      ("T", 2),
      ("W", 4),
      ("T", 6),
      ("F", 12),
      ("S", 9),
      ("S", 2)
]

var body: some View {

   ChartGrid {
       LineChart()
       ChartLabel("")
          .labelStyle(.automatic)
   }
       .data(demoData)
       .chartStyle(ChartStyle(backgroundColor: .white,
                                         foregroundColor: ColorGradient(.blue, .purple)))
}

Screen Shot 2022-06-02 at 10 30 16 AM

@dadixon dadixon added the v2 label Jun 2, 2022
@JakobStadlhuber
Copy link

Same

@app4g
Copy link

app4g commented Jul 27, 2022

The data is already being parsed but it's not implemented in the code for some reason.
You can try editing it like below. (this is specifically for BarChart)

Look for the code comment "// BarChartLabel"

import SwiftUI

/// A single row of data, a view in a `BarChart`
public struct BarChartRow: View {
    @EnvironmentObject var chartValue: ChartValue
    @ObservedObject var chartData: ChartData
    @State private var touchLocation: CGFloat = -1.0

    var style: ChartStyle
    
    var maxValue: Double {
        guard let max = chartData.points.max() else {
            return 1
        }
        return max != 0 ? max : 1
    }

	/// The content and behavior of the `BarChartRow`.
	///
	/// Shows each `BarChartCell` in an `HStack`; may be scaled up if it's the one currently being touched.
	/// Not using a drawing group for optimizing animation.
	/// As touched (dragged) the `touchLocation` is updated and the current value is highlighted.
    public var body: some View {
        GeometryReader { geometry in
            HStack(alignment: .bottom,
                   spacing: geometry.frame(in: .local).width / CGFloat(chartData.data.count * 3)) {
                    ForEach(0..<chartData.data.count, id: \.self) { index in
                        BarChartCell(value: chartData.normalisedPoints[index],
                                     index: index,
                                     gradientColor: self.style.foregroundColor.rotate(for: index),
                                     touchLocation: self.touchLocation,
                                     label: self.chartData.values[index]) // BarChartLabel
                            .scaleEffect(self.getScaleSize(touchLocation: self.touchLocation, index: index), anchor: .bottom)
                            .animation(Animation.easeIn(duration: 0.2))
                    }
//                    .drawingGroup()
            }
            .frame(maxHeight: chartData.isInNegativeDomain ? geometry.size.height / 2 : geometry.size.height)
            .gesture(DragGesture()
                .onChanged({ value in
                    let width = geometry.frame(in: .local).width
                    self.touchLocation = value.location.x/width
                    if let currentValue = self.getCurrentValue(width: width) {
                        self.chartValue.currentValue = currentValue
                        self.chartValue.interactionInProgress = true
                    }
                })
                .onEnded({ value in
                    self.chartValue.interactionInProgress = false
                    self.touchLocation = -1
                })
            )
        }
    }

	/// Size to scale the touch indicator
	/// - Parameters:
	///   - touchLocation: fraction of width where touch is happening
	///   - index: index into data array
	/// - Returns: a scale larger than 1.0 if in bounds; 1.0 (unscaled) if not in bounds
    func getScaleSize(touchLocation: CGFloat, index: Int) -> CGSize {
        if touchLocation > CGFloat(index)/CGFloat(chartData.data.count) &&
           touchLocation < CGFloat(index+1)/CGFloat(chartData.data.count) {
            return CGSize(width: 1.4, height: 1.1)
        }
        return CGSize(width: 1, height: 1)
    }

	/// Get data value where touch happened
	/// - Parameter width: width of chart
	/// - Returns: value as `Double` if chart has data
    func getCurrentValue(width: CGFloat) -> Double? {
        guard self.chartData.data.count > 0 else { return nil}
            let index = max(0,min(self.chartData.data.count-1,Int(floor((self.touchLocation*width)/(width/CGFloat(self.chartData.data.count))))))
            return self.chartData.points[index]
        }
}

struct BarChartRow_Previews: PreviewProvider {
     static let chartData = ChartData([6, 2, 5, 6, 7, 8, 9])
    static let chartData2 = ChartData([("M",6), ("T",2), ("W",5), ("T",6), ("F",7), ("S",8), ("S",9)])
    static let chartStyle = ChartStyle(backgroundColor: .white, foregroundColor: .orangeBright)
    static var previews: some View {
      VStack{
        BarChartRow(chartData: chartData, style: chartStyle)
          .border(.red)
          .frame(width: 100, height: 100)
        HStack (alignment: .lastTextBaseline){
          VStack {
              Text("Load")
              Text("400")
          }

          Spacer()
          BarChartRow(chartData: chartData2, style: chartStyle)
            .border(.red)
            .frame(width: 150, height: 50)
          
        }
      }
      .padding([.leading, .trailing],10)

    }
}

BarChartCell

import SwiftUI

/// A single vertical bar in a `BarChart`
public struct BarChartCell: View {
  var value: Double
  var index: Int = 0
  var gradientColor: ColorGradient
  var touchLocation: CGFloat
  var label: String = "" // BarChartLabel
  
  @State private var didCellAppear: Bool = false
  
  public init( value: Double,
               index: Int = 0,
               gradientColor: ColorGradient,
               touchLocation: CGFloat,
               label: String = "") { // BarChartLabel
    self.value = value
    self.index = index
    self.gradientColor = gradientColor
    self.touchLocation = touchLocation
    self.label = label     // BarChartLabel
  }
  
  /// The content and behavior of the `BarChartCell`.
  ///
  /// Animated when first displayed, using the `firstDisplay` variable, with an increasing delay through the data set.
  public var body: some View {
    VStack{ // BarChartLabel - Embed it into a Stack
      BarChartCellShape(value: didCellAppear ? value : 0.0)
        .fill(gradientColor.linearGradient(from: .bottom, to: .top))
        .onAppear {
          self.didCellAppear = true
        }
        .onDisappear {
          self.didCellAppear = false
        }
        .transition(.slide)
        .animation(Animation.spring().delay(self.touchLocation < 0 || !didCellAppear ? Double(self.index) * 0.04 : 0))
      Text(String(label)) // BarChartLabel
        .font(.caption).    // BarChartLabel
    }
  }
}

struct BarChartCell_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            Group {
                BarChartCell(value: 0, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat(), label: "POPO")
                BarChartCell(value: 0.5, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat())
                BarChartCell(value: 0.75, gradientColor: ColorGradient.whiteBlack, touchLocation: CGFloat())
                BarChartCell(value: 1, gradientColor: ColorGradient(.purple), touchLocation: CGFloat())
            }

            Group {
                BarChartCell(value: 1, gradientColor: ColorGradient.greenRed, touchLocation: CGFloat())
                BarChartCell(value: 1, gradientColor: ColorGradient.whiteBlack, touchLocation: CGFloat())
                BarChartCell(value: 1, gradientColor: ColorGradient(.purple), touchLocation: CGFloat())
            }.environment(\.colorScheme, .dark)
        }
    }
}

Screenshot 2022-07-27 at 10 07 59 AM

@app4g
Copy link

app4g commented Jul 27, 2022

struct ContentView: View {
//  var demoData: [String, Double] = [("M",1.0),("T",2.0),("W",4.0), ("T", 8.0), ("F",10.0), ("S",9.0),("S", 2.0)]
  var demoData: [(String, Double)] = ([("M",9), ("T",2), ("W",5), ("T",6), ("F",7), ("S",8), ("S",9)])
  var demoData2: [(String, Double)] = ([("M",1), ("T",11), ("W",12), ("T",6), ("F",11), ("S",0), ("S",7)])
  var demoData3: [(String, Double)] = ([("M",1.55), ("T",2.1), ("W",1.6), ("T",0.3), ("F",0.9), ("S",1.3), ("S",2.0)])

    var body: some View {
    VStack {
      Text("Hello, world!")
      
      HStack{
        CardView(showShadow: true) {
          Text("Load")
            .padding([.leading, .top],10)
            .font(.caption)
          ChartLabel("400", type: .custom(size: 10, padding: EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0), color: Color(UIColor.secondaryLabel)), format: "%0.0f")
          BarChart()
            .padding(.horizontal,10)
            .padding(.bottom,5)
        }
        .data(demoData)
        .chartStyle(ChartStyle(backgroundColor: .white,
                               foregroundColor: [ColorGradient(.blue, .purple)]
                              ))

        CardView(showShadow: true) {
          Text("Distance")
            .padding([.leading, .top],10)
            .font(.caption)
          ChartLabel("400km", type: .custom(size: 10, padding: EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0), color: Color(UIColor.secondaryLabel)), format: "%0.0f")
          BarChart()
            .padding(.horizontal,10)
            .padding(.bottom,5)
        }
        .data(demoData2)
        .chartStyle(ChartStyle(backgroundColor: .white,
                               foregroundColor: [ColorGradient(.blue, .purple)]
                              ))

        CardView(showShadow: true) {
          Text("Time")
            .padding([.leading, .top],10)
            .font(.caption)
          ChartLabel("10h 50m", type: .custom(size: 10, padding: EdgeInsets(top: 0.0, leading: 10.0, bottom: 0.0, trailing: 10.0), color: Color(UIColor.secondaryLabel)), format: "%0.1f")
          BarChart()
            .padding(.horizontal,10)
            .padding(.bottom,5)
        }
        .data(demoData3)
        .chartStyle(ChartStyle(backgroundColor: .white,
                               foregroundColor: [ColorGradient(.blue, .purple)]
                              ))

      }
      .frame(width: .infinity, height: 150, alignment: .center)

    }
  }
}

Screenshot 2022-07-27 at 11 32 44 AM

@JakobStadlhuber
Copy link

@app4g that looks nice, you forked already ChartView but without changes, do you have plans to implement the above shown changes? Would be nice :)

@app4g
Copy link

app4g commented Jul 27, 2022

@JakobStadlhuber I just made the changes locally and am just still playing around / testing it.
eg: it doesn't honour dark mode in cardview

and trying to get this to work. In the interim (screenshot) shows just changing it from .white to .lightgray jus to see if it works.

Screenshot 2022-07-27 at 8 00 00 PM

Yeah.. I've forked It but have yet to sync it. Possibly over the next few days as I play more w/ it.

@JakobStadlhuber
Copy link

Sounds good @app4g I will follow your repo. Do you think it is possible to get a y axis too?

@JakobStadlhuber
Copy link

@app4g some news with the forked repo?

@app4g
Copy link

app4g commented Aug 3, 2022

Forked Repo :
https://github.com/app4g/ChartView

Here is the Demo Project or rather the code I was working on to see /make the changes
https://github.com/app4g/ChartViewV2-Demo-Project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants