webbureaucrat

from legacy to functional and very little in between.

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 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.

I write to learn, so I welcome your constructive criticism. Report issues on GitLab.

← Home