@statistikzh/charts
v0.5.0
Published
## Basic Usage
Readme
Charts
Basic Usage
Each chart function takes an object with the following properties:
el: The root element where the chart will be rendered into.data: A list of data objects that will be rendered. Each object must be a single observation.options: Options for the chart (depends on the chart type).
TypeScript doesn't work yet. You can look at the src/types.ts folder to see the available options.
import { BarChart } from "@statistikzh/charts";
BarChart({
el: document.querySelector("#chart"),
data: [],
options: {},
});TypeScript
The library is written in TypeScript. The types are not yet fully implemented. You can look at the src/types.ts file to see the available options.
Sadly there are quite a few of type issues that are not solved yet.
Used libraries
We use redux as a state management solution. Every chart contains a separate redux store. The store contains the complete state of each chart.
Every element that lives inside the root SVG element is created with d3 and lit-html. lit-html provides easy solutions to improve the performance.
As a rule of thumb:
- Use d3 for all elements that are bound to data (lines, bars, etc.).
- Use lit-html for container, group, once only elmements etc.
The tooltip and the legend are web components created with lit.
Architecture
Each chart type is exported as a single function. Each chart can be called with the same object as an argument.:
BarChart({
el: document.querySelector("#chart"),
data: [],
options: {},
});The options can vary from type to type. Look up the src/types.ts file for the available options.
Chart creator function
The makeChart function contains shared functionality for all chart types. Each chart type should be created with this function.
export const BarChart = makeChart(
optionsSlice, // redux slice that contains the options of this chart type
constructOptions, // function that merges the default options with the user options
renderBarChart, // function that renders the components of the chart
);It contains the following parts:
- Creating and subscribing to the redux store
- Building the chart context object
- Creating the root svg element
- Rendering the chart, legend and tooltip with lit-html
- Initializing the service controller, with…
- LayoutObserver
- ChartResizeObserver
- Events
- Preparing and providing cleanup function
Chart context
The chart context object contains everything that needs to avaiable "globally" in the chart.
At the moment it contains:
store: The redux store. Used to access the state and dispatch actions.services: Service controller. Used to handle all sorts of effects.
The chart context is created in the makeChart function and is passed to the specific chart render function. From there it is passed to every componend or other function that needs to access "global" state.
Example: The functions of src/lib/scales.ts determine the scale type, domain etc. based on the context.
Components
The components are the building blocks of every chart type and live in the src/components directory. Every component receives the chart context as an argument and returns either an HTMLElement or a TemplateResult. The returned value is then rendered inside the root svg element.
Every componenet will be rendererd after each state change. To improve the performance and to prevent unnecessary re-renders a single component can be wrapped with the guard directive.
Services
Services are used to handle all sorts of logic / effects that can't be solved by rendering alone. Each service can hook into lifecycle events of the chart. They're described in the src/services/services.ts file.
LayoutObserver
./src/services/layoutObserver.ts
The layout observer handles the calculation of the margins thar are needed in order to display all parts inside the viewport of the chart.
This is necessary because we don't know how an axis label is. This depends on the defined format specifier, the tick values the axis renders and the domain.
After every render the observer checks if any of the elements overflows the viewport by retrieving the bounding box (getBBox()).
It would be to expensive to that with every single element. If an element has to be observed, the observeLayout directive can be applied on it.
ChartResizeObserver
./src/services/chartResizeObserver.ts
The chart resize observer simply creates a ResizeObserver and observes the root element of the chart.
When the width changes, the dimeinsions slice of the state will be updated.
This is only applied when the responsive option flag is set to true.
Events
The event handling is still a very rough implementation. The event service exposes a removeListener and a addListener method for consumers outside of the chart to use. Inside the chart the getListeners method can be used the retrieve the listeners for a specific event type. It is only used by the tooltip at the moment.
