DSFSparkline

repository·master·Indexed 41 days ago

https://github.com/dagronf/dsfsparkline

A lightweight component for creating condensed sparkline charts for macOS, iOS, and tvOS. It supports a wide variety of visualization types including Line, Bar, Stackline, Stripes, Dot, Win/Loss/Tie, Tablet, Pie, DataBar, PercentBar, WiperGauge, Activity Grid, and Circular Progress/Gauge. The library provides flexible rendering via SwiftUI, NSView/UIView, or bitmap surfaces, and supports both dynamic data streaming via DSFSparkline.DataSource and fixed data via DSFSparkline.StaticDataSource.

Tokens
8.6K
Snippets
25
Records
46
Agent score
1%

What's inside DSFSparkline

  1. Explore available sparkline graph types

    master

    DSFSparkline provides a wide variety of specialized sparkline types for different data visualizations:

    • Line: Simple line charts. Supports centering around zero, interpolation, and custom markers via markerDrawingBlock.
    • Bar: Simple bar charts. Can be centered around zero.
    • Stackline: Similar to bar charts but without separating individual columns; can be centered around zero.
    • Stripes: Maps values to a gradient (e.g., 'warming stripes' climate graphs). Supports integral pixel boundaries.
    • Dot: Dot-based sparklines (similar to Activity Viewer CPU history). Supports inverted modes.
    • Win/Loss/Tie: Represents positive as 'win', negative as 'loss', and zero as 'tie'.
    • Tablet: Uses filled circles for positive values and unfilled circles for negative values.
    • Pie: Basic pie chart sparkline.
    • DataBar: Supports 'percentage' and 'total' types.
    • PercentBar: A horizontal bar for a single value (0...1) with an optional text label.
    • WiperGauge: A gauge for a single value (0...1) with flat, gradient, or bucketed color mapping.
    • Activity Grid: GitHub-style grid with configurable cell counts, spacing, and fill schemes.
    • Circular Progress: Circular graphs with configurable track width, background, and padding (supports layering for 'health ring' effects).
    • Circular Gauge: Circular gauges with configurable track/line width, fill/stroke schemes, shadows, and animatable changes.
    • Dot: Dot-based sparklines (similar to Activity Viewer CPU history). Supports inverted modes.
  2. Embed sparklines in NSAttributedString

    master
    DSFSparkline supports embedding sparklines directly within NSAttributedString. You can use the snapshot method on the base sparkline view class to produce an NSImage (macOS) or UIImage (iOS) version of the sparkline, which can then be used as a text attachment.
  3. Use static graph overlays

    master

    Static graph overlays represent a fixed set of values (like a pie chart). They do not react to real-time data pushes; instead, they update only when a new DSFSparkline.StaticDataSource is assigned to them.

    let bitmap = DSFSparklineSurface.Bitmap()
    let pie = DSFSparklineOverlay.Pie()
    pie.dataSource = DSFSparkline.StaticDataSource([10, 55, 20])
    pie.lineWidth = 0.5
    pie.strokeColor = CGColor.black
    
    bitmap.addOverlay(pie)
    
    // Generate an image with retina scale
    let image = bitmap.image(width: 18, height: 18, scale: 2)!
  4. How to build sparklines using overlays

    master

    Overlay sparklines provide maximum flexibility and configuration. They are more complex to set up than prebuilt views and consist of three fundamental building blocks:

    1. A surface: The destination where the sparkline is drawn.
    2. A datasource: The set of values to draw.
    3. One or more overlays: The individual 'layers' that render different components of the sparkline.
  5. Use dynamic graph overlays

    master

    Dynamic graph overlays automatically update their visual representation as new values are 'pushed' onto their dataSource. This is ideal for showing historical data sets that evolve over time. As data is added, the view updates automatically, and older data falling outside the datasource window is discarded.

    let bitmap = DSFSparklineSurface.Bitmap()   // Create a bitmap surface
    let line = DSFSparklineOverlay.Line()      // Create a line overlay
    line.strokeWidth = 1
    line.primaryFill = primaryFill
    line.dataSource = source                   // Assign the datasource to the overlay
    bitmap.addOverlay(line)                    // And add the overlay to the surface.
    
    // Generate an image with retina scale
    let image = bitmap.image(width: 50, height: 25, scale: 2)!
  6. How overlays and components work together

    master

    A sparkline is composed of one or more Overlays. Overlays represent the individual visual components of a sparkline (e.g., a line graph, a bar graph, or grid lines).

    Key behaviors:

    • Composition: You can add multiple overlays to a single DSFSparklineSurface. You can even overlay different graph types on the same surface.
    • Z-Order: The order in which you call addOverlay(_:) determines the drawing order. Overlays added later will appear on top of those added earlier.
    • Data Synchronization: Overlays can share the same dataSource. If the data changes (e.g., via a push), all overlays using that source will automatically update.
    • Components: Some overlays are not graphs themselves but are "components" used to augment a graph, such as ZeroLine, RangeHighlight, or GridLines. These typically use the same dataSource to ensure they align correctly with the graph data.
  7. How to build sparklines using prebuilt views

    master

    For quick implementation in SwiftUI or via Interface Builder, use prebuilt views. These are simpler to set up than overlays but offer a more limited set of styling options. To use a prebuilt view, you need two components:

    1. A datasource: The set of values to draw.
    2. A prebuilt view type: The NSView/UIView/SwiftUI view used to render the sparkline.
    # No specific code provided for prebuilt views in this segment, but they require a datasource and a view type.
  8. Use prebuilt sparkline views in SwiftUI

    master

    Every prebuilt sparkline view has a SwiftUI companion view accessible via the .SwiftUI property (e.g., DSFSparklineLineGraphView.SwiftUI). You can pass a DSFSparkline.DataSource and various styling parameters like graphColor, lineWidth, or zeroLineDefinition directly into the view's initializer.

    struct SparklineView: View {
    
       let leftDataSource: DSFSparkline.DataSource
       let rightDataSource: DSFSparkline.DataSource
       
       let BigCyanZeroLine = DSFSparkline.ZeroLineDefinition(
          color: .cyan,
          lineWidth: 3,
          lineDashStyle: [4,1,2,1]
       )
       
       var body: some View {
          HStack {
             DSFSparklineLineGraphView.SwiftUI(
                dataSource: leftDataSource,
                graphColor: DSFColor.red,
                interpolated: true)
             DSFSparklineBarGraphView.SwiftUI(
                dataSource: rightDataSource,
                graphColor: DSFColor.blue,
                lineWidth: 2,
                showZeroLine: true,
                zeroLineDefinition: BigCyanZeroLine)
          }
       }
    }
  9. Install DSFSparkline via Swift Package Manager

    master

    To integrate DSFSparkline into your project, use the Swift Package Manager (SPM) and add the following repository URL:

    https://github.com/dagronf/DSFSparkline

    Important: You must choose exactly one package product to link to your target. Linking multiple products will cause inconsistent linker errors.

    https://github.com/dagronf/DSFSparkline
  10. Use prebuilt sparkline views in UIKit

    master

    DSFSparkline provides several 'prebuilt' views designed for quick integration. These views have a limited scope compared to custom implementations but are easier to set up. To use them in UIKit, instantiate the view, configure its properties (like graphColor or showZeroLine), and assign a DSFSparklineDataSource to its dataSource property. The view automatically updates whenever data is pushed to or set on the data source.

    // Create the view
    let sparklineView = DSFSparklineLineGraphView(…)
    sparklineView.graphColor = UIColor.blue
    sparklineView.showZeroLine = true
    
    // Create the datasource and assign to the view
    let sparklineDataSource = DSFSparklineDataSource(windowSize: 30, range: -1.0 ... 1.0)
    sparklineView.dataSource = sparklineDataSource
    
    // Add a single new data element to the sparkline
    sparklineDataSource.push(value: 0.7)                          // view automatically updates with new data
    
    // Add a set of data to the sparkline
    sparklineDataSource.push(values: [0.3, -0.2, 1.0])            // view automatically updates with new data
    
    // Completely replace the sparkline data with a new set of data
    sparklineDataSource.set(values: [0.2, -0.2, 0.0, 0.9, 0.8])   // view automatically resets to new data
  11. Migration from v2.0.0: Renamed types and properties

    master

    If you are upgrading from version 2.0.0, note the following breaking changes:

    • View Suffix: Primary views now include a View postfix. For example:
      • DSFSparklineLineGraph $\rightarrow$ DSFSparklineLineGraphView
      • DSFSparklineBarGraph $\rightarrow$ DSFSparklineBarGraphView
      • DSFSparklineDotGraph $\rightarrow$ DSFSparklineDotGraphView
    • Module Naming: SLColor and SLView have been renamed to DSFColor and DSFView for consistency.
    • Window Size: The windowSize property was removed from DSFSparklineDataSourceView. For Interface Builder support, use the graphWindowSize inspectable instead. If you see KVC errors regarding windowSize in your logs, remove it from your .xib file and use graphWindowSize.
  12. Create a SwiftUI line graph with overlays

    master

    Use DSFSparklineSurface.SwiftUI to render sparklines in SwiftUI. You compose the final view by passing an array of DSFSparklineOverlay objects. Common overlays include:

    • DSFSparklineOverlay.Line: The primary data line.
    • DSFSparklineOverlay.ZeroLine: A line representing a specific value (e.g., 0 or a midpoint).
    • DSFSparklineOverlay.RangeHighlight: A colored area highlighting a specific range of values.

    Overlays are layered in the order they appear in the array.

    fileprivate let SwiftUIDemoDataSource: DSFSparkline.DataSource = {
       let d = DSFSparkline.DataSource(windowSize: 20, range: 0 ... 1, zeroLineValue: 0.5)
         d.push(values: [0.72, 0.84, 0.15, 0.16, 0.30, 0.58, 0.87, 0.44, 0.02, 0.27, 0.48, 0.16, 0.15, 0.14, 0.81, 0.53, 0.67, 0.52, 0.07, 0.50])
         return d
      }()
    
    struct SuperCoolLineSpark: View {
       var zeroOverlay: DSFSparklineOverlay = {
          let zeroLine = DSFSparklineOverlay.ZeroLine()
          zeroLine.dataSource = SwiftUIDemoDataSource
          zeroLine.dashStyle = []
          return zeroLine
       }()
    
       var rangeOverlay: DSFSparklineOverlay = {
          let highlight = DSFSparklineOverlay.RangeHighlight()
          highlight.dataSource = SwiftUIDemoDataSource
          highlight.highlightRange = 0.0 ..< 0.2
          highlight.fill = DSFSparkline.Fill.Color(DSFColor.gray.withAlphaComponent(0.4).cgColor)
          return highlight
       }()
    
       var lineOverlay: DSFSparklineOverlay = {
          let lineOverlay = DSFSparklineOverlay.Line()
          lineOverlay.dataSource = SwiftUIDemoDataSource
          lineOverlay.primaryStrokeColor = DSFColor.systemBlue.cgColor
          lineOverlay.primaryFill = DSFSparkline.Fill.Color(DSFColor.systemBlue.withAlphaComponent(0.3).cgColor)
          lineOverlay.secondaryStrokeColor = DSFColor.systemYellow.cgColor
          lineOverlay.secondaryFill = DSFSparkline.Fill.Color(DSFColor.systemYellow.withAlphaComponent(0.3).cgColor)
          lineOverlay.strokeWidth = 1
          lineOverlay.markerSize = 4
          lineOverlay.centeredAtZeroLine = true
          return lineOverlay
       }()
    
       var body: some View {
          DSFSparklineSurface.SwiftUI([
             rangeOverlay,
             zeroOverlay,
             lineOverlay,
          ])
          .frame(width: 150, height: 40)
       }
    }