Bractlet / elm-plot / Plot

Series

viewSeries : List (Series data msg) -> data -> Html msg

A series is a list of data points possibly joined by some sort of interpolation. The example below renders an area, with the coordinates of the last argument given to viewSeries, where the coordinates are emphasized with a circle.

view : Svg msg
view =
    viewSeries
        [ area (List.map (\{ x, y } -> circle x y)) ]
        [ { x = 0, y = 1 }
        , { x = 2, y = 2 }
        , { x = 3, y = 3 }
        , { x = 4, y = 5 }
        , { x = 5, y = 8 }
        ]

Simple series

dots : (data -> List (DataPoint msg)) -> Series data msg

line : (data -> List (DataPoint msg)) -> Series data msg

area : (data -> List (DataPoint msg)) -> Series data msg

Simple data points

Data points are the coordinates which make up your series. They come with views or without. Pass your x and y coordinates, respectively, to create a data point for your series.

clear : Basics.Float -> Basics.Float -> DataPoint msg

A data point without a view.

square : Basics.Float -> Basics.Float -> DataPoint msg

circle : Basics.Float -> Basics.Float -> DataPoint msg

diamond : Basics.Float -> Basics.Float -> DataPoint msg

triangle : Basics.Float -> Basics.Float -> DataPoint msg

Custom series


type alias Series data msg =
{ axis : Axis
, interpolation : Interpolation
, toDataPoints : data -> List (DataPoint msg) 
}

The series configuration allows you to specify your own interpolation and how your data is transformed into series data points, but also a vertical axis relating to the series' scale. This way it's made sure you never have more than one y-axis per data set, because that would be just crazy.


type Interpolation
    = None
    | Linear (Maybe String) (List (Svg.Attribute Basics.Never))
    | Monotone (Maybe String) (List (Svg.Attribute Basics.Never))

Interpolation is basically the line that goes between your data points. Your current options are:

All but None takes a color which determines whether it draws the area below the interpolation and a list of attributes which you can use for styling your interpolation.

customSeries : Axis -> Interpolation -> (data -> List (DataPoint msg)) -> Series data msg

Make your own series! The standard line series looks like this on the inside:

line : (data -> List (DataPoint msg)) -> Series data msg
line toDataPoints =
    { axis = normalAxis
    , interpolation = Linear Nothing [ stroke pinkStroke ]
    , toDataPoints = toDataPoints
    }

Maybe pink isn't really your color and you want to make it green. No problem! You just add some different attributes to the interpolation. If you want a different interpolation or an area under that interpolation, look at the Interpolation type for more info.


type alias DataPoint msg =
{ view : Maybe (Svg msg)
, xLine : Maybe (AxisSummary -> LineCustomizations)
, yLine : Maybe (AxisSummary -> LineCustomizations)
, xTick : Maybe TickCustomizations
, yTick : Maybe TickCustomizations
, hint : Maybe (Html Basics.Never)
, x : Basics.Float
, y : Basics.Float 
}

The data point. Here you can do tons of crazy stuff, although most importantly, you can specify the coordinates of your plot with the x and y properties. Besides that you can:

dot : Svg msg -> Basics.Float -> Basics.Float -> DataPoint msg

Makes a data point provided a view, an x and a y.

hintDot : Svg msg -> Maybe Point -> Basics.Float -> Basics.Float -> DataPoint msg

Like dot, except it also takes a maybe coordinates to know if it should add a hint view/vertical line or not.

rangeFrameDot : Svg msg -> Basics.Float -> Basics.Float -> DataPoint msg

This dot implements a special plot in Tuftes book. It basically just adds ticks to your axis where your data points are! You might want to use clearAxis to remove all the other useless chart junk, now that you have all these nice ticks.

emphasizedDot : Svg msg -> Basics.Float -> Basics.Float -> DataPoint msg

Really a silly surprise dot you can use if you want to be flashy. Try it if you're feeling lucky.

customDot : Maybe (Svg msg) -> Maybe (AxisSummary -> LineCustomizations) -> Maybe (AxisSummary -> LineCustomizations) -> Maybe TickCustomizations -> Maybe TickCustomizations -> Maybe (Html Basics.Never) -> Basics.Float -> Basics.Float -> DataPoint msg

Just do whatever you want.

Small helper views

Just thought you might want a hand with all the views you need for your data points.

viewCircle : Basics.Float -> String -> Svg msg

Pass radius and color to make a circle!

viewSquare : Basics.Float -> String -> Svg msg

Pass width and color to make a square!

viewDiamond : Basics.Float -> Basics.Float -> String -> Svg msg

Pass width, height and color to make a diamond and impress with your classy plot!

viewTriangle : String -> Svg msg

Pass a color to make a triangle! Great for academic looking plots.

Bars

viewBars : Bars data msg -> data -> Html msg

This is for viewing a bar chart! The example below renders four groups of two bars each, labeled Q1, Q2, Q3, Q4 respectively.

view : Svg msg
view =
    viewBars
        (groups (List.map (\data -> group data.label data.heights)))
        [ { label = "Q1", heights = [ 1, 2 ] }
        , { label = "Q2", heights = [ 3, 4 ] }
        , { label = "Q3", heights = [ 4, 5 ] }
        , { label = "Q4", heights = [ 3, 2 ] }
        ]

Simple bars

groups : (data -> List BarGroup) -> Bars data msg

For pink and blue bar groups. If you have more than two colors, you have to make your own group. Under this documentation, it looks like this:

groups : (data -> List BarGroup) -> Bars data msg
groups toGroups =
    { axis = normalAxis
    , toGroups = toGroups
    , styles = [ [ fill pinkFill ], [ fill blueFill ] ]
    , maxWidth = Percentage 75
    }

So you can just go right ahead and add a third pastel to those styles!

group : String -> List Basics.Float -> BarGroup

A pretty plain group, nothing fancy.

histogram : (data -> List BarGroup) -> Bars data msg

For histograms! Meaning that there is only one bar in each group and it's always one horizontal unit wide.

histogramBar : Basics.Float -> BarGroup

Custom bars


type alias Bars data msg =
{ axis : Axis
, toGroups : data -> List BarGroup
, styles : List (List (Svg.Attribute msg))
, maxWidth : MaxBarWidth 
}

The bar configurations allows you to specify the styles of your bars, the max width of your bars, how your data is transformed into bar groups, as well the vertical axis related to your bar series.


type alias BarGroup =
{ label : Basics.Float -> LabelCustomizations
, hint : Basics.Float -> Maybe (Svg Basics.Never)
, verticalLine : Basics.Float -> Maybe (AxisSummary -> LineCustomizations)
, bars : List Bar 
}

A bar group is, well, a group of bars attached to a single data point on the horizontal axis.


type MaxBarWidth
    = Percentage Basics.Int
    | Fixed Basics.Float

The width options of your bars. If Percentage is used, it will be maximum that percentage of one unit on the horizontal axis wide. Similarily, using Fixed will set your bar to be maximum the provided float in pixels.

hintGroup : Maybe Point -> String -> List Basics.Float -> BarGroup

For groups with a hint.

customGroups : Axis -> (data -> List BarGroup) -> List (List (Svg.Attribute msg)) -> MaxBarWidth -> Bars data msg

For special bar charts.

customGroup : (Basics.Float -> LabelCustomizations) -> (Basics.Float -> Maybe (Svg Basics.Never)) -> (Basics.Float -> Maybe (AxisSummary -> LineCustomizations)) -> List Bar -> BarGroup

For your special groups.

Custom plot


type alias PlotCustomizations msg =
{ attributes : List (Svg.Attribute msg)
, id : String
, width : Basics.Int
, height : Basics.Int
, defs : List (Svg msg)
, margin : { top : Basics.Int
, right : Basics.Int
, bottom : Basics.Int
, left : Basics.Int }
, onHover : Maybe (Maybe Point -> msg)
, hintContainer : PlotSummary -> List (Html Basics.Never) -> Html Basics.Never
, horizontalAxis : Axis
, grid : { horizontal : Grid
, vertical : Grid }
, junk : PlotSummary -> List (JunkCustomizations msg)
, toDomainLowest : Basics.Float -> Basics.Float
, toDomainHighest : Basics.Float -> Basics.Float
, toRangeLowest : Basics.Float -> Basics.Float
, toRangeHighest : Basics.Float -> Basics.Float 
}

The plot customizations. Here you may:

Note: The id is particularily important when you have several plots in your dom.


type alias PlotSummary =
{ x : AxisSummary
, y : AxisSummary 
}

defaultSeriesPlotCustomizations : PlotCustomizations msg

The default series plot customizations.

viewSeriesCustom : PlotCustomizations msg -> List (Series data msg) -> data -> Html msg

Plot your series with special needs!

defaultBarsPlotCustomizations : PlotCustomizations msg

The default bars plot customizations.

viewBarsCustom : PlotCustomizations msg -> Bars data msg -> data -> Html msg

Plot your bar series with special needs!

Hint customizations


type alias Point =
Internal.Draw.Point

Just an x and a y property.

normalHintContainer : PlotSummary -> List (Html Basics.Never) -> Html Basics.Never

A view located at the bottom left corner of your plot, holding the hint views you (maybe) added in your data points or groups.

flyingHintContainer : (Basics.Bool -> List (Html Basics.Never) -> Html Basics.Never) -> Maybe Point -> PlotSummary -> List (Html Basics.Never) -> Html Basics.Never

A view holding your hint views which flies around on your plot following the hovered x.

normalHintContainerInner : Basics.Bool -> List (Html Basics.Never) -> Html Basics.Never

The normal hint view.

Grid customizations


type Grid


type alias GridLineCustomizations =
{ attributes : List (Svg.Attribute Basics.Never)
, position : Basics.Float 
}

decentGrid : Grid

A grid with decent spacing. Uses the decentPositions function to calculate the positions of the grid lines. This also means that if you use decentPositions to calculate your tick positions, then they will match.

clearGrid : Grid

No grid. Tufte would be proud of you. 💛

customGrid : (AxisSummary -> List GridLineCustomizations) -> Grid

Make your own grid!

Junk


type alias JunkCustomizations msg =
{ x : Basics.Float
, y : Basics.Float
, view : Svg msg 
}

Just add whatever you want. A title might be an idea though.

junk : Svg msg -> Basics.Float -> Basics.Float -> JunkCustomizations msg

Takes a view, an x coordinate and a y coordinate, and you can put your junk anywhere! If you want to add a title, which I assume is the real reason why you're here, you can do this:

title : Svg msg
title =
  viewLabel
    [ fill "bleak-capitalistic-color"
    , style "text-anchor: end; font-style: italic;"
    ]
    "Ca$h earned"

view : Svg.Svg a
view =
  viewSeriesCustom
    { defaultSeriesPlotCustomizations
    | ...
    , junk = \summary -> [ junk title summary.x.max summary.y.max  ]
    , ...
    }
    [ customLine ]
    data

Not sure if this is self explanatory, but summary.x.min/max, summary.y.min/max are just floats which you can do anything you'd like with.

You can of course also put other junk here, like legends for example.

Axis customizations


type Axis


type alias AxisSummary =
{ min : Basics.Float
, max : Basics.Float
, dataMin : Basics.Float
, dataMax : Basics.Float
, marginLower : Basics.Float
, marginUpper : Basics.Float
, length : Basics.Float
, all : List Basics.Float 
}

A summary of information about an axis.


type alias TickCustomizations =
{ attributes : List (Svg.Attribute Basics.Never)
, length : Basics.Float
, position : Basics.Float 
}


type alias LabelCustomizations =
{ view : Svg Basics.Never
, position : Basics.Float 
}


type alias LineCustomizations =
{ attributes : List (Svg.Attribute Basics.Never)
, start : Basics.Float
, end : Basics.Float 
}

Various axis

normalAxis : Axis

A super regular axis.

normalBarsAxis : Axis

So because there is extra funky labels added to your bar groups, your axis should not be cluttered up with other random numbers. So use this one.

sometimesYouDoNotHaveAnAxis : Axis

When you don't have an axis, which is only sometimes.

clearAxis : Axis

An axis closest to zero, but doesn't look like much unless you use the rangeFrameDot.

axisAtMin : Axis

An axis which is placed at the minimum of your axis! Meaning if you use it as a vertical axis, then it will end up to the far left, and if you use it as a horizontal axis, then it will end up in the bottom.

axisAtMax : Axis

Like axisAtMin, but opposite.

customAxis : (AxisSummary -> AxisCustomizations) -> Axis

When you want to make your own axis. This is where the fun starts! The normalAxis looks like this on the inside:

normalAxis : Axis
normalAxis =
    customAxis <|
        \summary ->
            { position = closestToZero
            , axisLine = Just (simpleLine summary)
            , ticks = List.map simpleTick (decentPositions summary |> remove 0)
            , labels = List.map simpleLabel (decentPositions summary |> remove 0)
            , flipAnchor = False
            }

But the special snowflake you are, you might want something different.

closestToZero : Basics.Float -> Basics.Float -> Basics.Float

A helper to position your axis as close to zero as possible, meaning if your range is 4 - 10, then the x-axis will be a 4, as that's the closest to zero it gets. Useful for avoiding confusion when your axis disappears below the reach of your plot because zero is not in your plot.

Position helpers

decentPositions : AxisSummary -> List Basics.Float

For decently spaced positions. Useful in tick/label and grid configurations.

interval : Basics.Float -> Basics.Float -> AxisSummary -> List Basics.Float

For ticks with a particular interval. The first value passed is the offset, and the second value is the actual interval. The offset is useful when you want two sets of ticks with different views. For example, if you want a long tick at every 2 * x and a small tick at every 2 * x + 1.

remove : Basics.Float -> List Basics.Float -> List Basics.Float

If you regret a particular position. Typically used for removing the label at the origin. Use like this:

normalAxis : Axis
normalAxis =
    axis <|
        \summary ->
            { position = ClosestToZero
            , axisLine = Just (simpleLine summary)
            , ticks = List.map simpleTick (decentPositions summary |> remove 0)
            , labels = List.map simpleLabel (decentPositions summary |> remove 0)
            }

See how in the normal axis we make a bunch of ticks, but then remove the one we don't want. You can do the same!

Small axis helpers

simpleLine : AxisSummary -> LineCustomizations

A nice grey line which goes from one side of your plot to the other.

simpleTick : Basics.Float -> TickCustomizations

A simple but powerful tick.

simpleLabel : Basics.Float -> LabelCustomizations

A simple label. You might want to try an make your own!

fullLine : List (Svg.Attribute Basics.Never) -> AxisSummary -> LineCustomizations

A line which goes from one end of the plot to the other.

viewLabel : List (Svg.Attribute msg) -> String -> Svg msg

displace : Basics.Float -> Basics.Float -> Svg.Attribute msg