1.1.4 • Published 3 years ago

chesapeake-progress-charts v1.1.4

Weekly downloads
1
License
ISC
Repository
bitbucket
Last release
3 years ago

README

This is a D3-based module that draws specific charts for the Chesapeake Progress website of the Chesapeake Bay Program.

Installation and Use

Install through with npm install chesapeake-progress-charts --save

To display a chart:

<section><figure id="my-chart" style="width:600px; height:500px"></figure></section>
import { ChartCreator } from "@cbp/progress-charts";
import "@cbp/progress-charts/dist/progress-charts.css";

const chartDiv = document.getElementById('#my-chart');
const options = {
  data: { url: 'http://localhost/json/my-chart-data' }
};
const myChart = new ChartCreator(chartDiv, options);

Or, to initiate on multiple charts on the same page:

<section><figure class="chart" data-src-url="http://localhost/json/chart-1"></figure></section>
<section><figure class="chart" data-src-url="http://localhost/json/chart-2"></figure></section>
<section><figure class="chart" data-src-url="http://localhost/json/chart-3"></figure></section>
document.querySelectorAll(".chart").forEach( (item) => {
  new ChartCreator(item, {
    width: item.getBoundingClientRect().width,
    height: item.getBoundingClientRect().height,
    data: { url: item.dataset.srcUrl }
  });
});

Once the chart has been drawn, a loaded class is applied to the target dom's parent. In the above examples, the respective <section> elements.

ChartCreator

ChartCreator() method is initialized with two arguments: 1. el a DOM node into which the chart SVG will be drawn and 2. options an object with the following properties:

Options

PropertyTypeDefaultDescription
widthinteger960The width of the SVG chart to be drawn in pixels.
heightinteger500The height of the SVG chart to be drawn in pixels.
marginobject{ top: 45, right: 45, bottom: 50, left: 65 }an object of margin for the SVG.
dataobject{}An object that contains either a url property or a data property that is sent to the DataStore. See next section below.

Chart Data

If data.data exists, the chart will be built with those params. If data.url is passed, the app will fetch the JSON from the provided URL and then draw the chart.

PropertyTypeDescription
dataarrayA JSON array of chart data objects.
urlstringA url that returns a JSON array of chart data objects.

When multiple chart data objects are passed in the JSON array, users can toggle between datasets. When segment labels match across datasets, transitions are applied to indicate change.

In order for the UI to toggle datasets, button elements with class chart-switcher must exist within a sibling node to the target chart element. A button can trigger the new dataset with a value attribute set to the respectively chart data object's array index.

<section>
  <div>
    <button value="0" class="chart-switcher activeView">First Dataset</button>
    <button value="1" class="chart-switcher">Second Dataset</button>
  </div>
  <figure class="chart-div"></figure>
</section>
[
  chartDataObject,
  chartDataObject
]

The app is capable of drawing Staked Bar, Line, Pie, and Doughnut charts. Each has specific data properties it expects:

Base Charts

PropertyTypeDefaultDescription
urlTitlestring""A slugified string that is used as an identifier for the chart and to associate the legend dom node.
typestring""Determines the type of chart to draw. Options are stacked bar chart, line chart, pie chart or doughnut chart.
showLegendstring""Whether or not to draw a legend for the chart. Yes to draw, No or empty to not draw.
prependToValuestring""Characters prepended to the value on tooltips.
appendToValuestring""Characters prepended to the value on tooltips.
overlayarray[]An array of chart data objects used to overlay a line chart onto a bar chart.

Scatterplot Charts

Inherits all the data properties from Base Charts

PropertyTypeDefaultDescription
xAxisLabelstring""Text that appears below the x-Axis.
yAxisLabelstring""Text that appears to the left of the y-Axis.
maxYfloat1.1 times the largest value in the dataset or stack.The top range of the Y-axis.
minYfloat0The bottom range of the Y -axis.
goalarray[]An array of goalline objects: {goalName: string, goalValue: float, goalColor: string}. goalName appears in the tooltip. goalColor can be any valid css color string (hex, rgb, hsl, etc).

Stacked Bar Charts

Inherits all the data properties from Scatterplot and Base Charts

PropertyTypeDefaultDescription
stackedBarDatasetarray[]An array of stack objects, each object includes the stack for a given x-Axis bar. The object must include a label property for the x-Axis column and then a key-value pair for each piece of the stack.
stackedBarSegmentsarray[]An array of segment objects, one object has the settings for each stack bar: label and fillColor.

For example, the following would be used for a bar chart from 2010 - 2013 showing the number of Oak and Maple trees planted. Oak is shaded in blue and maple in orange.

{
  "stackedBarDataset": [ 
    { "label": "2010", "Oaks Planted": "12", "Maples Planted": "7" }, 
    { "label": "2011", "Oaks Planted": "18", "Maples Planted": "33" },
    { "label": "2012", "Oaks Planted": "14", "Maples Planted": "19" },
    { "label": "2013", "Oaks Planted": "20", "Maples Planted": "27" }
  ],
  "stackedBarSegments": [
    { "label": "Oaks Planted", "fillColor": "#083a7c"},
    { "label": "Maples Planted", "fillColor": "#f4911e"}
  ]
}

Line Charts

Inherits all the data properties from Scatterplot and Base Charts

PropertyTypeDefaultDescription
labelsarray[]The x-Axis domain.
datasetarray[]An array of line objects. Currently only 1 line object is accepted.

For example, the following would be used to show the number of trees planted from 2010 - 2015.

{
  "labels": ["2010", "2011", "2012", "2013", "2014", "2015"],
  "dataset": [
    {
      "label": "Trees Planted",
      "data": [117,227,167,177,102,211]
    }
  ]
}

Pie and Doughnut Charts

Inherits all the data properties from Base Charts

PropertyTypeDefaultDescription
dataarray[]An array of pie slice objects each with value, color, and label properties.

For example, the following would be used to show the percentage split between Oak, Maple, and Pine trees planted in a given year. Oak is shaded blue, Maple is shaded orange, and Pine is shaded green.

{
  "data": [
    {"value": 24, "color": "#083a7c", "label": "Oak"},
    {"value": 36, "color": "#f4911e", "label": "Maple"},
    {"value": 40, "color": "#84a540", "label": "Pine"}
  ]
}

Legends

If showLegend in the chart data object is set ot true, the app will attempt to draw a legend if the necessary dom node exists. The node must have an id attribute of [data[0].urlTitle]-legend.

Examples

Stacked Bar with Two Datasets and Line Overlay

A line chart overlaid on a stacked bar chart with 2 toggles and legend:

http://localhost/json/chart-data

[
  {
    "urlTitle": "trees-planted-in-maryland",
    "showLegend": "Yes",
    "overlay": [{
        "urlTitle": "planting-volunteers",
        "type": "line chart",
        "yAxisLabel": "Volunteers",
        "labels": ["2010", "2011", "2012"],
        "dataset": [
          {
            "label": "Volunteers",
            "data": [46, 47, 70]
          }
        ]
      }],
    "type": "stacked bar chart",
    "yAxisLabel": "Trees Planted",
    "goal": [{"goalName": "Target to plant", "goalValue": 76, "goalColor": "#000"}],
    "stackedBarDataset": [
      {
        "label": 2010,
        "Oak": 22,
        "Maple": 32,
        "Pine": 16
      },
      {
        "label": 2011,
        "Oak": 64,
        "Maple": 23,
        "Pine": 43
      },
      {
        "label": 2012,
        "Oak": 29,
        "Maple": 18,
        "Pine": 53
      }
    ],
    "stackedBarSegments": [
      {"label": "Oak", "fillColor": "#083a7c"},
      {"label": "Maple", "fillColor": "#f4911e"},
      {"label": "Pine", "fillColor": "#84a540"}
    ]
  },
  {
    "urlTitle": "trees-planted-in-virginia",
    "overlay": [{
      "urlTitle": "planting-volunteers",
      "type": "line chart",
      "yAxisLabel": "Volunteers",
      "labels": ["2010", "2011", "2012"],
      "dataset": [
        {
          "label": "Volunteers",
          "data": [46, 47, 70]
        }
      ]
    }],
    "type": "stacked bar chart",
    "yAxisLabel": "Trees Planted",
    "goal": [{"goalName": "Target to plant", "goalValue": 134, "goalColor": "#000"}],
    "stackedBarDataset": [
      {
        "label": 2010,
        "Oak": 36,
        "Maple": 43,
        "Pine": 19
      },
      {
        "label": 2011,
        "Oak": 44,
        "Maple": 43,
        "Pine": 28
      },
      {
        "label": 2012,
        "Oak": 58,
        "Maple": 37,
        "Pine": 31
      }
    ],
    "stackedBarSegments": [
      {"label": "Oak", "fillColor": "#083a7c"},
      {"label": "Maple", "fillColor": "#f4911e"},
      {"label": "Pine", "fillColor": "#84a540"}
    ]
  }
]

chart.html

<article>
  <h1>Number of trees planted in Maryland and Virginia.</h1>
  <div>
    <button value="0" class="chart-switcher activeView">Maryland</button>
    <button value="1" class="chart-switcher">Virginia</button>
  </div>
  <figure class="chart" id="trees-planted-chart" data-src-url="http://localhost/json/chart-data"></figure>
  <div class="legend" id="trees-planted-in-maryland-legend"></div>
</article>

chart.js

import { ChartCreator } from "@cbp/progress-charts";
import "@cbp/progress-charts/dist/progress-charts.css";

const chartDiv = document.getElementById('#trees-planted-chart');
const myChart = new ChartCreator(chartDiv, {
  width: 900,
  height:550,
  data: {url: chartDiv.dataset.srcUrl}
});

Line Chart

A basic, simple line chart, showing CSS to override line and dot color.

http://localhost/json/chart-data

[
  {
    "urlTitle": "total-trees-planted",
    "showLegend": "No",
    "prependToValue": "",
    "appendToValue": " millions",
    "type": "line chart",
    "yAxisLabel": "Trees Planted Nationally (millions)",
    "goal": [
      {"goalName": "Target", "goalValue": "124", "goalColor": "#01212e"}
    ],
    "labels": ["2014", "2015", "2016"],
    "dataset": [
      {
        "label": "Trees Planted",
        "data": [98, 81, 109]
      }
    ]
  }
]

chart.html

<article>
  <h1>Number of trees planted nationally.</h1>
  <figure class="chart" id="trees-planted-chart" data-src-url="http://localhost/json/chart-data"></figure>
</article>

chart.css (.scatterplot-chart is automatically added to the SVG drawn)

.scatterplot-chart {
  --primaryColor: #766290;
}

chart.js

import { ChartCreator } from "@cbp/progress-charts";
import "@cbp/progress-charts/dist/progress-charts.css";

const chartDiv = document.getElementById('#trees-planted-chart');
const myChart = new ChartCreator(chartDiv, {
  width: 900,
  height:550,
  data: {url: chartDiv.dataset.srcUrl}
});

Contribution

  1. From a terminal in the path where you'd like the source files to be created, type git clone https://wwhorton@bitbucket.org/wwhorton/progress-charts.git
  2. This should create a progress-charts directory. Change to that directory and type npm install to install all of the necessary dependencies.
  3. Type npm run start to launch the development server, or npm run watch to have webpack monitor the source files for changes and rebuild as necessary. The development server will typically handle rebuilds as needed, but if you don't need an actual webserver the watch script is sufficient.
  4. npm run build will do a single rebuild of all source files.

Contribution guidelines

Tests

  • Write unit tests for each discrete JS script. Give them the same name as the script to be tested but insert .test., i.e. chart-ui.test.js.
  • We're aiming for 100% test coverage. You can check coverage by running npm run coverage.
  • Run tests in watch mode using npm run test, or once using npm run testonce. Feel free to tweak the test reporting using the various switches available for the mocha-cli, but preferably after creating a new npm script and copying the existing test command.
  • Keep tests in the same directory as the script being tested.
  • Helpful links:

Development

We're using Babel so that we can write ES6 JavaScript using the new module features, among other reasons. Err on the side of more modules than fewer; it's all going to be packed into flat, minified distribution files by Webpack so any performance impact from numerous modules won't be relevant. For ease of use, try to use a flatter directory structure, however.

Keep JavaScript in the JS directory, HTML in the parent directory ('/src'), sass in the sass directory, and any miscellaneous resources in the resource directory. Again, these will be optimized by Webpack so the more important issue on the dev side is organization. The directory names are important because they will be referenced in the Webpack config file, but subdirectories don't matter; they'll be picked up automatically.

1.1.4

3 years ago

1.1.1

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.0

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago