Alpha version!
Make sure to check out the many examples at elm-charts.org.
The configuration of this charting library mirrors the pattern of HTML elements and attributes. It looks something like this:
import Html exposing (Html)
import Chart as C
import Chart.Attributes as CA
view : Html msg
view =
C.chart
[ CA.width 300
, CA.height 300
]
[ C.xTicks []
, C.yTicks []
, C.xLabels []
, C.yLabels []
, C.bars []
[ C.bar .income [ CA.color "red" ]
, C.bar .spending [ CA.opacity 0.8 ]
]
data
]
All the elements, like chart
, xTicks
, yTicks
, xLabels
, yLabels
, bars
and bar
in the example
above, and many others, are defined in this module. All the attributes, like width
, height
, color
, and opacity
,
are defined in Chart.Attributes
. Attributes related to events are located in
the Chart.Events
module. Functions for working with rendered chart items are located in Chart.Item
.
Lastly, Chart.Svg
holds charting primitives in case you have very special needs.
In the examples throughout the documentation, I will assume the imports:
import Html as H exposing (Html)
import Html.Attributes as HA
import Html.Events as HE
import Svg as S
import Svg.Attributes as SA
import Svg.Events as SE
import Chart as C
import Chart.Attributes as CA
import Chart.Events as CE
import Chart.Item as CI
chart : List (Attributes.Attribute (Container data msg)) -> List (Element data msg) -> Html msg
This is the root container of your chart. All your chart elements must be placed in
here. The below example illustrates what configurations are available for
the chart
element.
view : Html msg
view =
C.chart
[ CA.width 300 -- Sets width dimension of chart
, CA.height 500 -- Sets height dimension of chart
-- Note that the chart scales with it's container
, CA.margin { top = 10, bottom = 20, left = 20, right = 20 }
-- Add space around your chart.
-- Useful if you have labels which extend
-- outside the main chart area.
, CA.padding { top = 10, bottom = 10, left = 10, right = 10 }
-- Expand your domain / range by a set
-- amount of SVG units.
-- Useful if you have e.g. scatter dots
-- which extend beyond your main chart area,
-- and you'd like them to be within.
-- Control the range and domain of your chart.
-- Your range and domain is by default set to the limits of
-- your data, but you can change them like this:
, CA.range
[ CA.lowest -5 CA.orLower
-- Makes sure that your x-axis begins at -5 or lower, no matter
-- what your data is like.
, CA.highest 10 CA.orHigher
-- Makes sure that your x-axis ends at 10 or higher, no matter
-- what your data is like.
]
, CA.domain
[ CA.lowest 0 CA.exactly ]
-- Makes sure that your y-axis begins at exactly 0, no matter
-- what your data is like.
-- Add event triggers to your chart. Learn more about these in
-- the `Chart.Events` module.
, CE.onMouseMove OnHovering (CE.getNearest CI.bars)
, CE.onMouseLeave (OnHovering [])
-- Add arbitrary HTML and SVG attributes to your chart.
, CA.htmlAttrs [ HA.style "background" "beige" ]
, CA.attrs [ SA.id "my-chart" ]
]
[ C.grid []
, C.xLabels []
, C.yLabels []
, ..
]
Explore live examples for the following attributes: - margin - padding - range - domain - onMouseMove - onMouseLeave - htmlAttrs
The representation of a chart element.
bars : List (Attributes.Attribute (Bars data)) -> List (Property data () Svg.Bar) -> List data -> Element data msg
Add a bar series to your chart. Here's some handy terminology:
Each data
in your List data
is a "bin". For
each "bin", whatever number of bars your have specified in the second argument will
show up, side-by-side.
C.bars []
[ C.bar .income []
, C.bar .spending []
]
[ { income = 10, spending = 2 }
, { income = 12, spending = 6 }
, { income = 18, spending = 16 }
]
The example above will thus produce three bins, each containing two bars. You can make
your bars show up overlapping instead of side-by-side by using the CA.ungroup
attribute:
C.bars
[ CA.ungroup ]
[ C.bar .total []
, C.bar .gross []
, C.bar .net []
]
[ { net = 10, gross = 20, total = 50 }
, { net = 13, gross = 28, total = 63 }
, { net = 16, gross = 21, total = 82 }
]
By default, the x value of each bin is set by a simple count. The first bin is set at
x = 1, the second at x = 2, and so on. If you'd like to control what the x values of
your bins are, e.g. you are making a histogram, you may use the CA.x1
and CA.x2
attributes, as illustrated below.
C.bars
[ CA.x1 .score
, CA.x2 (\datum -> datum.score + 20)
]
[ C.bar .students [] ]
[ { score = 0, students = 1 }
, { score = 20, students = 10 }
, { score = 40, students = 30 }
, { score = 60, students = 20 }
, { score = 80, students = 1 }
]
In this case, you actually only need to specify either x1
or x2
because the library
estimates the unknown x value based on the size of the previous or next bin. However, it comes in
handy to specify both when you have bins of irregular sizes.
The rest of the configuration options concern styling:
C.bars
[ CA.spacing 0.1 -- The spacing _between_ the bars in each bin relative to the full length (1).
, CA.margin 0.2 -- The spacing _around_ the bars in each bin relative to the full length (1).
, CA.roundTop 0.2 -- The rounding of your bars' top corners. It gets weird after around 0.5.
, CA.roundBottom 0.2 -- The rounding of your bars' bottom corners. It gets weird after around 0.5.
, CA.withGrid -- Add grid lines at the bin limits.
]
[ C.bar .income []
, C.bar .spending []
]
[ { income = 10, spending = 2 }
, { income = 12, spending = 6 }
, { income = 18, spending = 16 }
]
Explore live examples for the following attributes: - spacing - margin - roundTop - roundBottom
barsMap : (data -> a) -> List (Attributes.Attribute (Bars data)) -> List (Property data () Svg.Bar) -> List data -> Element a msg
This is just like bars
, but it maps your data
. This is useful if you have
several kinds of data types present in your chart.
type Datum
= Money { year : Float, income : Float }
| People { year : Float, people : Float }
view : Html msg
view =
C.chart []
[ C.barsMap Money
[ CA.x1 .year ]
[ C.bar .income [] ]
[ { year = 2000, income = 200 }
, { year = 2010, income = 300 }
, { year = 2020, income = 500 }
]
, C.barsMap People
[ CA.x1 .year ]
[ C.bar .people [] ]
[ { year = 2000, people = 21 }
, { year = 2010, people = 65 }
, { year = 2020, people = 93 }
]
]
bar : (data -> Basics.Float) -> List (Attributes.Attribute Svg.Bar) -> Property data inter Svg.Bar
Specify the configuration of a bar. The first argument will determine the height of your bar. The second is a list of styling attributes. The example below illustrates what styling options are available.
C.chart []
[ C.bars []
[ C.bar .income
[ CA.color "blue" -- Change the color
, CA.border "darkblue" -- Change the border color
, CA.borderWidth 2 -- Change the border width
, CA.opacity 0.7 -- Change the border opacity
-- A bar can either be solid (default), striped, dotted, or gradient.
, CA.striped
[ CA.width 2 -- Width of each stripe
, CA.spacing 3 -- Spacing bewteen each stripe
, CA.color "blue" -- Color of stripe
, CA.rotate 90 -- Angle of stripe
]
, CA.dotted []
-- Same configurations as `striped`
, CA.gradient
[ "blue", "darkblue" ] -- List of colors in gradient
, CA.roundTop 0.2 -- Round the top corners
, CA.roundBottom 0.2 -- Round the bottom corners
-- You can highlight a bar or a set of bars by adding a kind of "aura" to it.
, CA.highlight 0.5 -- Determine the opacity of the aura
, CA.highlightWidth 5 -- Determine the width of the aura
, CA.highlightColor "blue" -- Determine the color of the aura
-- Add arbitrary SVG attributes to your bar
, CA.attrs [ SA.strokeOpacity "0.5" ]
]
]
[ { income = 10 }
, { income = 12 }
, { income = 18 }
]
]
Explore live examples for the following attributes: - color - borderWidth - opacity - striped - dotted - gradient - roundTop - roundBottom - highlight
barMaybe : (data -> Maybe Basics.Float) -> List (Attributes.Attribute Svg.Bar) -> Property data inter Svg.Bar
Same as bar
, but allows for missing data.
C.chart []
[ C.bars []
[ C.barMaybe .income [] ]
[ { income = Just 10 }
, { income = Nothing }
, { income = Just 18 }
]
]
series : (data -> Basics.Float) -> List (Property data Svg.Interpolation Svg.Dot) -> List data -> Element data msg
Add a scatter or line series to your chart. Each data
in your List data
will result in one "dot".
The first argument of series
determines the x value of each dot. The y value and all styling configuration
is determined by the list of interpolated
or scatter
properties defined in the second argument.
C.series .age
[ C.interpolated .height [] []
, C.interpolated .weight [] []
]
[ { age = 0, height = 40, weight = 4 }
, { age = 5, height = 80, weight = 24 }
, { age = 10, height = 120, weight = 36 }
, { age = 15, height = 180, weight = 54 }
, { age = 20, height = 184, weight = 60 }
]
See interpolated
and scatter
for styling options.
seriesMap : (data -> a) -> (data -> Basics.Float) -> List (Property data Svg.Interpolation Svg.Dot) -> List data -> Element a msg
This is just like series
, but it maps your data
. This is useful if you have
several kinds of data types present in your chart.
type Datum
= Height { age : Float, height : Float }
| Weight { age : Float, weight : Float }
view : Html msg
view =
C.chart []
[ C.seriesMap Height .age
[ C.interpolated .height [] ]
[ { age = 0, height = 40 }
, { age = 5, height = 80 }
, { age = 10, height = 120 }
, { age = 15, height = 180 }
]
, C.seriesMap Weight .age
[ C.interpolated .weight [] ]
[ { age = 0, weight = 4 }
, { age = 5, weight = 24 }
, { age = 10, weight = 36 }
, { age = 15, weight = 54 }
]
]
scatter : (data -> Basics.Float) -> List (Attributes.Attribute Svg.Dot) -> Property data inter Svg.Dot
Specify the configuration of a set of dots. The first argument will determine the y value of your dots. The second is a list of styling attributes. The example below illustrates what styling options are available.
C.series .year
[ C.scatter .income
[ CA.size 10 -- Change size of dot
, CA.color "blue" -- Change color
, CA.opacity 0.8 -- Change opacity
, CA.border "lightblue" -- Change border color
, CA.borderWidth 2 -- Change border width
-- You can highlight a dot or a set of dots by adding a kind of "aura" to it.
, CA.highlight 0.3 -- Determine the opacity of the aura
, CA.highlightWidth 6 -- Determine the width of the aura
, CA.highlightColor "blue" -- Determine the color of the aura
-- A dot is by default a circle, but you can change it to any
-- of the shapes below.
, CA.triangle
, CA.square
, CA.diamond
, CA.plus
, CA.cross
]
]
[ { year = 2000, income = 40000 }
, { year = 2010, income = 57000 }
, { year = 2020, income = 62000 }
]
Explore live examples for the following attributes: - size - opacity - border - borderWidth - highlight - triangle - square - cross
scatterMaybe : (data -> Maybe Basics.Float) -> List (Attributes.Attribute Svg.Dot) -> Property data inter Svg.Dot
Same as scatter
, but allows for missing data.
C.chart []
[ C.series .year
[ C.scatterMaybe .income [] ]
[ { year = 2000, income = Just 40000 }
, { year = 2010, income = Nothing }
, { year = 2020, income = Just 62000 }
]
]
interpolated : (data -> Basics.Float) -> List (Attributes.Attribute Svg.Interpolation) -> List (Attributes.Attribute Svg.Dot) -> Property data Svg.Interpolation Svg.Dot
Specify the configuration of a interpolated series (a line). The first argument will determine the y value of your dots. The second is a list of attributes pertaining to your interpolation. The third argument is a list of attributes pertaining to the dots of your series.
The example below illustrates what styling options are available.
C.series .age
[ C.interpolated .height
[ -- The following attributes allow alternatives to the default
-- linear interpolation.
CA.monotone -- Use a monotone interpolation (looks smooth)
, CA.stepped -- Use a stepped interpolation (looks like stairs)
, CA.color "blue"
, CA.width 2
, CA.dashed [ 4, 4 ]
-- The area beneath the curve is by default transparent, but you
-- can change the opacity of it, or make it striped, dotted, or gradient.
, CA.opacity 0.5
, CA.striped
[ CA.width 2 -- Width of each stripe
, CA.spacing 3 -- Spacing bewteen each stripe
, CA.color "blue" -- Color of stripe
, CA.rotate 90 -- Angle of stripe
]
, CA.dotted [] -- Same configurations as `striped`
, CA.gradient [ "blue", "darkblue" ] -- List of colors in gradient
-- Add arbitrary SVG attributes to your line
, CA.attrs [ SA.id "my-chart" ]
]
[]
]
[ { age = 0, height = 40 }
, { age = 5, height = 80 }
, { age = 10, height = 120 }
, { age = 15, height = 180 }
, { age = 20, height = 184 }
]
Explore live examples for the following attributes: - monotone - stepped - color - width - opacity - striped - dotted - gradient
interpolatedMaybe : (data -> Maybe Basics.Float) -> List (Attributes.Attribute Svg.Interpolation) -> List (Attributes.Attribute Svg.Dot) -> Property data Svg.Interpolation Svg.Dot
Same as interpolated
, but allows for missing data.
C.chart []
[ C.series .age
[ C.interpolatedMaybe .height [] ]
[ { age = 0, height = Just 40 }
, { age = 5, height = Nothing }
, { age = 10, height = Just 120 }
, { age = 15, height = Just 180 }
, { age = 20, height = Just 184 }
]
]
See live example of missing data in line chart.
Internal.Property.Property data String inter deco
A property of a bar, line, or scatter series.
stacked : List (Property data inter deco) -> Property data inter deco
Stack a set of bar or line series.
C.chart []
[ C.bars []
[ C.stacked
[ C.bar .cats []
, C.bar .dogs []
]
]
[ { cats = 2, dogs = 4 }
, { cats = 3, dogs = 2 }
, { cats = 6, dogs = 1 }
]
]
See live example.
variation : (Basics.Int -> data -> List (Attributes.Attribute deco)) -> Property data inter deco -> Property data inter deco
Change the style of your bars or dots based on the index of its data point and the data point itself.
C.chart []
[ C.series .year
[ C.scatter .income [ CA.opacity 0.6 ]
|> C.variation (\index datum -> [ CA.size datum.people ])
]
[ { year = 2000, income = 40000, people = 150 }
, { year = 2010, income = 48000, people = 98 }
, { year = 2020, income = 62000, people = 180 }
]
]
See live example.
amongst : List (Item.One data x) -> (data -> List (Attributes.Attribute deco)) -> Property data inter deco -> Property data inter deco
Change the style of your bars or dots based on whether it is a member
of the group of products which you list. A such group of products can be
attrained through events like Chart.Events.onMouseMove
or similar.
C.chart
[ CE.onMouseMove OnHover (CE.getNearest CI.dots) ]
[ C.series .year
[ C.scatter .income [ CA.opacity 0.6 ]
|> C.amongst model.hovering (\datum -> [ CA.highlight 0.5 ])
]
[ { year = 2000, income = 40000, people = 150 }
, { year = 2010, income = 48000, people = 98 }
, { year = 2020, income = 62000, people = 180 }
]
]
See live example.
named : String -> Property data inter deco -> Property data inter deco
Name a bar, scatter, or interpolated series. This name will show up in the default tooltip, and you can use it to identify items from this series.
C.chart []
[ C.series .year
[ C.scatter .income []
|> C.named "Income"
]
[ { year = 2000, income = 40000 }
, { year = 2010, income = 48000 }
, { year = 2020, income = 62000 }
]
]
See live example.
format : (Basics.Float -> String) -> Property data inter deco -> Property data inter deco
Easily format the value which shows up by default in your tooltip if you add one. You
can also access it using Chart.Item.getTooltipValue
.
See live example.
formatMaybe : (Maybe Basics.Float -> String) -> Property data inter deco -> Property data inter deco
Like format
, except it allows you customize the formatting of missing values too!
xAxis : List (Attributes.Attribute Axis) -> Element item msg
Add an x-axis line to your chart. The example below illustrates the styling options:
C.chart []
[ C.xAxis
[ CA.color "red" -- Change color of line
, CA.width 2 -- Change width of line
, CA.noArrow -- Remove arrow from line
, CA.pinned .max -- Change what y position the axis is set at
-- .max is at the very top
-- .min is at the very bottom
-- CA.zero is the closest you can go to zero
-- (always 3) is at y = 3.
, CA.limits
[ CA.lowest 2 CA.exactly
, CA.highest 8 CA.exactly
]
-- Change from where to where you line goes.
-- The example will make a line where x1 = 2 to x2 = 8
]
]
Explore live examples for the following attributes: - color - noArrow - pinned - limits
yAxis : List (Attributes.Attribute Axis) -> Element item msg
Add an y-axis line to your chart. The styling options are the same
as for xAxis
.
xTicks : List (Attributes.Attribute Ticks) -> Element item msg
Produce a set of ticks at "nice" numbers on the x-axis of your chart. The example below illustrates the configuration:
C.chart []
[ C.xTicks
[ CA.color "red" -- Change color
, CA.height 8 -- Change height
, CA.width 2 -- Change width
, CA.amount 15 -- Change amount of ticks
, CA.flip -- Flip to opposite direction
, CA.noGrid -- By default a grid line is added
-- for each tick. This removes them.
, CA.ints -- Add ticks at "nice" ints
, CA.times Time.utc -- Add ticks at "nice" times
, CA.pinned .max -- Change what y position the ticks are set at
-- .max is at the very top
-- .min is at the very bottom
-- CA.zero is the closest you can go to zero
-- (always 3) is at y = 3.
, CA.limits
[ CA.lowest 2 CA.exactly
, CA.highest 8 CA.exactly
]
-- Change the upper and lower limit of your tick range.
-- The example will add ticks between x = 2 and 8.
]
]
Explore live examples for the following attributes: - pinned - ints - times - noGrid - amount
yTicks : List (Attributes.Attribute Ticks) -> Element item msg
Produce a set of ticks at "nice" numbers on the y-axis of your chart.
The styling options are the same as for xTicks
.
xLabels : List (Attributes.Attribute Labels) -> Element item msg
Produce a set of labels at "nice" numbers on the x-axis of your chart. The example below illustrates the configuration:
C.chart []
[ C.xLabels
[ CA.color "red" -- Change color
, CA.fontSize 12 -- Change font size
, CA.uppercase -- Make labels uppercase
, CA.rotate 90 -- Rotate labels
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.amount 15 -- Change amount of ticks
, CA.flip -- Flip to opposite direction
, CA.withGrid -- Add grid line by each label.
, CA.ints -- Add ticks at "nice" ints
, CA.times Time.utc -- Add ticks at "nice" times
, CA.format (\num -> String.fromFloat num ++ "°")
-- Format the "nice" number
, CA.ellipsis 40 10
-- Add ellipsis. Arguments are width and height of label.
-- Note: There is no SVG feature for ellipsis, so this
-- turns labels into HTML.
, CA.hideOverflow -- Cut off labels if exeeding chart bounds
, CA.pinned .max -- Change what y position the labels are set at
-- .max is at the very top
-- .min is at the very bottom
-- CA.zero is the closest you can go to zero
-- (always 3) is at y = 3.
, CA.limits
[ CA.lowest 2 CA.exactly
, CA.highest 8 CA.exactly
]
-- Change the upper and lower limit of your labels range.
-- The example will add labels between x = 2 and 8.
]
]
Explore live examples for the following attributes: - alignLeft - moveUp - amount - ints - times
For more in depth and irregular customization, see xLabel
or check out
the custom labels example.
yLabels : List (Attributes.Attribute Labels) -> Element item msg
Produce a set of labels at "nice" numbers on the y-axis of your chart.
The styling options are the same as for xLabels
.
grid : List (Attributes.Attribute Grid) -> Element item msg
Add a custom grid to your chart.
C.chart []
[ C.grid [ CA.width 2 ]
, C.xTicks []
, C.yTicks []
]
Grid lines are added by default where ticks are added. You can add
grid lines to where your labels are using the CA.withGrid
attribute:
C.yLabels [ CA.withGrid ]
Customizations:
C.grid
[ CA.color "blue" -- Change color
, CA.width 3 -- Change width
, CA.dashed [ 5, 5 ] -- Add dashing (only for line grids)
, CA.dotGrid -- Use dot grid instead of line grid
]
xLabel : List (Attributes.Attribute Label) -> List (Svg msg) -> Element data msg
Produce a single x label. This is typically for cases where you need
very custom labels and xLabels
does not cut it. It is especially useful
in combination with the generate
helper. An example use case:
C.chart []
[ -- Create labels for 10 "nice" integers on the x-axis
-- and highlight the label at x = 0.
C.generate 10 C.ints .x [] <| \plane int ->
let color = if int == 0 then "red" else "gray" in
[ C.xLabel
[ CA.x (toFloat int), CA.color color ]
[ S.text (String.fromInt int) ]
]
]
A full list of possible attributes:
C.chart []
[ C.xLabel
[ CA.x 5 -- Set x coordinate
, CA.y 8 -- Set y coordinate
, CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.border "white" -- Set stroke color
, CA.borderWidth 0.5 -- Set stroke width
, CA.fontSize 12 -- Set font size
, CA.color "red" -- Set color
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
, CA.flip -- Flip to opposite direction
, CA.hideOverflow -- Cut off labels if exeeding chart bounds
, CA.ellipsis 40 10
-- Add ellipsis. Arguments are width and height of label.
-- Note: There is no SVG feature for ellipsis, so this
-- turns labels into HTML.
, CA.withGrid -- Add grid line by each label.
]
[ S.text "hello!" ]
]
See also the custom labels example.
yLabel : List (Attributes.Attribute Label) -> List (Svg msg) -> Element data msg
Produce a single y label. This is typically for cases where you need
very custom labels and yLabels
does not cut it. See xLabel
for
usage and customization.
xTick : List (Attributes.Attribute Tick) -> Element data msg
Produce a single x tick. This is typically for cases where you need
very custom ticks and xTicks
does not cut it. It is especially useful
in combination with the generate
helper. An example use case:
C.chart []
[ -- Create ticks for 10 "nice" integers on the x-axis
-- and highlight the tick at x = 0.
C.generate 10 C.ints .x [] <| \plane int ->
let color = if int == 0 then "red" else "gray" in
[ C.xTick [ CA.x (toFloat int), CA.color color ] ]
]
A full list of possible attributes:
C.xTick
[ CA.x 5 -- Set x coordinate
, CA.y 8 -- Set y coordinate
, CA.color "red" -- Change color
, CA.height 8 -- Change height
, CA.width 2 -- Change width
, CA.amount 15 -- Change amount of ticks
, CA.flip -- Flip to opposite direction
, CA.noGrid -- By default a grid line is added
-- for each tick. This removes them.
]
yTick : List (Attributes.Attribute Tick) -> Element data msg
Produce a single y tick. This is typically for cases where you need
very custom ticks and yTicks
does not cut it. See xTick
for
usage and customization.
generate : Basics.Int -> Svg.Generator a -> (Internal.Coordinates.Plane -> Internal.Coordinates.Axis) -> List (Attributes.Attribute Internal.Coordinates.Axis) -> (Internal.Coordinates.Plane -> a -> List (Element data msg)) -> Element data msg
Generate "nice" numbers. Useful in combination with xLabel
, yLabel
, xTick
, and yTick
.
C.chart []
[ C.generate 10 C.ints .x [ CA.lowest -5 CA.exactly, CA.highest 15 CA.exactly ] <| \plane int ->
[ C.xTick [ CA.x (toFloat int) ]
, C.xLabel [ CA.x (toFloat int) ] [ S.text (String.fromInt int) ]
]
]
The example above generates 10 ints on the x axis between x = -5 and x = 15. For each of those ints, it adds a tick and a label.
See live example.
floats : Svg.Generator Basics.Float
Generate "nice" floats.
ints : Svg.Generator Basics.Int
Generate "nice" ints.
times : Time.Zone -> Svg.Generator Intervals.Time
Generate "nice" times.
See the docs in terezka/intervals
for more info about the properties of Time
!
binLabels : (data -> String) -> List (Attributes.Attribute (ItemLabel (Item.Many data Item.Bar))) -> Element data msg
Add labels by every bin.
C.chart []
[ C.bars [] [ C.bar .income [] ]
[ { name = "Anna", income = 60 }
, { name = "Karenina", income = 70 }
, { name = "Jane", income = 80 }
]
, C.binLabels .name [ CA.moveDown 15 ]
]
Attributes you can use:
C.binLabels .name
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-bin-labels" ]
-- Edit the position of the label
, CA.position CI.getTop
-- Given the entire bin item (not just the data)
-- produce a string.
, CA.format (\bin -> String.fromFloat (CI.getShared bin).start)
]
See live example.
barLabels : List (Attributes.Attribute (ItemLabel (Item.One data Item.Bar))) -> Element data msg
Add labels by every bar.
C.chart []
[ C.bars []
[ C.bar .income [] ]
[ { name = "Anna", income = 60 }
, { name = "Karenina", income = 70 }
, { name = "Jane", income = 80 }
]
, C.barLabels [ CA.moveUp 6 ]
]
Attributes you can use:
C.barLabels
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-bar-labels" ]
-- Edit the position of the label
, CA.position CI.getTop
-- Change the text of the label
, CA.format (\bar -> String.fromFloat (CI.getY bar))
]
See live example.
dotLabels : List (Attributes.Attribute (ItemLabel (Item.One data Item.Dot))) -> Element data msg
Add labels by every bar.
C.chart []
[ C.series .age
[ C.scatter .income [] ]
[ { age = 34, income = 60 }
, { age = 42, income = 70 }
, { age = 48, income = 80 }
]
, C.dotLabels CI.getCenter [ CA.moveUp 6 ]
]
Attributes you can use:
C.dotLabels
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-dot-labels" ]
-- Edit the position of the label
, CA.position CI.getTop
-- Change the text of the label
, CA.format (\dot -> String.fromFloat (CI.getY dot))
]
See live example.
productLabel : List (Attributes.Attribute (ItemLabel (Item.One data x))) -> Item.One data x -> Element data msg
Helper to add a label by a particular product.
C.chart
[ CE.onMouseMove OnHover (CE.getNearest CI.bars) ]
[ C.bars []
[ C.bar .income [] ]
[ { name = "Anna", income = 60 }
, { name = "Karenina", income = 70 }
, { name = "Jane", income = 80 }
]
, C.each model.hovering <| \_ bar ->
[ C.productLabel [ CA.moveUp 6 ] bar ]
]
Attributes you can use:
C.productLabel
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-bar-labels" ]
-- Edit the position of the label
, CA.position CI.getTop
-- Change the text of the label
, CA.format (\bar -> String.fromFloat (CI.getY bar))
]
product
label : List (Attributes.Attribute Svg.Label) -> List (Svg msg) -> Internal.Coordinates.Point -> Element data msg
Add a label, such as a chart title or other note, at a specific coordinate.
C.chart []
[ C.label [] [ S.text "Data from Fruits.com" ] { x = 5, y = 10 } ]
The example above adds your label at coordinates x = y and y = 10.
Other attributes you can use:
C.labelAt
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
, CA.ellipsis 40 10
-- Add ellipsis. Arguments are width and height of label.
-- Note: There is no SVG feature for ellipsis, so this
-- turns labels into HTML.
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-label" ]
]
[ S.text "Data from Fruits.com" ]
{ x = 5, y = 10 }
labelAt : (Internal.Coordinates.Axis -> Basics.Float) -> (Internal.Coordinates.Axis -> Basics.Float) -> List (Attributes.Attribute Svg.Label) -> List (Svg msg) -> Element data msg
Add a label, such as a chart title or other note, at a position relative to your axes.
C.chart []
[ C.labelAt (CA.percent 20) (CA.percent 90) [] [ S.text "Data from Fruits.com" ] ]
The example above adds your label at 20% the length of your range and 90% of your domain.
Other attributes you can use:
C.labelAt (CA.percent 20) (CA.percent 90)
[ CA.moveUp 5 -- Move 5 SVG units up
, CA.moveDown 5 -- Move 5 SVG units down
, CA.moveLeft 5 -- Move 5 SVG units left
, CA.moveRight 5 -- Move 5 SVG units right
, CA.color "#333"
, CA.border "white"
, CA.borderWidth 1
, CA.fontSize 12
, CA.alignRight -- Anchor labels to the right
, CA.alignLeft -- Anchor labels to the left
, CA.rotate 90 -- Rotate label 90 degrees
, CA.uppercase -- Make uppercase
-- Add arbitrary SVG attributes to your labels.
, CA.attrs [ SA.class "my-label" ]
]
[ S.text "Data from Fruits.com" ]
See live example.
legendsAt : (Internal.Coordinates.Axis -> Basics.Float) -> (Internal.Coordinates.Axis -> Basics.Float) -> List (Attributes.Attribute (Svg.Legends msg)) -> List (Attributes.Attribute (Svg.Legend msg)) -> Element data msg
Add legends to your chart.
C.chart []
[ C.series .x
[ C.line .y [] []
|> C.named "cats"
, C.line .y [] []
|> C.named "dogs"
]
, C.legendsAt .min .max
[ CA.column -- Appear as column instead of row
, CA.alignRight -- Anchor legends to the right
, CA.alignLeft -- Anchor legends to the left
, CA.moveUp 5 -- Move 5px up
, CA.moveDown 5 -- Move 5px down
, CA.moveLeft 5 -- Move 5px left
, CA.moveRight 5 -- Move 5px right
, CA.spacing 20 -- Spacing between legends
, CA.background "beige" -- Color background
, CA.border "gray" -- Add border
, CA.borderWidth 1 -- Set border width
-- Add arbitrary HTML attributes. Convinient for extra styling.
, CA.htmlAttrs [ HA.class "my-legend" ]
]
[ CA.width 30 -- Change width of legend window
, CA.height 30 -- Change height of legend window
, CA.fontSize 12 -- Change font size
, CA.color "red" -- Change font color
, CA.spacing 12 -- Change spacing between window and title
, CA.htmlAttrs [ HA.class "my-legends" ] -- Add arbitrary HTML attributes.
]
]
See live example: - Basic bar legends. - Basic dot legends. - Basic line legends. - Mutiple chart types.
tooltip : Item a -> List (Attributes.Attribute Tooltip) -> List (Html.Attribute Basics.Never) -> List (Html Basics.Never) -> Element data msg
Add a tooltip for a specific item.
C.chart
[ CE.onMouseMove OnHover (CE.getNearest CI.any) ]
[ C.series .year
[ C.scatter .income [] ]
[ { year = 2000, income = 40000 }
, { year = 2010, income = 56000 }
, { year = 2020, income = 62000 }
]
, C.each model.hovering <| \plane product ->
[ C.tooltip product [] [] [] ]
]
Customizations:
C.tooltip item
[ -- Change direction
CA.onTop -- Always place tooltip on top of the item
, CA.onBottom -- Always place tooltip below of the item
, CA.onRight -- Always place tooltip on the right of the item
, CA.onLeft -- Always place tooltip on the left of the item
, CA.onLeftOrRight -- Place tooltip on the left or right of the item,
-- depending on which side has more space available
, CA.onTopOrBottom -- Place tooltip on the top or bottom of the item,
-- depending on which side has more space available
-- Change focal point (where on the item the tooltip is achored)
, CA.top
, CA.bottom
, CA.left
, CA.right
, CA.center
, CA.topLeft
, CA.topRight
, CA.topCenter
, CA.bottomLeft
, CA.bottomRight
, CA.bottomCenter
, CA.leftCenter
, CA.rightCenter
, CA.offset 20 -- Change offset between focal point and tooltip
, CA.noArrow -- Remove little box arrow
, CA.border "blue" -- Change border color
, CA.background -- Change background color
]
[] -- Add any HTML attributes
[] -- Add any HTML children (Will be filled with default tooltip if left empty)
Explore live examples for the following attributes: - onTopOrBottom - top - offset - noArrow - border - background
See also example of custom formatting and example of custom content and the other examples pertaining to interactivity.
line : List (Attributes.Attribute Svg.Line) -> Element data msg
Add a line.
C.chart []
[ C.line
[ CA.x1 2 -- Set x1
, CA.x2 8 -- Set x2
, CA.y1 3 -- Set y1
, CA.y2 7 -- Set y2
-- Instead of specifying x2 and y2
-- you can use `x2Svg` and `y2Svg`
-- to specify the end coordinate in
-- terms of SVG units.
--
-- Useful if making little label pointers.
-- This makes a from ( x1, y1 ) to the point
-- ( x1 + 15 SVG units, y1 + 30 SVG units )
, CA.x2Svg 15
, CA.y2Svg 30
, CA.break -- "break" line, so it it has a 90° angle
, CA.flip -- flip break to opposite direction
, CA.tickLength -- Add "ticks" at the ends of the line
, CA.tickDirection -- The angle of the ticks
, CA.color "red" -- Change color
, CA.width 2 -- Change width
, CA.opacity 0.8 -- Change opacity
, CA.dashed [ 5, 5 ] -- Add dashing
-- Add arbitrary SVG attributes.
, CA.attrs [ SA.id "my-line" ]
]
]
See live example.
rect : List (Attributes.Attribute Svg.Rect) -> Element data msg
Add a rectangle.
C.chart []
[ C.rect
[ CA.x1 2 -- Set x1
, CA.x2 8 -- Set x2
, CA.y1 3 -- Set y1
, CA.y2 7 -- Set y2
, CA.color "#aaa" -- Change fill color
, CA.opacity 0.8 -- Change fill opacity
, CA.border "#333" -- Change border color
, CA.borderWidth 2 -- Change border width
-- Add arbitrary SVG attributes.
, CA.attrs [ SA.id "my-rect" ]
]
]
See live example.
list : List (Element data msg) -> Element data msg
Add a list of elements.
svgAt : (Internal.Coordinates.Axis -> Basics.Float) -> (Internal.Coordinates.Axis -> Basics.Float) -> Basics.Float -> Basics.Float -> List (Svg msg) -> Element data msg
Add arbitrary SVG at a specific location. See Chart.Svg
for handy SVG helpers.
C.chart []
[ C.svgAt .min .max 10 20 [ .. ]
-- Add .. at x = the minumum value of your range (x-axis) + 12 SVG units
-- and y = the maximum value of your domain (y-axis) + 20 SVG units
]
htmlAt : (Internal.Coordinates.Axis -> Basics.Float) -> (Internal.Coordinates.Axis -> Basics.Float) -> Basics.Float -> Basics.Float -> List (Html.Attribute msg) -> List (Html msg) -> Element data msg
Add arbitrary HTML at a specific location.
See live example.
svg : (Internal.Coordinates.Plane -> Svg msg) -> Element data msg
Add arbitrary SVG. See Chart.Svg
for handy SVG helpers.
See live example.
html : (Internal.Coordinates.Plane -> Html msg) -> Element data msg
Add arbitrary HTML.
none : Element data msg
No element.
eachBin : (Internal.Coordinates.Plane -> Item.Many data Item.Any -> List (Element data msg)) -> Element data msg
Add elements for each bin.
C.chart []
[ C.bars []
[ C.bar .income []
, C.bar .spending []
]
[ { country = "Denmark", income = 40000, spending = 10000 }
, { country = "Sweden", income = 56000, spending = 12000 }
, { country = "Norway", income = 62000, spending = 18000 }
]
, C.eachBin <| \plane bin ->
let common = CI.getShared bin in
[ C.label [] [ S.text common.datum.country ] (CI.getBottom plane bin) ]
]
Use the functions in Chart.Item
to access information about your bins.
eachStack : (Internal.Coordinates.Plane -> Item.Many data Item.Any -> List (Element data msg)) -> Element data msg
Add elements for each stack.
C.chart []
[ C.bars []
[ C.stacked
[ C.bar .income []
, C.bar .savings []
]
]
[ { income = 40000, savings = 10000 }
, { income = 56000, savings = 12000 }
, { income = 62000, savings = 18000 }
]
, C.eachStack <| \plane stack ->
let total = List.sum (List.map CI.getY (CI.getMembers stack)) in
[ C.label [] [ S.text (String.fromFloat total) ] (CI.getTop plane stack) ]
]
Use the functions in Chart.Item
to access information about your stacks.
eachBar : (Internal.Coordinates.Plane -> Item.One data Item.Bar -> List (Element data msg)) -> Element data msg
Add elements for each bar.
C.chart []
[ C.bars []
[ C.bar .income []
, C.bar .spending []
]
[ { income = 40000, spending = 10000 }
, { income = 56000, spending = 12000 }
, { income = 62000, spending = 18000 }
]
, C.eachBar <| \plane bar ->
let yValue = CI.getY bar in
[ C.label [] [ S.text (String.fromFloat yValue) ] (CI.getTop plane bar) ]
]
Use the functions in Chart.Item
to access information about your bars.
eachDot : (Internal.Coordinates.Plane -> Item.One data Item.Dot -> List (Element data msg)) -> Element data msg
Add elements for each dot.
C.chart []
[ C.series []
[ C.scatter .income []
, C.scatter .spending []
]
[ { income = 40000, spending = 10000 }
, { income = 56000, spending = 12000 }
, { income = 62000, spending = 18000 }
]
, C.eachBar <| \plane bar ->
let yValue = CI.getY bar in
[ C.label [] [ S.text (String.fromFloat yValue) ] (CI.getTop plane bar) ]
]
Use the functions in Chart.Item
to access information about your dots.
eachItem : (Internal.Coordinates.Plane -> Item.One data Item.Any -> List (Element data msg)) -> Element data msg
Add elements for each dot or bar. Works like eachBar
and eachDot
, but includes both
bars and dots.
Use the functions in Chart.Item
to access information about your items.
each : List a -> (Internal.Coordinates.Plane -> a -> List (Element data msg)) -> Element data msg
Add elements for each item of whatever list in the first argument.
C.chart
[ CE.onMouseMove OnHover (CE.getNearest CI.any) ]
[ C.series .year
[ C.scatter .income [] ]
[ { year = 2000, income = 40000 }
, { year = 2010, income = 56000 }
, { year = 2020, income = 62000 }
]
, C.each model.hovering <| \plane product ->
[ C.tooltip product [] [] [] ]
]
See live example.
eachCustom : Item.Remodel (Item.One data Item.Any) a -> (Internal.Coordinates.Plane -> a -> List (Element data msg)) -> Element data msg
Filter and group products in any way you'd like and add elements for each of them.
C.chart []
[ C.eachCustom (CI.named "cats") <| \plane product ->
[ C.label [] [ S.text "hello" ] (CI.getTop plane product) ]
]
The above example adds a label for each product of the series named "cats".
Use the functions in Chart.Item
to access information about your items.
withBins : (Internal.Coordinates.Plane -> List (Item.Many data Item.Any) -> List (Element data msg)) -> Element data msg
Given all your bins, add a list of elements.
Use helpers in Chart.Item
to interact with bins.
withStacks : (Internal.Coordinates.Plane -> List (Item.Many data Item.Any) -> List (Element data msg)) -> Element data msg
Given all your stacks, add a list of elements.
Use helpers in Chart.Item
to interact with stacks.
withBars : (Internal.Coordinates.Plane -> List (Item.One data Item.Bar) -> List (Element data msg)) -> Element data msg
Given all your bars, add a list of elements.
Use helpers in Chart.Item
to interact with bars.
withDots : (Internal.Coordinates.Plane -> List (Item.One data Item.Dot) -> List (Element data msg)) -> Element data msg
Given all your dots, add a list of elements.
Use helpers in Chart.Item
to interact with dots.
withItems : (Internal.Coordinates.Plane -> List (Item.One data Item.Any) -> List (Element data msg)) -> Element data msg
Given all your products, add a list of elements.
Use helpers in Chart.Item
to interact with products.
withPlane : (Internal.Coordinates.Plane -> List (Element data msg)) -> Element data msg
Using the information about your coordinate system, add a list of elements.
custom : { name : String, color : String, position : Svg.Position, format : data -> String, data : data, render : Svg.Plane -> Svg Basics.Never } -> Element data msg
Add a custom element.
See live example.
binned : Basics.Float -> (data -> Basics.Float) -> List data -> List { bin : Basics.Float, data : List data }
Gather data points into bins. Arguments:
The list of data.
C.binned 10 .score [ Result "Anna" 43 , Result "Maya" 65 , Result "Joan" 69 , Result "Tina" 98 ] == [ { bin = 40, data = [ Result "Anna" 43 ] } , { bin = 60, data = [ Result "Maya" 65, Result "Joan" 69 ] } , { bin = 90, data = [ Result "Tina" 98 ] } ]
type alias Result = { name : String, score : Float }