Chart Annotations With JavaScript
I use Google Analytics daily. One amazing feature I wanted to emulate for myself was the ability to add annotations to charts. This tutorial will cover how to add basic annotations to ZingChart using JavaScript.
We have been covering using ZingChart's API in the past few blog posts. Check them out below to get caught up:
HTML
This demo was created with the ZingChart selection tool module. The selection tool allows you to exhibit an active state to each node clicked on (aka changes the node color when clicked on). To include the module, add this script to your header:
<script src="cdn.zingchart.com/modules/zingchart-selection-tool.min.js"></script>
To start this demo out, we're going to need a normal <div>
with an ID so we can reference this later in our CSS & JavaScript.
We will also need a <form>
element with two <input>
elements. One will take the type of "text" for a text field & the other will take the type of "submit" for a submit field. This will be where we submit our annotations.
<div id="myChart">
<form id="addNote">
<input type="text">
<input type="submit">
</form>
</div>
CSS
There are three significant sections to our CSS:
First, we need to define a height & width to our chart container <div>
. Our chart will not render otherwise.
#myChart {
height: 500px;
width: 600px;
}
Second, our form <form id="addNote">
will need to be hidden by default (we will make it visible later upon node click). We can use opacity to do so:
#addNote {
opacity: 0;
}
We also want our form <form id="addNote">
to have a class of 'open' in our CSS. We can dynamically add this class with JavaScript later (will occur when a user clicks a node). This 'open' class will have an opacity value of 1 to make our form <form id="addNote">
visible.
#addNote.open {
opacity: 1;
}
JavaScript
Our JavaScript will start inside of our chart configuration. We mentioned the selection tool module earlier. To use this, we will need to add two attributes into our plot
attribute:
plot: {
selectionMode: 'multiple',
selectedState: {
backgroundColor: 'black'
}
}
selectionMode: 'multiple'
defines the ability to select multiple nodes. Within selectedState
we are able to define a backgroundColor
of our selected nodes.
The next step will be to store our chart render method in a variable. This will allow us to "bind" ZingChart events to our chart in a legible fashion.
var chart = zingchart.render({
id: "myChart",
data: myConfig
});
There are two very important parts of this demo. One happens on a chart node click & the other happens when we submit text to our form element for an annotation.
Chart Node Click Function
In this node click function, we will store chart x and y coordinates from our chart node (we will use this to position our annotation later) into variables & add a class of "open" to our form
element to make it visible.
We are going to start by grabbing our form
element from the DOM.
// Grabs the <form> element from the DOM
var form = document.querySelector('#addNote');
Next, we will define two variables xValue
& yValue
to store our node x and y coordinates in.
/ Creates variables that will hold node_click x & y coordinates
var xValue = 0;
var yValue = 0;
Finally, we will add our function. We can use the "chart" variable we created from our render method earlier.
We will bind this variable to a ZingChart API event. There is a built-in 'node_click' event built into ZingChart we can use. This ZingChart API event will take a callback function, which will take in an event (e) as a parameter. This is structured almost identically to adding event listeners. The node_click
event (e) will give us information about our nodes including x and y coordinate values (if specified).
This function will create two variables: nodeValueX
& nodeValueY
. These two values will take in the x and y coordinate values of our node_click event.
We will then re-assign these values to our original xValue
& yValue
variables so that we can use them for our annotation position later. Finally, this function will also use classList.add
to add a class of "open" to our <form>
element.
chart.bind('node_click', function(e) {
// These variables store node_click event (e) x and y coordinates
var nodeXValue = e.x;
var nodeYValue = e.y;
// Re-assigns variables to original xValue and yValue variables
xValue = nodeXValue;
yValue = nodeYValue;
// Adds open class to our <form> element
form.classList.add('open');
});
Form Submit Function
We grabbed the <form>
element from the DOM earlier. We will now be attaching an event listener to fire a function on the "submit" event. Four major things will happen when a user submits the <form>
element:
-
Preventing a
<form>
submit without a value usinge.preventDefault()
. -
Grabbing the
<input>
text value from the DOM & assigning it to a variable. -
Creating an annotation with the
zingchart.exec()
API method. Using the built-in 'addobject' method, we can add and style a ZingChartlabel
object as our annotation. Thislabel
will take in the x & y coordinate variables we created uponnode_click
earlier. This ensures ourlabel
is added to the node clicked. -
Removing the "open" class from our
<form>
element usingclassList.remove()
// This event listener function fires when our <form> element is submitted
form.addEventListener('submit', function(e) {
// Prevents a <form> element submit without a value
e.preventDefault();
// Grabs the <input> text value from the DOM and assigns to a variable
var note = form.querySelector('input[type="text"]').value;
// Creates a ZingChart label object from the <input> text value submitted
zingchart.exec('myChart', 'addobject', {
type: 'label',
data: {
text: note,
x: xValue,
y: yValue,
backgroundColor: '#eee',
padding: [10, 25],
borderRadius: 4,
}
});
// Removes open class form <form> element
form.classList.remove('open');
})