DEV Community

loading...

Elm Line Charts Part III: Lines and the Chart

webbureaucrat
functional programming enthusiast and civic tech nerd.
Originally published at webbureaucrat.gitlab.io on ・2 min read

This is the last installment of a series describing how to configure an Elm LineChart. In the previous post I used a viewmodel to configure an axis, so this post will cover how to use lists of those viewmodels to plot the rest of the chart.

Converting to the ViewModel

I want this line chart to have three lines based on my ChartModel from the previous post, and I know I'm starting with a model that has a list of Hospitalizations, so I'll start with ways to convert between the two.

icuBeds: List Hospitalization -> List ChartModel
icuBeds days = 
  List.map (\d -> d.icuBedsTotal/d.icuBedsTotalCapacity 
                  |> \ratio -> ratio * 100 
                  |> ChartModel d.date
           ) days

nonIcuBeds: List Hospitalization -> List ChartModel
nonIcuBeds days = 
  List.map(\d ->
    d.acuteNonIcuBedsTotal/d.acuteNonIcuBedsTotalCapacity 
    |> \ratio -> ratio * 100 
    |> ChartModel d.date 
    ) days

ventilators : List Hospitalization -> List ChartModel
ventilators days = List.map (\d ->  
  d.ventilatorsTotal/d.ventilatorsTotalCapacity 
  |> \ratio -> ratio * 100 
  |> ChartModel d.date
  ) days

All I'm doing here is taking different fields from Hospitalization, converting to a percent, and piping out to a ChartModel. I've configured this for each of the three percentages I want on my chart.

Draw the Rest of the Owl

I'm happy with the rest of the defaults and they don't generally need a ton of explanation, so I'm just going to dump this pile of code unceremoniously here so that I can paste it someplace else when I need it.

chart : Time.Zone -> List Hospitalization -> Html Msg
chart zone days = LineChart.viewCustom 
{ x = xAxisConfig zone 
, y = Axis.default 400 "Volume" .val 
, area = Area.default 
, container = Container.default "hospitalization-raw-chart" 
, interpolation = Interpolation.default 
, intersection = Intersection.default 
, legends = Legends.default 
, events = Events.default 
, junk = Junk.default 
, grid = Grid.default 
, line = Line.default 
, dots = Dots.default 
} 
[ LineChart.line Colors.blue Dots.none "ICU Beds" (icuBeds days) 
, LineChart.line Colors.purple Dots.none "Acute Non-ICU Beds" (nonIcuBeds days) 
, LineChart.line Colors.red Dots.none "Ventilators" (ventilators days)
]

As you can see you plug in your time zone and some default values and a list of lines based on the functions defined above and give it a good stir.

In all seriousness, the important thing here is to use viewCustom rather than fiddle with making the numbered signatures work. (One thing I absolutely do not understand is the way that Elm deals with parametric polymorphism by putting numbers in the signatures. Elm, you are flawed and I love you anyway.)

Discussion (0)

Forem Open with the Forem app