36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/src/HelloWorld.elm:
--------------------------------------------------------------------------------
1 | port module HelloWorld exposing (elmToJS)
2 |
3 | import Platform
4 | import Vega exposing (..)
5 |
6 |
7 | helloWorld : Spec
8 | helloWorld =
9 | let
10 | ds =
11 | dataSource
12 | [ dataFromRows "myData"
13 | []
14 | (dataRow [ ( "label", vStr "Hello from Vega" ) ] [])
15 | ]
16 |
17 | mk =
18 | marks
19 | << mark text
20 | [ mFrom [ srData (str "myData") ]
21 | , mEncode [ enEnter [ maText [ vField (field "label") ] ] ]
22 | ]
23 | in
24 | toVega [ ds, mk [] ]
25 |
26 |
27 |
28 | {- This list comprises the specifications to be provided to the Vega runtime.
29 | In this example, only a single spec 'helloWord' is provided.
30 | -}
31 |
32 |
33 | mySpecs : Spec
34 | mySpecs =
35 | combineSpecs [ ( "helloWorld", helloWorld ) ]
36 |
37 |
38 |
39 | {- ---------------------------------------------------------------------------
40 | The code below is boilerplate for creating a headless Elm module that opens
41 | an outgoing port to JavaScript and sends the Vega specs (mySpecs) to it.
42 | There should be no need to change this.
43 | -}
44 |
45 |
46 | main : Program () Spec msg
47 | main =
48 | Platform.worker
49 | { init = always ( mySpecs, elmToJS mySpecs )
50 | , update = \_ model -> ( model, Cmd.none )
51 | , subscriptions = always Sub.none
52 | }
53 |
54 |
55 | port elmToJS : Spec -> Cmd msg
56 |
--------------------------------------------------------------------------------
/examples/tests/colorTests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vega Colour Tests
5 |
6 |
7 |
11 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Vega Colour Tests
36 |
37 |
38 |
39 |
Source
40 |
41 |
42 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017-present, giCentre, City University London
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/examples/tests/eventTests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vega Event Tests
5 |
6 |
7 |
11 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
32 | Apache arrow
37 | is a cross-platform binary format for in-memory data storage. Being much
38 | more compact than JSON it is suitable for larger datasets as well as for
39 | interoperability with other software that generates apache-arrow format
40 | files:
41 |
42 |
43 |
44 | To use Apache Arrow data with Vega (or Vega-Lite) you need to link to the
45 | vega-loader-arrow
48 | and apache-arrow javascript packages in the head of your HTML along with
49 | the normal links to the vega and vega-lite runtimes:
50 |
Standard Legend Layout (3 legends, cusomtised central legend):
41 |
42 |
43 |
44 | Legend Layout (3 legends with thick dashed borders, styled only through
45 | config options) with left and down offset large italic title:
46 |
47 |
48 |
49 |
50 | Horizontal Legend Layout below chart (3 legends, no borders, styled only
51 | through config options). Should not have a large margin:
52 |
53 |
54 |
55 |
56 | Manually positioned single legend within the top-right of the charting
57 | area. Positions via enter encoding:
58 |
59 |
60 |
61 |
62 | Manually positioned single legend within the top-right of the charting
63 | area. Positions via top-level absolute positioning; should be identical to
64 | example above:
65 |
39 | Lines should be straight but with lower side longer than upper side
40 | because of the orthographic projection.
41 |
42 |
43 |
44 |
Shape mark from simple geoJson file
45 |
46 | Similar to above but with solid interior and curved upper and lower
47 | boundaries because boundaries of geoJSON files interpolated along great
48 | circles.
49 |
50 |
51 |
52 |
Shape mark from simple topoJson file
53 |
Two regions with separate IDs and coloured interiors.
54 |
55 |
56 |
Shape mark from multi-part topoJson file
57 |
Four regions including region with hole and coloured interiors.
58 |
59 |
60 |
Shape mark from multi-part topoJson file
61 |
As above but as a mesh instance
62 |
63 |
64 |
Shape mark from multi-part topoJson file
65 |
As above but as an interior mesh instance
66 |
67 |
68 |
Shape mark from multi-part topoJson file
69 |
As above but as an exterior mesh instance
70 |
71 |
72 |
London Mesh and Features
73 |
74 | London Boroughs with features shaded, exterior mesh in black and interior
75 | mesh in red
76 |
45 | Pie charts encode proportional differences among a set of numeric values
46 | as the angular extent and in area of a circular slice.
47 |
48 |
49 |
50 |
51 | Similarly 'doughnut charts' encode proportional differences but with a
52 | central 'hole' to reduce emphasis on variability in area saliency.
53 |
54 |
55 |
56 |
57 | This radial plot uses both angular and radial extent to convey multiple
58 | dimensions of data. However, this approach is not perceptually effective,
59 | as viewers will most likely be drawn to the total area of the shape,
60 | conflating the two dimensions. This example also demonstrates one way to
61 | add labels to circular plots.
62 |
63 |
64 |
65 |
66 | A radar chart displaya multivariate data in the form of a two-dimensional
67 | radual layout of three or more quantitative variables whose magnitude is
68 | represented by distsance from a central point. Useful for quantitative
69 | variables that have a circular distribution (e.g. temporal cycles and
70 | azimuthal directions).
71 |
72 |
73 |
74 |
Source
75 |
76 | click to see code
77 |
78 |
79 |
80 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to make participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies within all project spaces, and it also applies when
49 | an individual is representing the project or its community in public spaces.
50 | Examples of representing a project or community include using an official
51 | project e-mail address, posting via an official social media account, or acting
52 | as an appointed representative at an online or offline event. Representation of
53 | a project may be further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at gicentre@city.ac.uk. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
78 |
--------------------------------------------------------------------------------
/examples/tests/configTests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vega Configuration Tests
5 |
6 |
7 |
11 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
Vega Configuration Tests
36 |
37 |
Style Configuration
38 |
39 |
Original plot with no configuration
40 |
41 |
42 |
ggplot2 style configuration
43 |
44 |
45 |
46 | signal determining base font size and configuration of thick capped grid
47 | and domain and larger lineBottom aligned x axis labels offset to the
48 | right.
49 |
50 |
51 |
52 |
Title, subtitle and group encoding (hover pointer over subtitle)
53 |
54 |
55 |
56 | Title encoding using deprecated tiEncode (should generate new
57 | title element encoding with blue text for title only).
58 |
59 |
60 |
61 |
Subtitle configuration
62 |
63 |
64 |
Event Configuration
65 |
66 |
Unconfigured event spec
67 |
68 |
69 |
Dragging disabled via config
70 |
71 |
72 |
73 | Bar chart with horizontal axis ticks aligned to band extent and horizontal
74 | axis displaced by 4 pixels and crosshair cursor over bars.
75 |
76 |
77 |
78 |
As previous but with global crosshair cursor
79 |
80 |
81 |
Locale Configuration
82 |
83 |
Default locale (no extra configuration).
84 |
85 |
86 |
Empty locale provided (should default as above)
87 |
88 |
89 |
90 | German locale assuming Euro currency, German month names and . tbousand
91 | divider
92 |
45 | A bar chart encodes quantitative values as the extent of rectangular bars.
46 | This example includes basic highlighting and tooltips on mouse hover.
47 |
48 |
49 |
50 |
A bar chart with gradient colouring.
51 |
52 |
53 |
54 | A stacked bar chart depicts the sum of series of quantitative values using
55 | layered bars, while still enabling inspection of individual series.
56 |
57 |
58 |
59 |
60 | This grouped bar chart facets the data into groups, then creates a bar
61 | chart for each sub-group.
62 |
63 |
64 |
65 |
66 | This nested bar chart depicts aggregated values across multiple
67 | categories. The input data is subdivided according to two fields (with
68 | uneven category membership). Each sub-group is then aggregated to show the
69 | average value of a third, quantitative field.
70 |
71 |
72 |
73 |
74 | A population pyramid shows the distribution of age groups within a
75 | population. This example shows males and females across 150 years of U.S.
76 | census data. Drag the slider to see the U.S. population change over time
77 | (but watch out for missing data in 1890!).
78 |
46 | Different interpolators change the curvature of the line. Options such as
47 | cardinal or Catmull-Rom interpolation can produce pleasing curves, but can
48 | also “hallucinate” maximum or minimum values that do not exist in the
49 | data. Use monotone interpolation for smooth curves that faithfully
50 | preserve monotonicity.
51 |
52 |
53 |
54 |
55 | An area chart uses a filled shape to show changes in a quantitative value.
56 |
57 |
58 |
59 |
60 | A stacked area chart depicts the sum of series of quantitative values
61 | using layered areas, while still enabling inspection of individual series.
62 |
63 |
64 |
65 |
66 | By dividing an area chart into consecutive layers, horizon graphs present
67 | time-series data in a compact space while preserving resolution. Click the
68 | chart to change the number of layers. Though the chart size changes, the
69 | spatial resolution of the area chart stays constant.
70 |
71 |
72 |
73 |
74 | The Job Voyager is an interactive stacked graph of occupations based on
75 | 150 years of U.S. census data. Either click elements or type queries to
76 | explore. The search box supports regular expressions; for example the
77 | query ist$ finds all jobs ending with 'ist'.
78 |
46 | A node-link tree diagram of classes in a software package hierarchy,
47 | positioned in Cartesian coordinates using Vega’s tree transform. Adjust
48 | the parameters to see layouts suitable for general trees or cluster
49 | dendrograms.
50 |
51 |
52 |
53 |
54 | A node-link tree diagram of classes in a software package hierarchy,
55 | positioned in polar coordinates using Vega’s tree transform. Adjust the
56 | parameters to see layouts suitable for general trees or cluster
57 | dendrograms.
58 |
59 |
60 |
61 |
62 | Treemaps display hierarchical data as a set of nested rectangles. This
63 | example shows the software class hierarchy of the Flare visualization
64 | toolkit (a precursor to D3 and Vega). Node areas are proportional to the
65 | file size in bytes of each source code file.
66 |
67 |
68 |
69 |
70 | A circle packing layout uses containment to convey hierarchical
71 | relationships. The layout is computed using Vega’s pack transform. This
72 | example shows the software class hierarchy of the Flare visualization
73 | toolkit; node areas are proportional to the file size in bytes of each
74 | source code file.
75 |
76 |
77 |
78 |
79 | A sunburst diagram is a radial space-filling tree visualization, similar
80 | in spirit to a treemap. Adjacency, rather than containment, is used to
81 | depict hierarchical relationships. The layout is computed using Vega’s
82 | partition transform. This example shows the software class hierarchy of
83 | the Flare visualization toolkit; node areas are proportional to the file
84 | size in bytes of each source code file.
85 |
47 | Hierarchical edge bundling that visualizes dependencies between classes in
48 | a software class hierarchy. Dependency curves are routed along the tree
49 | path between source and targets nodes in the package hierarchy. This
50 | example uses Vega’s tree transform to layout the nodes, and a line mark
51 | with bundle interpolation to draw dependencies. Hover over a node to
52 | highlight specific linkages.
53 |
54 |
55 |
56 |
57 | Network layout by force-directed placement. Uses Vega’s force transform to
58 | simulate physical forces such as charge repulsion and edge constraint.
59 | Drag nodes to reposition them.
60 |
61 |
62 |
63 |
64 | Matrix diagrams visualize a network by treating nodes as rows and columns
65 | of a table; cells are colored in if an edge exists between two nodes. This
66 | example depicts character co-occurrences in Victor Hugo’s Les Misérables.
67 | The underlying data is an undirected graph, and so the matrix is symmetric
68 | around the diagonal. The matrix is also reorderable by grabbing a node
69 | label to rearrange rows and columns.
70 |
71 |
72 |
73 |
74 | An arc diagram visualizes a network using a one-dimensional layout of
75 | nodes and circular arcs to represent links. Though an arc diagram may not
76 | always convey the overall structure of the graph as effectively as a
77 | two-dimensional layout, with a good ordering of nodes one can identify
78 | cliques and bridges. Arc diagrams were originally invented to depict
79 | repeated musical structures in Martin Wattenberg’s The Shape of Song.
80 |
81 |
82 |
83 |
84 | An interactive visualization of connections among major U.S. airports in
85 | 2008. Based on a U.S. airports example by Mike Bostock.
86 |
45 | An interactive graphic showing projected and real U.S. national budgets.
46 | Adapted from
47 | Budget Forecasts, Compared With Reality
52 | by Amanda Cox, The New York Times (February 2, 2010).
53 |
54 |
55 |
56 |
57 | Often credited as the founder of statistical graphics, William Playfair
58 | published this chart in 1822 in a letter to Parliament. It shows 250 years
59 | of the price of wheat, typical weekly wages of a mechanic, and the
60 | reigning monarch. He intended to demonstrate that "never at any former period was wheat so cheap, in proportion to
62 | mechanical labour, as it is at the present time."
64 |
65 |
66 |
67 |
68 | The population of the German city of Falkensee over time, by Dominik
69 | Moritz. Based on an
70 | image from Wikipedia.
75 |
76 |
77 |
78 |
79 | A collection of small multiple area charts, showing average daily
80 | temperatures in Seattle for each hour of the day.
81 |
82 |
83 |
84 |
85 | Weekly weather data depicting ranges of record temperatures (light gray),
86 | normal temperatures (dark gray), actual temperatures (solid black) and
87 | forecasted temperatures (black barbells, with thick ends indicating
88 | forecasted ranges for high and low values).
89 |
90 |
91 |
92 |
93 | A ridgeline plot showing the prevalence of various food and beverage
94 | categories in Seattle’s University District. Similar to a violin plot,
95 | this plot uses a continuous approximation of discrete data computed using
96 | kernel density estimation (KDE).
97 |
46 | Scatter plots are ideal for visualizing the relationship between two
47 | quantitative variables. This example plots horsepower vs. mileage for a
48 | data set of cars. A size encoding is used to additionally depict
49 | acceleration.
50 |
51 |
52 |
53 |
54 | A configurable scatter plot of movie statistics, including IMDB and Rotten
55 | Tomatoes review scores. Null values in one or more dimensions are depicted
56 | along the margins to better convey missing values. Tooltips are included
57 | for interactive inspection of individual movies.
58 |
59 |
60 |
61 |
62 | A connected scatter plot uses line segments to connect consecutive scatter
63 | plot points, for example to illustrate trajectories over time. This
64 | example shows the shifting relationship between the price of gas and the
65 | average number of miles driven in a year, adapted from Driving Shifts Into
66 | Reverse by Hannah Fairfield, The New York Times (May 2, 2010).
67 |
68 |
69 |
70 |
71 | A dot plot of average yields for a variety of barley strains, with error
72 | bars indicating the spread of values. Vega can visualize pre-calculated
73 | error ranges or apply a number of standard measures. Use the drop down
74 | menu to visualize different measures of spread, including the 95%
75 | confidence interval of the mean (calculated via bootstrapping), standard
76 | error, standard deviation, and the interquartile range.
77 |
78 |
79 |
80 |
81 | A trellis plot subdivides a chart into small multiples to isolate specific
82 | subsets and promote comparison. This example shows barley yields by
83 | variety at different sites, adapted from the original
84 | Trellis Display article
89 | by Becker et al.
90 |
91 |
92 |
93 |
94 | A labelled scatter plot of Rotten Tomatoes and IMDB scores. Text marks are
95 | re-positioned using non-overlapping label transform.
96 |
42 | A heatmap of annual temperatures in Seattle, organized by day versus hour.
43 | How do different choices of color palette affect the clarity of the
44 | patterns?
45 |
46 |
47 |
48 |
49 | Density estimates for automobile statistics, partitioned by region of
50 | origin. The density grids are rendered as images by the heatmap transform.
51 | By default each heatmap is normalized independently. If resolve equals
52 | `shared`, the heatmaps instead show probability or count densities
53 | normalized by the global maximum across plots.
54 |
55 |
56 |
57 |
58 | Parallel coordinates visualize multi-dimensional data by representing each
59 | dimension as a parallel axis, and drawing individual data records as lines
60 | connecting points on each axis. Line crossings indicate negative
61 | correlation, and different axis orderings may reveal different patterns of
62 | interest.
63 |
64 |
65 |
66 |
67 | A word cloud (or tag cloud) depicts text data, typically by sizing each
68 | word proportionally to its frequency within the text. Vega’s wordcloud
69 | transform uses a layout similar to Wordle, based on Jason Davies’
70 | wordcloud implementation. This example visualizes frequent words in the
71 | abstracts of published research papers from the Vega project.
72 |
73 |
74 |
75 |
76 | A custom timeline visualization showing the lifespans of the first five
77 | U.S. presidents, including the years each held office. The timeline is
78 | additionally annotated with selected historical events.
79 |
80 |
81 |
82 |
83 | A beeswarm plot conveys the size of a group of items by visually
84 | clustering the each individual data point. This example uses Vega’s force
85 | transform to calculate the clustered layout. The example uses non-standard
86 | xfocus and yfocus encoding channels to create anchor coordinates that
87 | parameterize the x and y forces.
88 |
89 |
90 |
91 |
92 | A calendar visualization of daily changes to the S&P 500 since 2000.
93 | Adapted from a
94 | Calendar View
95 | by Mike Bostock.
96 |
97 |
98 |
99 |
100 | A packed bubble chart displays relatively sized circles arbitrarily packed together. You can change the shape of the
101 | packing by adjusting the x or y gravity. This example shows dummy categorical data where node areas are proportional
102 | to the amount value.
103 |
104 | The original Vega example was made by David Bacci
105 |
42 | Interactive cross-filtering of airline arrival delay, departure time and
43 | travel distance data for 200,000 flights. Uses the Vega crossfilter
44 | transform to perform efficient incremental updates. Click and drag to move
45 | or resize a brush, double-click to maximize, or use the scroll wheel to
46 | zoom the brush size. Based on the
47 | Crossfilter.js example
48 | by Mike Bostock.
49 |
50 |
51 |
52 |
53 | An overview plus detail interaction: click and drag in the overview to
54 | zoom the larger detail view. Based on a
55 | D3 example
56 | by Mike Bostock.
57 |
58 |
59 |
60 |
61 | Brushing and linking is an interaction technique that highlights points
62 | based on linked selections across multiple views. This can be particularly
63 | useful for exploring relationships in multi-dimensional data. This example
64 | uses an interactive scatter plot matrix of penguin morphology, in an
65 | homage to the original
66 | Brushing Scatterplots
67 | paper
68 | by Becker and Cleveland. Click and drag on the visualization to make a
69 | linked selection.
70 |
71 |
72 |
73 |
74 | Interactive scatter plot that can be panned and zoomed. Click and drag to
75 | pan, use the scroll wheel to zoom. Scatter plot points also adjust their
76 | size in response to the zoom level.
77 |
78 |
79 |
80 |
81 | Interactive timelines for global health and economic development data:
82 | grab a point to drag it through time. Based on the
83 | DimpVis technique
84 | by Brittany Kondo and Christopher Collins, University of Ontario Institute
85 | of Technology (2014).
86 |
87 |
88 |
89 |
90 | A scatter plot with interactive guides. Shift-click legend entries to
91 | select subsets of the data, or drag along the x-axis to create a 1D brush.
92 | Click the chart background to clear all selections.
93 |
94 |
95 |
96 |
97 | This example enables interactive exploration of investment returns based
98 | on the time of purchase. As the mouse position changes, the chart updates
99 | to show the resulting proportional returns for a set of technology stocks
100 | had one invested at that time.
101 |
102 |
103 |
104 |
105 | Estimation of π by randomly sampling points and counting how many of them
106 | fall inside or outside a unit circle. Based on the
107 | Observable notebook by Cameron Yick.
109 |
110 |
111 |
112 |
113 |
114 | Circle packing with interaction based on an original Vega spec by Madison
115 | Giammaria. It incorporates a timer to facilitate zoom and fade animations, offering a technique beneficial for
116 | drill-down behavior and exploration. A few text marks associated with the user-selected node are revealed on zoom.
117 |
118 |
119 |
120 |
121 |
Source
122 |
123 | click to see code
124 |
125 |
126 |
127 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/examples/tests/src/EventTests.elm:
--------------------------------------------------------------------------------
1 | port module EventTests exposing (elmToJS)
2 |
3 | import Browser
4 | import Dict
5 | import Html exposing (Html)
6 | import Html.Attributes
7 | import Html.Events
8 | import Json.Encode
9 | import Vega exposing (..)
10 |
11 |
12 |
13 | {- These tests converted from the examples under 'Marks' on the offical Vega site:
14 | https://vega.github.io/vega/docs/marks/
15 | -}
16 |
17 |
18 | uiEvents : Spec
19 | uiEvents =
20 | let
21 | si =
22 | signals
23 | << signal "rSize" [ siValue (vNum 100), siBind (iRange [ inMin 1, inMax 400 ]) ]
24 | << signal "rColor" [ siValue (vStr "red"), siBind (iRadio [ inOptions (vStrs [ "red", "blue", "black" ]) ]) ]
25 | << signal "borderColor" [ siValue black, siBind (iColor []) ]
26 | << signal "rFill" [ siValue vFalse, siBind (iCheckbox []) ]
27 | << signal "rLabel" [ siValue (vStr ""), siBind (iText [ inPlaceholder "Type label here" ]) ]
28 | << signal "labelSize" [ siValue (vNum 10), siBind (iNumber []) ]
29 | << signal "borderWidth" [ siValue (vStr "medium"), siBind (iSelect [ inOptions (vStrs [ "thin", "medium", "thick" ]) ]) ]
30 | << signal "timestamp" [ siValue (vStr "12:00"), siBind (iTime []) ]
31 |
32 | mk =
33 | marks
34 | << mark rect
35 | [ mEncode
36 | [ enUpdate
37 | [ maFillOpacity [ vSignal "rFill ? 1 : 0" ]
38 | , maFill [ vSignal "rColor" ]
39 | , maStroke [ vSignal "borderColor" ]
40 | , maStrokeWidth [ vSignal "borderWidth == 'thin' ? 1 : borderWidth == 'medium' ? 4 : 10" ]
41 | , maWidth [ vSignal "rSize" ]
42 | , maHeight [ vSignal "rSize" ]
43 | ]
44 | ]
45 | ]
46 | << mark text
47 | [ mEncode
48 | [ enEnter [ maAlign [ hCenter ] ]
49 | , enUpdate
50 | [ maX [ vSignal "rSize / 2" ]
51 | , maY [ vSignal "rSize / 2" ]
52 | , maText [ vSignal "rLabel +' '+ timestamp" ]
53 | , maFill [ vSignal "rColor == 'black' && rFill ? 'white' : 'black'" ]
54 | , maFontSize [ vSignal "labelSize" ]
55 | ]
56 | ]
57 | ]
58 | in
59 | toVega
60 | [ width 400, height 400, padding 5, si [], mk [] ]
61 |
62 |
63 | eventStream1 : Spec
64 | eventStream1 =
65 | let
66 | si =
67 | signals
68 | << signal "myDrag"
69 | [ siValue (vNums [ 200, 200 ])
70 | , siOn
71 | [ evHandler
72 | [ esObject
73 | [ esBetween [ esMark rect, esType etMouseDown ] [ esSource esView, esType etMouseUp ]
74 | , esSource esView
75 | , esType etMouseMove
76 | ]
77 | ]
78 | [ evUpdate "xy()" ]
79 | ]
80 | ]
81 |
82 | mk =
83 | marks
84 | << mark rect
85 | [ mEncode
86 | [ enEnter [ maFill [ vStr "firebrick" ], maWidth [ vNum 80 ], maHeight [ vNum 50 ] ]
87 | , enUpdate [ maX [ vSignal "myDrag[0]" ], maY [ vSignal "myDrag[1]" ] ]
88 | ]
89 | ]
90 | << mark text
91 | [ mEncode
92 | [ enEnter
93 | [ maAlign [ hCenter ]
94 | , maBaseline [ vMiddle ]
95 | , maFill [ white ]
96 | , maText [ vStr "Drag me" ]
97 | ]
98 | , enUpdate
99 | [ maX [ vSignal "myDrag[0]+40" ]
100 | , maY [ vSignal "myDrag[1]+25" ]
101 | ]
102 | ]
103 | ]
104 | in
105 | toVega
106 | [ width 400, height 400, background (str "rgb(252,247,236)"), padding 5, si [], mk [] ]
107 |
108 |
109 |
110 | {- This list comprises the specifications to be provided to the Vega runtime. -}
111 |
112 |
113 | specs : List ( String, Spec )
114 | specs =
115 | [ ( "uiEvents", uiEvents )
116 | , ( "eventStream1", eventStream1 )
117 | ]
118 |
119 |
120 |
121 | {- ---------------------------------------------------------------------------
122 | BOILERPLATE: NO NEED TO EDIT
123 |
124 | The code below creates an Elm module that opens an outgoing port to Javascript
125 | and sends both the specs and DOM node to it.
126 | It allows the source code of any of the generated specs to be selected from
127 | a drop-down list. Useful for viewin specs that might generate invalid Vega-Lite.
128 | -}
129 |
130 |
131 | type Msg
132 | = NewSource String
133 |
134 |
135 | main : Program () Spec Msg
136 | main =
137 | Browser.element
138 | { init = always ( Json.Encode.null, specs |> combineSpecs |> elmToJS )
139 | , view = view
140 | , update = update
141 | , subscriptions = always Sub.none
142 | }
143 |
144 |
145 | view : Spec -> Html Msg
146 | view spec =
147 | Html.div []
148 | [ Html.select [ Html.Events.onInput NewSource ]
149 | (( "Select source", Json.Encode.null )
150 | :: specs
151 | |> List.map (\( s, _ ) -> Html.option [ Html.Attributes.value s ] [ Html.text s ])
152 | )
153 | , Html.div [ Html.Attributes.id "specSource" ] []
154 | , if spec == Json.Encode.null then
155 | Html.div [] []
156 |
157 | else
158 | Html.pre [] [ Html.text (Json.Encode.encode 2 spec) ]
159 | ]
160 |
161 |
162 | update : Msg -> Spec -> ( Spec, Cmd Msg )
163 | update msg _ =
164 | case msg of
165 | NewSource srcName ->
166 | ( specs |> Dict.fromList |> Dict.get srcName |> Maybe.withDefault Json.Encode.null, Cmd.none )
167 |
168 |
169 | port elmToJS : Spec -> Cmd msg
170 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # elm-vega
2 |
3 | 
4 |
5 | [](https://elm-lang.org)
6 | [](https://vega.github.io/vega/)
7 | [](CODE_OF_CONDUCT.md)
8 |
9 | _Declarative visualization for Elm._
10 |
11 | This package allows you to create [Vega](https://vega.github.io/vega/) specifications in Elm providing a pure functional approach to declarative visualization.
12 | It does not generate graphical output directly, but instead allows you to create JSON _specifications_ that can be sent to the Vega runtime to create the output.
13 |
14 | _Note: If you wish to create Vega-Lite specifications, use the sister-package [elm-vegaLite](https://github.com/gicentre/elm-vegaLite)._
15 |
16 | ## Example
17 |
18 | Visualizing a set of geospatial centroids as a Voronoi diagram:
19 |
20 | ```elm
21 | let
22 | ds =
23 | dataSource
24 | [ data "centroids"
25 | [ daUrl (str "https://gicentre.github.io/data/uk/constituencySpacedCentroidsWithSpacers.csv")
26 | , daFormat [ csv, parseAuto ]
27 | ]
28 | |> transform
29 | [ trGeoPoint "projection"
30 | (field "longitude")
31 | (field "latitude")
32 | , trVoronoi (field "x")
33 | (field "y")
34 | [ voSize (numSignals [ "width", "height" ]) ]
35 | ]
36 | ]
37 |
38 | pr =
39 | projections
40 | << projection "projection"
41 | [ prType transverseMercator
42 | , prScale (num 3700)
43 | , prTranslate (nums [ 320, 3855 ])
44 | ]
45 |
46 | sc =
47 | scales
48 | << scale "cScale" [ scType scOrdinal, scRange raCategory ]
49 |
50 | mk =
51 | marks
52 | << mark path
53 | [ mFrom [ srData (str "centroids") ]
54 | , mEncode
55 | [ enEnter
56 | [ maPath [ vField (field "path") ]
57 | , maFill
58 | [ ifElse "datum.region == 0"
59 | [ transparent ]
60 | [ vScale "cScale", vField (field "region") ]
61 | ]
62 | ]
63 | ]
64 | ]
65 | in
66 | toVega
67 | [ width 420, height 670, ds, pr [], sc [], mk [] ]
68 | ```
69 |
70 | This generates a JSON specification that when sent to the Vega runtime produces the following output:
71 |
72 | 
73 |
74 | ## Why elm-vega?
75 |
76 | ### A rationale for Elm programmers
77 |
78 | There is a [demand for good visualization packages with Elm](https://package.elm-lang.org/packages/elm/svg/latest), especially ones that incorporate good practice in visualization design.
79 | [Vega](https://vega.github.io/vega/) provides a theoretically robust and flexible grammar for specifying visualization design but is based on the JSON format.
80 | elm-vega provides a typed functional mapping of Vega, so affording the advantages of the Elm language in building up higher level visualization functions.
81 | Because Vega is widely used, you can take advantage of the many thousands of visualizations already shared in the Vega language.
82 |
83 | **Characteristics of elm-vega.**
84 |
85 | - Built upon the widely used [Vega](https://vega.github.io/vega/) specification that has an academic robustness and momentum behind its development.
86 |
87 | - Full access to lower level expressive visualization design.
88 |
89 | - Strict typing and friendly error messages means "the compiler is your friend" when building and debugging complex visualizations.
90 |
91 | ### A rationale for data visualizers
92 |
93 | In using JSON to fully encode a visualization specification Vega is portable across a range of platforms and sits well in the JavaScript / Web ecosystem.
94 | Yet JSON is really an interchange format rather than one suited directly for visualization design and construction.
95 |
96 | By wrapping Vega within the Elm language, we can avoid working with JSON directly and instead take advantage of a typed functional programming environment for improved error support and customisation.
97 | This greatly improves reusability of code and integration with larger programming projects.
98 |
99 | Elm and elm-vega provide an ideal environment for educators wishing to teach more advanced Data Visualization combining the beginner-friendly design of Elm with the robust and theoretically underpinned design of Vega.
100 |
101 | ## Limitations
102 |
103 | - elm-vega does not render graphics directly, but instead generates data visualization specifications that may be passed to JavaScript for rendering.
104 |
105 | ## Further Reading
106 |
107 | - If you have not done so already, to get familiar with the approach of declarative visualization you may find it helpful to look first at the simpler [elm-vegaLite](https://github.com/gicentre/elm-vegaLite).
108 | - Then try [creating your first Vega visualization with elm-vega](https://github.com/gicentre/elm-vega/tree/main/docs/helloWorld) and [specifying a Vega bar chart](https://github.com/gicentre/elm-vega/tree/main/docs/barChart).
109 | - For a rich set of Vega examples see the [Vega example gallery](https://github.com/gicentre/elm-vega/tree/main/examples/gallery).
110 | - To get coding, see the [elm-vega API](https://package.elm-lang.org/packages/gicentre/elm-vega/latest) documentation.
111 | - Further examples can be found in the [elm-vega examples](https://github.com/gicentre/elm-vega/tree/main/examples) and [elm-vega tests](https://github.com/gicentre/elm-vega/tree/main/examples/tests) folders.
112 | - You can also work with elm-vega in [litvis](https://github.com/gicentre/litvis) – a _literate visualization_ environment for embedding visualization specifications in a formatted text environment.
113 |
114 | ## Looking for an older version?
115 |
116 | If you are using Elm 0.18, you will need to use [elm-vega 3.0](https://github.com/gicentre/elm-vega/tree/v3.0) and its [API documentation](https://package.elm-lang.org/packages/gicentre/elm-vega/3.0.1).
117 | This older version combines modules for working with both Vega and Vega-Lite.
118 |
--------------------------------------------------------------------------------
/examples/tests/src/TopLevelTests.elm:
--------------------------------------------------------------------------------
1 | port module TopLevelTests exposing (elmToJS)
2 |
3 | import Browser
4 | import Dict
5 | import Html exposing (Html)
6 | import Html.Attributes
7 | import Html.Events
8 | import Json.Encode
9 | import Vega exposing (..)
10 |
11 |
12 | topLevelTest1 : Spec
13 | topLevelTest1 =
14 | let
15 | table =
16 | dataFromColumns "table" []
17 | << dataColumn "label" (vStrs [ "Hello", "from", "elm-vega" ])
18 | << dataColumn "x" (vNums [ 1, 2, 3 ])
19 |
20 | ds =
21 | dataSource [ table [] ]
22 |
23 | sc =
24 | scales
25 | << scale "xscale"
26 | [ scDomain (doData [ daDataset "table", daField (field "x") ])
27 | , scRange raWidth
28 | ]
29 |
30 | mk =
31 | marks
32 | << mark text
33 | [ mFrom [ srData (str "table") ]
34 | , mEncode
35 | [ enEnter
36 | [ maX [ vScale "xscale", vField (field "x") ]
37 | , maText [ vField (field "label") ]
38 | ]
39 | ]
40 | ]
41 | in
42 | toVega
43 | [ description "Hello from Elm-Vega", width 100, ds, sc [], mk [] ]
44 |
45 |
46 | topLevelTest2 : Spec
47 | topLevelTest2 =
48 | let
49 | table =
50 | dataFromColumns "table" []
51 | << dataColumn "label" (vStrs [ "Hello", "from", "elm-vega" ])
52 | << dataColumn "x" (vNums [ 1, 2, 3 ])
53 |
54 | ds =
55 | dataSource [ table [] ]
56 |
57 | sc =
58 | scales
59 | << scale "xscale"
60 | [ scDomain (doData [ daDataset "table", daField (field "x") ])
61 | , scRange raWidth
62 | ]
63 |
64 | mk =
65 | marks
66 | << mark text
67 | [ mFrom [ srData (str "table") ]
68 | , mEncode
69 | [ enEnter
70 | [ maX [ vScale "xscale", vField (field "x") ]
71 | , maText [ vField (field "label") ]
72 | ]
73 | ]
74 | ]
75 | in
76 | toVega
77 | [ userMeta
78 | [ ( "Org", vStr "giCentre" )
79 | , ( "Date", vStr "2019-10-29" )
80 | , ( "Version", vNum 3.2 )
81 | ]
82 | , width 100
83 | , ds
84 | , sc []
85 | , mk []
86 | ]
87 |
88 |
89 | topLevelTest3 : Spec
90 | topLevelTest3 =
91 | let
92 | table =
93 | dataFromColumns "table" []
94 | << dataColumn "label" (vStrs [ "Pink background", "300px wide", "60px tall", "L-T-R-B padding 20,30,40 & 50px" ])
95 | << dataColumn "y" (vNums [ 1, 2, 3, 4 ])
96 |
97 | si =
98 | signals
99 | << signal "myBgColor" [ siInit "rgb(255,200,200)" ]
100 | << signal "myHeight" [ siInit "60" ]
101 | << signal "myPadding"
102 | [ siValue
103 | (vObject
104 | [ keyValue "left" (vNum 20)
105 | , keyValue "top" (vNum 30)
106 | , keyValue "right" (vNum 40)
107 | , keyValue "bottom" (vNum 50)
108 | ]
109 | )
110 | ]
111 | << signal "myAutosize" [ siValue (vObject [ keyValue "type" (vStr "fit") ]) ]
112 |
113 | ds =
114 | dataSource [ table [] ]
115 |
116 | sc =
117 | scales
118 | << scale "yScale"
119 | [ scDomain (doData [ daDataset "table", daField (field "y") ])
120 | , scRange raHeight
121 | ]
122 |
123 | mk =
124 | marks
125 | << mark text
126 | [ mFrom [ srData (str "table") ]
127 | , mEncode
128 | [ enEnter
129 | [ maY [ vScale "yScale", vField (field "y") ]
130 | , maText [ vField (field "label") ]
131 | ]
132 | ]
133 | ]
134 | in
135 | toVega
136 | [ description "Hello from Elm-Vega"
137 | , background (strSignal "myBgColor")
138 | , widthSignal "600/2"
139 | , heightSignal "myHeight"
140 | , paddingSignal "myPadding"
141 | , autosize [ asSignal "myAutosize" ]
142 | , si []
143 | , ds
144 | , sc []
145 | , mk []
146 | ]
147 |
148 |
149 |
150 | {- This list comprises the specifications to be provided to the Vega runtime. -}
151 |
152 |
153 | specs : List ( String, Spec )
154 | specs =
155 | [ ( "topLevelTest1", topLevelTest1 )
156 | , ( "topLevelTest2", topLevelTest2 )
157 | , ( "topLevelTest3", topLevelTest3 )
158 | ]
159 |
160 |
161 |
162 | {- ---------------------------------------------------------------------------
163 | BOILERPLATE: NO NEED TO EDIT
164 |
165 | The code below creates an Elm module that opens an outgoing port to Javascript
166 | and sends both the specs and DOM node to it.
167 | It allows the source code of any of the generated specs to be selected from
168 | a drop-down list. Useful for viewin specs that might generate invalid Vega-Lite.
169 | -}
170 |
171 |
172 | type Msg
173 | = NewSource String
174 |
175 |
176 | main : Program () Spec Msg
177 | main =
178 | Browser.element
179 | { init = always ( Json.Encode.null, specs |> combineSpecs |> elmToJS )
180 | , view = view
181 | , update = update
182 | , subscriptions = always Sub.none
183 | }
184 |
185 |
186 | view : Spec -> Html Msg
187 | view spec =
188 | Html.div []
189 | [ Html.select [ Html.Events.onInput NewSource ]
190 | (( "Select source", Json.Encode.null )
191 | :: specs
192 | |> List.map (\( s, _ ) -> Html.option [ Html.Attributes.value s ] [ Html.text s ])
193 | )
194 | , Html.div [ Html.Attributes.id "specSource" ] []
195 | , if spec == Json.Encode.null then
196 | Html.div [] []
197 |
198 | else
199 | Html.pre [] [ Html.text (Json.Encode.encode 2 spec) ]
200 | ]
201 |
202 |
203 | update : Msg -> Spec -> ( Spec, Cmd Msg )
204 | update msg _ =
205 | case msg of
206 | NewSource srcName ->
207 | ( specs |> Dict.fromList |> Dict.get srcName |> Maybe.withDefault Json.Encode.null, Cmd.none )
208 |
209 |
210 | port elmToJS : Spec -> Cmd msg
211 |
--------------------------------------------------------------------------------
/examples/tests/src/ColorTests.elm:
--------------------------------------------------------------------------------
1 | port module ColorTests exposing (elmToJS)
2 |
3 | import Browser
4 | import Dict
5 | import Html exposing (Html)
6 | import Html.Attributes
7 | import Html.Events
8 | import Json.Encode
9 | import Vega exposing (..)
10 |
11 |
12 | colorTest1 : Spec
13 | colorTest1 =
14 | let
15 | ellipse =
16 | let
17 | rminor =
18 | -- Minor axis as a proportion of major axis
19 | 0.3
20 |
21 | pair t =
22 | let
23 | x =
24 | cos t
25 |
26 | y =
27 | rminor * sin t
28 | in
29 | "L " ++ String.fromFloat x ++ " " ++ String.fromFloat y
30 |
31 | thetas =
32 | List.range 0 40 |> List.map (\n -> (2 * pi / 40) * toFloat n)
33 | in
34 | List.intersperse " " (List.map pair thetas) |> String.concat
35 |
36 | ellipseEncoding c a =
37 | let
38 | ( x1, x2 ) =
39 | if a < 0 then
40 | ( 1, 0 )
41 |
42 | else if a > 0 then
43 | ( 0.7, 0.3 )
44 |
45 | else
46 | ( 0.5, 0.5 )
47 |
48 | ( y1, y2 ) =
49 | if a < 0 then
50 | ( 1, 0 )
51 |
52 | else if a > 0 then
53 | ( 0.1, 1 )
54 |
55 | else
56 | ( 1, 0 )
57 | in
58 | [ mEncode
59 | [ enEnter
60 | [ maStroke [ vStr c ]
61 | , maFill
62 | [ vGradient grLinear
63 | [ grStops [ ( num 0, "white" ), ( num 1, c ) ]
64 | , grX1 (num x1)
65 | , grX2 (num x2)
66 | , grY1 (num y1)
67 | , grY2 (num y2)
68 | ]
69 | ]
70 | , maX [ vNum 100 ]
71 | , maY [ vNum 100 ]
72 | , maScaleX [ vNum 100 ]
73 | , maScaleY [ vNum 100 ]
74 | , maPath [ vStr ellipse ]
75 | , maAngle [ vNum a ]
76 | , maStrokeWidth [ vNum 2 ]
77 | ]
78 | , enUpdate
79 | [ maOpacity [ vNum 1 ]
80 | , maBlend [ vSignal "blend" ]
81 | ]
82 | , enHover [ maOpacity [ vNum 0.5 ] ]
83 | ]
84 | ]
85 |
86 | si =
87 | signals
88 | << signal "blend"
89 | [ siValue (vStr "normal")
90 | , siBind
91 | (iSelect
92 | [ inOptions
93 | (vStrs
94 | [ "normal"
95 | , "multiply"
96 | , "screen"
97 | , "overlay"
98 | , "darken"
99 | , "lighten"
100 | , "color-dodge"
101 | , "color-burn"
102 | , "hard-light"
103 | , "soft-light"
104 | , "difference"
105 | , "exclusion"
106 | , "hue"
107 | , "saturation"
108 | , "color"
109 | , "luminosity"
110 | ]
111 | )
112 | ]
113 | )
114 | ]
115 |
116 | sc =
117 | scales
118 | << scale "scale"
119 | [ scType scLinear, scRange raWidth ]
120 |
121 | ax =
122 | axes
123 | << axis "scale"
124 | siBottom
125 | [ axGrid true
126 | , axTickCount (num 10)
127 | , axDomain false
128 | , axTicks false
129 | , axLabels false
130 | ]
131 | << axis "scale"
132 | siLeft
133 | [ axGrid true
134 | , axTickCount (num 10)
135 | , axDomain false
136 | , axTicks false
137 | , axLabels false
138 | ]
139 |
140 | mk =
141 | marks
142 | << mark path (ellipseEncoding "#f00" 45)
143 | << mark path (ellipseEncoding "#0f0" 0)
144 | << mark path (ellipseEncoding "#00f" -45)
145 | in
146 | toVega
147 | [ width 200, height 200, si [], sc [], ax [], mk [] ]
148 |
149 |
150 |
151 | {- This list comprises the specifications to be provided to the Vega runtime. -}
152 |
153 |
154 | specs : List ( String, Spec )
155 | specs =
156 | [ ( "colorTest1", colorTest1 )
157 | ]
158 |
159 |
160 |
161 | {- ---------------------------------------------------------------------------
162 | BOILERPLATE: NO NEED TO EDIT
163 |
164 | The code below creates an Elm module that opens an outgoing port to Javascript
165 | and sends both the specs and DOM node to it.
166 | It allows the source code of any of the generated specs to be selected from
167 | a drop-down list. Useful for viewin specs that might generate invalid Vega-Lite.
168 | -}
169 |
170 |
171 | type Msg
172 | = NewSource String
173 |
174 |
175 | main : Program () Spec Msg
176 | main =
177 | Browser.element
178 | { init = always ( Json.Encode.null, specs |> combineSpecs |> elmToJS )
179 | , view = view
180 | , update = update
181 | , subscriptions = always Sub.none
182 | }
183 |
184 |
185 | view : Spec -> Html Msg
186 | view spec =
187 | Html.div []
188 | [ Html.select [ Html.Events.onInput NewSource ]
189 | (( "Select source", Json.Encode.null )
190 | :: specs
191 | |> List.map (\( s, _ ) -> Html.option [ Html.Attributes.value s ] [ Html.text s ])
192 | )
193 | , Html.div [ Html.Attributes.id "specSource" ] []
194 | , if spec == Json.Encode.null then
195 | Html.div [] []
196 |
197 | else
198 | Html.pre [] [ Html.text (Json.Encode.encode 2 spec) ]
199 | ]
200 |
201 |
202 | update : Msg -> Spec -> ( Spec, Cmd Msg )
203 | update msg _ =
204 | case msg of
205 | NewSource srcName ->
206 | ( specs |> Dict.fromList |> Dict.get srcName |> Maybe.withDefault Json.Encode.null, Cmd.none )
207 |
208 |
209 | port elmToJS : Spec -> Cmd msg
210 |
--------------------------------------------------------------------------------
/docs/helloWorld/README.md:
--------------------------------------------------------------------------------
1 | # Creating Your First Vega Visualization with Elm-Vega
2 |
3 | ## 1. One-time setup of Elm
4 |
5 | If you already have [Elm](http://elm-lang.org) installed, you can skip this section. If not, you can install Elm by following [these instructions](https://guide.elm-lang.org/install.html). While not strictly necessary, I would strongly recommend configuring your favourite text editor to be able to format, syntax highlight and lint Elm code (details in the installation guide above). My preferred editor that accepts Elm-specific plug-ins is [VSCode](https://code.visualstudio.com), but any text editor will do.
6 |
7 | ## 2. Create HTML/JavaScript page to link with Elm
8 |
9 | The easiest way to get Elm-Vega to produce graphical output is to write a skeleton Elm program that sends some Vega to an HTML page. That HTML page will contain some JavaScript that turns a Vega specification into graphics.
10 |
11 | To get started, copy this example to a file `helloWorld.html` somewhere on your machine:
12 |
13 | ```html
14 |
15 |
16 |
17 | Hello Vega
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
43 |
44 |
45 | ```
46 |
47 | Most of this is scaffolding that you won't need to change as you write new Elm-vega applications.
48 | The key elements are:
49 |
50 | - Links to `vega` and `vega-embed` JavaScript that do the hard work of converting the Vega specification you will be generating into graphical output.
51 |
52 | - A link to the JavaScript file generated by Elm-Vega that creates your Vega specification (here called `helloWorld.js`)
53 |
54 | - A `
` container with an ID (here called `helloWorld`) that will be the location in the HTML page that will contain your visualization.
55 |
56 | - An _Elm subscription_ that links this page with the Elm program that generates the Vega specification.
57 | Here `Elm.HelloWorld.init()` references an Elm module that must be called `HelloWorld`.
58 | When you create Elm-Vega modules with different names, you must match that name here (for example, `Elm.MyNewModule.init()`).
59 |
60 | ## 3. Create an Elm-Vega Program
61 |
62 | Create a file called `HelloWorld.elm` in the same location as `helloWorld.html`. Copy the following code into it.
63 |
64 | ```elm
65 | port module HelloWorld exposing (elmToJS)
66 |
67 | import Platform
68 | import Vega exposing (..)
69 |
70 |
71 | helloWorld : Spec
72 | helloWorld =
73 | let
74 | ds =
75 | dataSource
76 | [ dataFromRows "myData"
77 | []
78 | (dataRow [ ( "label", vStr "Hello from Vega" ) ] [])
79 | ]
80 |
81 | mk =
82 | marks
83 | << mark text
84 | [ mFrom [ srData (str "myData") ]
85 | , mEncode [ enEnter [ maText [ vField (field "label") ] ] ]
86 | ]
87 | in
88 | toVega [ ds, mk [] ]
89 |
90 |
91 |
92 | {- This list comprises the specifications to be provided to the Vega runtime.
93 | In this example, only a single spec 'helloWord' is provided.
94 | -}
95 |
96 |
97 | mySpecs : Spec
98 | mySpecs =
99 | combineSpecs [ ( "helloWorld", helloWorld ) ]
100 |
101 |
102 |
103 | {- ---------------------------------------------------------------------------
104 | The code below is boilerplate for creating a headless Elm module that opens
105 | an outgoing port to JavaScript and sends the Vega specs (mySpecs) to it.
106 | There should be no need to change this.
107 | -}
108 |
109 |
110 | main : Program () Spec msg
111 | main =
112 | Platform.worker
113 | { init = always ( mySpecs, elmToJS mySpecs )
114 | , update = \_ model -> ( model, Cmd.none )
115 | , subscriptions = always Sub.none
116 | }
117 |
118 |
119 | port elmToJS : Spec -> Cmd msg
120 | ```
121 |
122 | This creates a working Elm-program whose job is to send a Vega specification as a JSON file via an Elm _port_ to the JavaScript seen in the HTML file above. For convenience, we will always call this port `elmToJS` so it need not be changed when creating new programs. The only code you need to modify as you write your own Elm-Vega is the function that generates a `Spec`, here called `helloWorld`, and the name of the module, here called `HelloWorld`.
123 |
124 | You can add multiple Vega specifications to the same page by creating new `Spec` functions and adding their names to `combineSpecs` where each tuple comprises the name of the spec that can be referenced by the HTML and its corresponding elm function that generates the spec. Typically, to avoid confusion, both will share the same name (`( "helloWord", helloWorld )` in this example).
125 |
126 | This Vega example creates a simple data source called `myData` comprising a single row (`"label" : "Hello from Vega"`) and a single text mark that displays the label defined in the data source.
127 |
128 | ## 4. Compile the Elm-Vega into JavaScript
129 |
130 | The final task is to convert the Elm file into JavaScript so it can be used by the HTML. To do this, open a command line window (e.g. a Terminal on MacOS or PowerShell on Windows), change to the directory containing your HTML and Elm files and type
131 |
132 | ```bash
133 | elm make helloWorld.elm --output=js/helloWorld.js --optimize
134 | ```
135 |
136 | This should create the `helloWorld.js` file required by the HTML.
137 |
138 | Opening `helloWorld.html` in the browser should display a page showing the text "Hello from Vega".
139 |
140 | _Note that in this example the data used in the visualization is generated entirely inline and does not rely on external files. Typical Elm-Vega programs will however load data from external .json, .csv or other files and so normal JavaScript file loading restrictions apply. As such you would more typically test your applications with a local web server (such as generated by `python -m http.server` or `elm-reactor`) rather than load directly from your file system._
141 |
142 | ## 5. Next Steps
143 |
144 | Most of the setup described above varies little between applications. To understand more about how Elm-Vega can generate Vega specifications, see
145 |
146 | - [creating a simple bar chart](../barChart/README.md),
147 | - the [simple Vega examples](../../examples/) included in the `examples` folder,
148 | - the [test-gallery](../../test-gallery/) for a full range of examples.
149 |
--------------------------------------------------------------------------------
/examples/tests/src/AriaTests.elm:
--------------------------------------------------------------------------------
1 | port module AriaTests exposing (elmToJS)
2 |
3 | import Browser
4 | import Dict
5 | import Html exposing (Html)
6 | import Html.Attributes
7 | import Html.Events
8 | import Json.Encode
9 | import Vega exposing (..)
10 |
11 |
12 | dPath : String
13 | dPath =
14 | "https://cdn.jsdelivr.net/npm/vega-datasets@2.1/data/"
15 |
16 |
17 | scatter : Boo -> List AxisProperty -> List LegendProperty -> List TopMarkProperty -> Spec
18 | scatter titleAria axps leps mps =
19 | let
20 | ti =
21 | title (strs [ "Engine Efficiency" ])
22 | [ tiSubtitle (strs [ "Size vs efficiency" ])
23 | , tiAria titleAria
24 | ]
25 |
26 | ds =
27 | dataSource
28 | [ data "cars" [ daUrl (str (dPath ++ "cars.json")) ]
29 | |> transform [ trFilter (expr "datum['Horsepower'] != null && datum['Miles_per_Gallon'] != null && datum['Acceleration'] != null") ]
30 | ]
31 |
32 | sc =
33 | scales
34 | << scale "xScale"
35 | [ scType scLinear
36 | , scRound true
37 | , scNice niTrue
38 | , scZero true
39 | , scDomain (doData [ daDataset "cars", daField (field "Horsepower") ])
40 | , scRange raWidth
41 | ]
42 | << scale "yScale"
43 | [ scType scLinear
44 | , scRound true
45 | , scNice niTrue
46 | , scZero true
47 | , scDomain (doData [ daDataset "cars", daField (field "Miles_per_Gallon") ])
48 | , scRange raHeight
49 | ]
50 | << scale "cScale"
51 | [ scType scOrdinal
52 | , scRange raCategory
53 | , scDomain (doData [ daDataset "cars", daField (field "Origin") ])
54 | ]
55 |
56 | ax =
57 | axes
58 | << axis "xScale"
59 | siBottom
60 | (axps
61 | ++ [ axGrid true
62 | , axTickCount (num 6)
63 | , axTitle (str "Horsepower")
64 | ]
65 | )
66 | << axis "yScale"
67 | siLeft
68 | (axps
69 | ++ [ axGrid true
70 | , axTickCount (num 6)
71 | , axTitle (strs [ "Efficiency" ])
72 | ]
73 | )
74 |
75 | lg =
76 | legends
77 | << legend
78 | (leps
79 | ++ [ leFill "cScale"
80 | , leTitle (strs [ "Country of Manufacture" ])
81 | , leEncode [ enSymbols [ enUpdate [ maShape [ symbolValue symCircle ] ] ] ]
82 | ]
83 | )
84 |
85 | mk =
86 | marks
87 | << mark symbol
88 | (mps
89 | ++ [ mFrom [ srData (str "cars") ]
90 | , mEncode
91 | [ enUpdate
92 | [ maX [ vScale "xScale", vField (field "Horsepower") ]
93 | , maY [ vScale "yScale", vField (field "Miles_per_Gallon") ]
94 | , maFill [ vScale "cScale", vField (field "Origin") ]
95 | , maShape [ symbolValue symCircle ]
96 | ]
97 | ]
98 | ]
99 | )
100 | in
101 | toVega
102 | [ width 400, height 300, ti, ds, sc [], ax [], lg [], mk [] ]
103 |
104 |
105 | ariaTest1 : Spec
106 | ariaTest1 =
107 | scatter true [] [] []
108 |
109 |
110 | ariaTest2 : Spec
111 | ariaTest2 =
112 | scatter true [ axAria [] ] [] []
113 |
114 |
115 | ariaTest3 : Spec
116 | ariaTest3 =
117 | scatter true [ axAria [ arDisable ] ] [] []
118 |
119 |
120 | ariaTest4 : Spec
121 | ariaTest4 =
122 | scatter true [ axAria [ arDescription (str "my ARIA description") ] ] [] []
123 |
124 |
125 | ariaTest5 : Spec
126 | ariaTest5 =
127 | scatter true [] [ leAria [] ] []
128 |
129 |
130 | ariaTest6 : Spec
131 | ariaTest6 =
132 | scatter true [] [ leAria [ arDisable ] ] []
133 |
134 |
135 | ariaTest7 : Spec
136 | ariaTest7 =
137 | scatter true [] [ leAria [ arDescription (str "my ARIA description") ] ] []
138 |
139 |
140 | ariaTest8 : Spec
141 | ariaTest8 =
142 | scatter false [] [] []
143 |
144 |
145 | ariaTest9 : Spec
146 | ariaTest9 =
147 | scatter true [] [] [ mAria [] ]
148 |
149 |
150 | ariaTest10 : Spec
151 | ariaTest10 =
152 | scatter true [] [] [ mAria [ arDisable ] ]
153 |
154 |
155 | ariaTest11 : Spec
156 | ariaTest11 =
157 | scatter true [] [] [ mAria [ arDescription (str "my ARIA description") ] ]
158 |
159 |
160 |
161 | {- This list comprises the specifications to be provided to the Vega runtime. -}
162 |
163 |
164 | specs : List ( String, Spec )
165 | specs =
166 | [ ( "ariaTest1", ariaTest1 )
167 | , ( "ariaTest2", ariaTest2 )
168 | , ( "ariaTest3", ariaTest3 )
169 | , ( "ariaTest4", ariaTest4 )
170 | , ( "ariaTest5", ariaTest5 )
171 | , ( "ariaTest6", ariaTest6 )
172 | , ( "ariaTest7", ariaTest7 )
173 | , ( "ariaTest8", ariaTest8 )
174 | , ( "ariaTest9", ariaTest9 )
175 | , ( "ariaTest10", ariaTest10 )
176 | , ( "ariaTest11", ariaTest11 )
177 | ]
178 |
179 |
180 |
181 | {- ---------------------------------------------------------------------------
182 | BOILERPLATE: NO NEED TO EDIT
183 |
184 | The code below creates an Elm module that opens an outgoing port to Javascript
185 | and sends both the specs and DOM node to it.
186 | It allows the source code of any of the generated specs to be selected from
187 | a drop-down list. Useful for viewin specs that might generate invalid Vega-Lite.
188 | -}
189 |
190 |
191 | type Msg
192 | = NewSource String
193 |
194 |
195 | main : Program () Spec Msg
196 | main =
197 | Browser.element
198 | { init = always ( Json.Encode.null, specs |> combineSpecs |> elmToJS )
199 | , view = view
200 | , update = update
201 | , subscriptions = always Sub.none
202 | }
203 |
204 |
205 | view : Spec -> Html Msg
206 | view spec =
207 | Html.div []
208 | [ Html.select [ Html.Events.onInput NewSource ]
209 | (( "Select source", Json.Encode.null )
210 | :: specs
211 | |> List.map (\( s, _ ) -> Html.option [ Html.Attributes.value s ] [ Html.text s ])
212 | )
213 | , Html.div [ Html.Attributes.id "specSource" ] []
214 | , if spec == Json.Encode.null then
215 | Html.div [] []
216 |
217 | else
218 | Html.pre [] [ Html.text (Json.Encode.encode 2 spec) ]
219 | ]
220 |
221 |
222 | update : Msg -> Spec -> ( Spec, Cmd Msg )
223 | update msg _ =
224 | case msg of
225 | NewSource srcName ->
226 | ( specs |> Dict.fromList |> Dict.get srcName |> Maybe.withDefault Json.Encode.null, Cmd.none )
227 |
228 |
229 | port elmToJS : Spec -> Cmd msg
230 |
--------------------------------------------------------------------------------
/examples/gallery/geo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Vega Test Gallery: Geographic Maps
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
50 | A choropleth map of 2009 U.S. unemployment rates by county. A quantize
51 | scale is used to divide the color range into 9 discrete, uniformly-spaced
52 | bins.
53 |
54 |
55 |
56 |
57 | A Dorling cartogram is a thematic map that uses sized circles to represent
58 | a quantity of interest per geographic region. This example visualizes the
59 | ratio of obese adults (BMI >= 30) by U.S. state in 2008. A double encoding
60 | uses both circle area and fill color to convey the obesity rate. Vega’s
61 | force transform and geoCentroid expression function are used to compute
62 | the layout.
63 |
64 |
65 |
66 |
67 | A configurable map of world countries. Explore the results of applying
68 | different map projections and parameter settings. This example loads
69 | TopoJSON data and applies the Vega geoshape and graticule transforms.
70 |
71 |
72 |
73 |
74 | A globe visualization of earthquakes reported by the USGS for the week of
75 | February 6, 2018. The earthquakes are formatted as GeoJSON data, and the
76 | geoshape transform’s pointRadius parameter is used to visualize earthquake
77 | magnitude as a circular area. This example is based on Jeremy Ashkenas’
78 | USGS World Earthquake Map.
83 |
84 |
85 |
86 |
87 | A gallery of world maps using various cartographic projections. Each map
88 | clips the projected land masses and graticule to the sphere of the Earth
89 | to ensure no extraneous shapes are shown. This example uses projections
90 | from the
91 | d3-geo-projection library
94 | that are not included in the standard Vega release.
95 |
96 |
97 |
98 |
99 | A world map that pans and zooms in response to mouse drag and scroll wheel
100 | input. This example applies an inverse map projection (using Vega’s invert
101 | expression function) to map changes in pixel space to updated projection
102 | parameters.
103 |
104 |
105 |
106 |
107 | This example visualizes the difference in projected area of countries
108 | using two different map projections. Each country is abstracted to a
109 | circle, sized by the area of that country under a particular map
110 | projection. Country circles are positioned based on the centroid position
111 | of the country under a primary projection. A second set of circles are
112 | then overlaid, with projected areas based on a secondary projection. This
113 | example demonstrates Vega’s geoArea and geoCentroid expression language
114 | functions.
115 |
116 |
117 |
118 |
119 | A colored contour plot of the Maungawhau volcano in New Zealand. This
120 | example demonstrates contour generation directly from a provided grid of
121 | data values, rather than performing kernel density estimation on a
122 | discrete point set.
123 |
124 |
125 |
126 |
127 | A vector field visualization of simulated winds over northwestern Europe.
128 | This example uses the angle channel of the symbol mark to set the
129 | orientation of wedge or arrow shape types.
130 |
131 |
132 |
133 |
134 | 2016 annual global precipitation data from the
135 | NOAA Climate Forecast System (CFS) v2. The data are provided as a raster grid of longitude and latitude (1°
140 | per cell). Isocontours are computed against the grid and projected.
141 | Adapted from an example by @mattijn.
142 |
47 | A histogram subdivides a numerical range into bins, and counts the number
48 | of data points with each segment. The resulting bar chart provides a
49 | discrete estimate of the probability density function.
50 |
51 |
52 |
53 |
54 | This example demonstrates a histogram over a numerical range, with a
55 | segment to show the prevalence of null values.
56 |
57 |
58 |
59 |
60 | Visual comparison of estimated probability distributions for a sample of
61 | numeric values. A normal (Gaussian) distribution parameterized by the mean
62 | and standard deviation, and a kernel density estimate. This example
63 | supports estimates of either probability density functions (pdf) or
64 | cumulative distribution functions (cdf), using Vega’s density transform.
65 |
66 |
67 |
68 |
69 | A box plot summarizes a distribution of quantitative values using a set of
70 | summary statistics. Here, the boxes show the interquartile range (IQR),
71 | with the white bar indicating the median value. The thin lines
72 | (“whiskers”) currently show the extent of the minimum and maximum values;
73 | other values, such as whiskers extending 1.5 * IQR from each end of the
74 | box, are often used as well. See the violin plot example for an
75 | alternative approach.
76 |
77 |
78 |
79 |
80 | A violin plot visualizes a distribution of quantitative values as a
81 | continuous approximation of the probability density function, computed
82 | using kernel density estimation (KDE). The densities are additionally
83 | annotated with the median value and interquartile range, shown as black
84 | lines. Violin plots can be more informative than classical box plots.
85 |
86 |
87 |
88 |
89 | A plot of the top-k film directors by aggregate worldwide gross. Performs
90 | an aggregation of all directors, ranks them, and filters to only the top
91 | results, using the 'window' transform.
92 |
93 |
94 |
95 |
96 | A plot of the top-k film directors, plus all other directors, by aggregate
97 | worldwide gross. Unlike the previous example, this chart includes a
98 | category of all other directors aggregated together. The visualization
99 | spec first computes aggregates for all directors and ranks them. It then
100 | copies these ranks back to the source data using a lookup transform, and
101 | determines which directors belong in the “other” category before
102 | performing a final aggregation.
103 |
104 |
105 |
106 |
107 | A binned scatterplot is a more scalable alternative to the standard
108 | scatter plot. The data points are grouped into bins, and an aggregate
109 | statistic is used to summarize each bin. Here we use a circular area
110 | encoding to depict the count of records, visualizing the density of data
111 | points. For higher bin counts color might instead be used, though with
112 | some loss of perceptual comparison accuracy.
113 |
114 |
115 |
116 |
117 | Data point density calculation that can be have its parameters
118 | interactively changed. Depicts the density as both a raster ('heatmap')
119 | and isocontour plot.
120 |
121 |
122 |
123 |
124 | Although now deprecated, it is also possible to create contours with the
125 | trContour transform.
126 |
127 |
128 |
129 |
130 | A wheat plot is an alternative to standard dot plots and histograms that
131 | incorporates aspects of both. The x-coordinate of a point is based on its
132 | exact value. The y-coordinate is determined by grouping points into
133 | histogram bins, then stacking them based on their rank order within each
134 | bin. While not scalable to large numbers of data points, wheat plots allow
135 | inspection of (and interaction with) individual points without
136 | overplotting.
137 |
138 |
139 |
140 |
141 | A quantile dot plot represents a probability distribution by taking a
142 | uniform sample of quantile values and plotting them in a dot plot. It
143 | visualizes a representative set of possible outcomes of a random process,
144 | and provides a discrete alternative to probability density and violin
145 | plots in which finding probability intervals reduces to counting dots in
146 | the display.
147 |
148 |
149 |
150 | This example visualizes quantiles for a log-normal distribution that
151 | models hypothetical bus arrival times (in minutes from the current time),
152 | following the example of
153 |
157 | Kay, Kola, Hullman and Munson, 2016. If we are willing to miss a bus 2 out of 20 times, given 20 quantiles
159 | we can count up 2 dots from the left to get the time we should arrive at
160 | the bus stop.
161 |
162 |
163 |
164 | Click or drag on the chart to explore risk thresholds for arriving at the
165 | bus stop. Double-click to remove the threshold.
166 |
167 |
168 |
169 |
170 | A quantile-quantile (or Q-Q) plot visually compares two probability
171 | distributions by plotting a set of matching quantile values for both. For
172 | example, plotting the corresponding 1st, 2nd, 3rd, etc., percentiles for
173 | each distribution. Q-Q plots are often used to plot an empirical data
174 | distribution against a theoretical distribution. If the two distributions
175 | are similar, they will lie along a line; notable deviations from a line
176 | are evidence of different distribution functions.
177 |
178 |
179 |
180 | This example compares an empirical sample against two theoretical
181 | distributions. Change the input data source (samples from normal or
182 | uniform distributions) to observe how different samples compare with the
183 | theoretical distributions. The quantile transform produces quantile values
184 | for input data; the quantileUniform and quantileNormal expression
185 | functions produce the theoretical quantile values.
186 |
187 |
188 |
189 |
190 | Rather than showing a continuous probability distribution, Hypothetical
191 | Outcome Plots (or HOPs) visualize a set of draws from a distribution,
192 | where each draw is shown as a new plot in either a small multiples or
193 | animated form.
194 |
195 |
196 | This example – inspired by The New York Times – displays random draws for
197 | a simulated time-series of values (these could be sales or employment
198 | statistics). The noise signal determines the amount of random variation
199 | added to the signal. The trend signal determines the strength of a linear
200 | trend, where zero corresponds to no trend at all (a flat uniform
201 | distribution). When the noise is high enough, draws from a distribution
202 | without any underlying trend may cause us to “hallucinate” interesting
203 | variations. Viewing the different frames may help viewers get a more
204 | intuitive sense of random variation.
205 |
206 |
207 |
208 |
209 | A two-dimensional regression analysis models one data variable as a
210 | function of another. The resulting model produces a trend line that
211 | summarizes and extrapolates observed data. This example uses parametric
212 | regression models to predict IMDB users’ film ratings based on Rotten
213 | Tomatoes critics’ ratings.
214 |
215 |
216 |
217 |
218 | Locally-estimated regression
221 | produces a trend line by performing weighted regressions over a sliding
222 | window of points. The bandwidth parameter determines the size of the
223 | sliding window of nearest-neighbor points, expressed as a fraction of the
224 | total number of points included.
225 |
226 |
227 |
228 |
229 | Summary statistics for U.S. flight data, interactively grouped by time
230 | unit. Demonstrates use of the timeunit transform, in conjunction with the
231 | timeSequence and timeUnitSpecifier expression functions, to flexibly
232 | process and format date-time data.
233 |