Meteogram

author(s): Torstein Hønsi

HTML

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/datagrouping.js"></script>
<script src="https://code.highcharts.com/modules/windbarb.js"></script>
<script src="https://code.highcharts.com/modules/pattern-fill.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

<link href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">

<figure class="highcharts-figure">
    <div id="container">
        <div id="loading">
            <i class="fa fa-spinner fa-spin"></i> Loading data from external source
        </div>
    </div>
    <p class="highcharts-description">
        Chart showing meteorological data. This is an advanced example of using
        Highcharts to load data from an external API, and displaying the data
        using several custom visuals. The chart loads the data from a weather
        forecast website. After the data is parsed, the chart is generated, then
        the icons are added. In the end, the wind arrows are displayed.
    </p>
</figure>

<!--
<div style="width: 800px; margin: 0 auto">
    <a href="#http://www.yr.no/place/United_Kingdom/England/London/forecast_hour_by_hour.xml">London</a>,
    <a href="#http://www.yr.no/place/France/Rhône-Alpes/Val_d\'Isère~2971074/forecast_hour_by_hour.xml">Val d'Isère</a>,
    <a href="#http://www.yr.no/place/United_States/California/San_Francisco/forecast_hour_by_hour.xml">San Francisco</a>,
    <a href="#http://www.yr.no/place/Norway/Vik/Vikafjell/forecast_hour_by_hour.xml">Vikjafjellet</a>
</div>
-->

CSS

body {
    font-family:
        -apple-system,
        BlinkMacSystemFont,
        "Segoe UI",
        Roboto,
        Helvetica,
        Arial,
        "Apple Color Emoji",
        "Segoe UI Emoji",
        "Segoe UI Symbol",
        sans-serif;
    background: var(--highcharts-background-color);
    color: var(--highcharts-neutral-color-100);
}

#container {
    max-width: 800px;
    min-width: 360px;
    height: 310px;
    margin: 0 auto;
}

#loading {
    margin-top: 100px;
    text-align: center;
}

.highcharts-figure {
    min-width: 350px;
    max-width: 800px;
    margin: 1em auto;
}

.highcharts-description {
    background: light-dark(#f2f6f2, #323232);
    border-radius: 0 4px 4px 0;
    border-left: 2px solid light-dark(#1d6aff, #fff);
    font-size: 0.8rem;
    font-style: italic;
    padding: 8px 16px;
    margin: 2em 10px 1em;
}

JavaScript

/**
 * This is a complex demo of how to set up a Highcharts chart, coupled to a
 * dynamic source and extended by drawing image sprites, wind arrow paths
 * and a second grid on top of the chart. The purpose of the demo is to inpire
 * developers to go beyond the basic chart types and show how the library can
 * be extended programmatically. This is what the demo does:
 *
 * - Loads weather forecast from www.yr.no in form of a JSON service.
 * - When the data arrives async, a Meteogram instance is created. We have
 *   created the Meteogram prototype to provide an organized structure of the
 *   different methods and subroutines associated with the demo.
 * - The parseYrData method parses the data from www.yr.no into several parallel
 *   arrays. These arrays are used directly as the data option for temperature,
 *   precipitation and air pressure.
 * - After this, the options structure is built, and the chart generated with
 *   the parsed data.
 * - On chart load, weather icons and the frames for the wind arrows are
 *   rendered using custom logic.
 */

function Meteogram(json, container) {
    // Parallel arrays for the chart data, these are populated as the JSON file
    // is loaded
    this.symbols = [];
    this.precipitations = [];
    this.precipitationsError = []; // Only for some data sets
    this.winds = [];
    this.temperatures = [];
    this.pressures = [];

    // Initialize
    this.json = json;
    this.container = container;

    // Run
    this.parseYrData();
}

/**
 * Mapping of the symbol code in yr.no's API to the icons in their public
 * GitHub repo, as well as the text used in the tooltip.
 *
 * https://api.met.no/weatherapi/weathericon/2.0/documentation
 */
Meteogram.dictionary = {
    clearsky: {
        symbol: '01',
        text: 'Clear sky'
    },
    fair: {
        symbol: '02',
        text: 'Fair'
    },
    partlycloudy: {
        symbol: '03',
        text: 'Partly cloudy'
    },
    cloudy: {
        symbol: '04',
       ...