Elm Line Charts Part II: Imports and Axes

This is the second in a series of blog posts dealing with LineChart in Elm. In the previous post, I outlined how to grab the timezone as a prerequisite for time-based linecharts. In this post, I will begin to write the chart module I'm trying to use in Chicago Test Out by defining my imports and creating a custom axis.

Imports and Aliases

LineChart requires a lot of imports. For my own convenience, I'm going to leave them here.

module HospitalizationPercentChart exposing (chart)

import Hospitalization exposing (Hospitalization)
import Html exposing (..)
import LineChart
import LineChart.Colors as Colors
import LineChart.Junk as Junk
import LineChart.Area as Area
import LineChart.Axis as Axis
import LineChart.Axis.Line as AxisLine
import LineChart.Axis.Range as Range
import LineChart.Axis.Ticks as Ticks
import LineChart.Axis.Title as Title
import LineChart.Junk as Junk
import LineChart.Dots as Dots
import LineChart.Grid as Grid
import LineChart.Dots as Dots
import LineChart.Line as Line
import LineChart.Colors as Colors
import LineChart.Events as Events
import LineChart.Legends as Legends
import LineChart.Container as Container
import LineChart.Interpolation as Interpolation
import LineChart.Axis.Intersection as Intersection
import Msg exposing (..)
import Time

The aliases are not only convenient, but are an established convention in the documentation, so they're a good idea if you'd like to copy and paste code.

Defining a View Model

Line charts are typed according to a model, and axes are configured according to specific fields within that model. It's a good design, but a consequence of that is that it often requires a generic data viewmodel specifically for the chart. (For example, let's say I have a list of records and each record represents a day. If I define the Y axis to be the number of ICU beds for that day, it cannot also be used to show the number of ventilators in use for that day.)

For this line chart, I'm definitely going to want multiple lines on the chart, and even if I didn't, it would probably be a good practice to leave that option open to extension, so let's create that model:

type alias ChartModel =
    { date: Float
    , val: Float
    }

While I expect the date to display as a date, the line charts library will ultimately handle that conversion--it expects a float. val is a generic name for a wrapper around any float value.

Defining an Axis

One of the reasons why I'm writing this series is that the examples in the documentation use a lot of the defaults for the library. These are great if you're trying to get a quick sense for how the library works without being overwhelmed by choices right off the bat. This series aims to be a little more in-depth and a little more oriented toward real-world usage, so I'm going to assume a certain amount of customization.

xAxisConfig : Time.Zone -> Axis.Config ChartModel msg
xAxisConfig zone =
    Axis.custom
        { title = Title.default "Time"
        , variable = Just << .date
        , pixels = 1000
        , range = Range.default
        , axisLine = AxisLine.rangeFrame Colors.black
        , ticks = Ticks.time zone 5
        }

This code is fairly self-explanatory, and I'm mainly including it as a copypasta for myself for the future. Basically, it's a function that takes a time zone and spits out an axis based on the .date property of our ChartModel. Also, note that I'm not using the default ticks because I have found that doesn't work well with time as an axis. (The letters overlap a great deal.)

If your imports are alright, you should once again have a program in a compiling state. Next, we'll work on defining lines.