SwiftUI 中的 LineChart 多种 AreaMark 颜色

问题描述 投票:0回答:1

我尝试根据您在线图中的位置来研究不同的颜色。但这没有成功。可悲的是,总是会出现一些问题。我将展示一些示例,希望人们能够清楚地了解我想要实现的目标:

第一:

    struct Value: Identifiable {
    var x: String
    var y: Int
    var color: String
    var id: UUID = UUID()
}

struct ContentView12: View {
    let data: [Value] = [
        .init(x: "0", y: 3, color: "blue"),
        .init(x: "1", y: 4, color: "blue"),
        .init(x: "2", y: 5, color: "blue"),
        .init(x: "3", y: 8, color: "blue"),
        .init(x: "4", y: -6, color: "red"),
        .init(x: "5", y: -4, color: "red"),
        .init(x: "6", y: -6, color: "red"),
        .init(x: "7", y: -8, color: "red"),
        .init(x: "8", y: 10, color: "blue"),
        .init(x: "9", y: 8, color: "blue"),
        .init(x: "10", y: 5, color: "blue"),
        .init(x: "11", y: 7, color: "blue"),
        .init(x: "12", y: 10, color: "blue")
    ]
    
    var body: some View {
        
        
        VStack {
            Chart(data) { v in
                LineMark(
                    x: .value("x", v.x),
                    y: .value("y", v.y)
                )
                .interpolationMethod(.linear)
                .foregroundStyle(Color.black)
                
                AreaMark(
                    x: .value("x", v.x),
                    y: .value("y", v.y)
                )
                .interpolationMethod(.linear)
                .foregroundStyle(by: .value("area", v.color))
            }
            .chartForegroundStyleScale([
                "red": Color.red,
                "blue": Color.blue,
                "green": Color.green
            ])
            
        }
        .frame(maxHeight: 300)

    }
}

Not really what I long for

第二:

Chart(lineModel) { cost in
                    LineMark(
                        x: .value("Date", cost.date),
                        y: .value("Price", cost.amount)
                    )
                    AreaMark(
                        x: .value("Date", cost.date),
                        y: .value("Price", cost.amount),
                        stacking: .unstacked
                    )
                    .foregroundStyle(by: .value("Price", cost.amount >= 0 ? "blue" : "red"))
                }
                .chartForegroundStyleScale([
                    "red": Color.red,
                    "blue": Color.blue
                ])

Neither did this one work

swiftui linechart
1个回答
0
投票

您需要将数据分成每个点和颜色的片段。 然后画出每个部分的图表

//
//  ContentView.swift
//  test
//
//  Created by HZ on 13/06/2024.
//

import SwiftUI
import Charts

struct Value: Identifiable {
    var x: String
    var y: Int
    var color: String
    var id: UUID = UUID()
}

struct ContentView1: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

struct ContentView: View {
    
    let data: [Value] = [
        .init(x: "0", y: 3, color: "blue"),
        .init(x: "1", y: 4, color: "blue"),
        .init(x: "2", y: 5, color: "blue"),
        .init(x: "3", y: 8, color: "blue"),
        .init(x: "4", y: -6, color: "red"),
        .init(x: "5", y: -4, color: "red"),
        .init(x: "6", y: -6, color: "red"),
        .init(x: "7", y: -8, color: "red"),
        .init(x: "8", y: 10, color: "blue"),
        .init(x: "9", y: 8, color: "blue"),
        .init(x: "10", y: 5, color: "blue"),
        .init(x: "11", y: 7, color: "blue"),
        .init(x: "12", y: 10, color: "blue")
    ]
    
    var body: some View {
        VStack {
            Chart {
                ForEach(segmentData(data: data), id: \.id) { segment in
                    ForEach(segment.data) { v in
                        LineMark(
                            x: .value("x", v.x),
                            y: .value("y", v.y)
                        )
                        .interpolationMethod(.linear)
                        .foregroundStyle(by: .value("area", v.color))
                        
                        AreaMark(
                            x: .value("x", v.x),
                            y: .value("y", v.y)
                        )
                        .interpolationMethod(.linear)
                        .foregroundStyle(by: .value("area", v.color))
                    }
                }
            }
            .chartForegroundStyleScale([
                "red": Color.red,
                "blue": Color.blue
            ])
        }
        .frame(maxHeight: 300)
    }
    
    func segmentData(data: [Value]) -> [Segment] {
        var segments: [Segment] = []
        var currentSegment: [Value] = []
        
        for i in 0..<data.count {
            let value = data[i]
            if currentSegment.isEmpty || currentSegment.last!.color == value.color {
                currentSegment.append(value)
            } else {
                segments.append(Segment(id: UUID(), data: currentSegment))
                currentSegment = [value]
            }
        }
        
        if !currentSegment.isEmpty {
            segments.append(Segment(id: UUID(), data: currentSegment))
        }
        
        return segments
    }
    
    struct Segment: Identifiable {
        var id: UUID
        var data: [Value]
    }
}
#Preview {
    ContentView()
}
© www.soinside.com 2019 - 2024. All rights reserved.