Zoomdata Version

Creating a Custom Chart

OVERVIEW

Starting with Zoomdata v2.2, the Zoomdata application and custom chart templates are powered by an enhanced API. Zoomdata charts and custom charts use the controller object to integrate with Zoomdata. Using the controller object ensures that Zoomdata interacts properly with your chart in embedded contexts outside of the Zoomdata client application. For information about upgrading your existing custom Zoomdata chart template, see Migrating Custom Chart Templates .

This topic explains how to build a custom chart in Zoomdata using the ECharts 2.0 library . The final sample chart is available for download from Zoomdata's Github repo . You will have to adapt the steps while working on your own custom chart template.

Architecture of Integration with Zoomdata

Creating a custom chart in Zoomdata is essentially a process of integrating JavaScript chart code with Zoomdata. The key object used to integrate chart code with Zoomdata is the controller object. The controller object serves two purposes:

  • Supply your chart with data and parameters from Zoomdata, like groups, metrics, and colors
  • Allow Zoomdata to trigger events in your chart, like clearing and resizing

The controller object includes the following important members and methods, some of which you must implement to integrate your chart code into Zoomdata or to create a new chart for the Zoomdata gallery of charts.

Important Members and Methods of controller

While developing a custom chart or integrating a custom chart into Zoomdata, you will probably use some or all of the following members and methods of the controller object, depending on your design goals.

  • element contains the HTML DOM element in which the chart rendered, whether in the Zoomdata application or in a custom embedded setting. This member should be treated as read-only.
  • dataAccessors[] contains one member for each chart variable, such as Group , Subgroup , Y-Axis Metric , used by the chart. The members are named the same name as the chart variable, so a chart with variables Y-Axis Metric and X-Axis Metric will have two dataAccessors: dataAccessors['Y-Axis Metric'] and dataAccessors['X-Axis Metric'] . These dataAccessors each contain methods to identify their type, such as attribute or metric. They also contain methods for identifying their current value. Y-Axis Metric , for instance, might be set to a userincome field.
  • update(data, progress) is called by Zoomdata whenever new data is available for the chart. The data is passed in the data parameter, and the percentage of data passed so far is indicated by the progress parameter. You must implement this method in your code.
  • resize(height, width) is called by Zoomdata whenever the DOM element containing the chart is resized. New height and width are passed in the parameters. You must implement this method in your code.
  • createAxisLabel({}) is used to render a selectable access label when the chart is rendered in the Zoomdata environment. When the chart is embedded in a context outside of the Zoomdata application, this method does not have any effect. The chart's dataAccessors do provide the information necessary to render controls in an embedded environment.
  • menu.show({}) and .hide() are used to render and hide a context menu when the chart is rendered in the Zoomdata environment. When the chart is embedded in a context outside of the Zoomdata application, this method does not have any effect. The chart's dataAccessors do provide the information necessary to render controls in an embedded environment.
  • tooltip.show({}) and .hide() are used to render and hide a tooltip when the chart is rendered in the Zoomdata environment. When the chart is embedded in a context outside of the Zoomdata application, this method does not have any effect. The chart's dataAccessors do provide the information necessary to render controls in an embedded environment.

STEPS FOR CREATING A CUSTOM CHART TEMPLATE

These high-level steps for creating a custom chart template each may require adaptation for your particular needs. They will serve as a guide your work.

  1. Select blank template .
    If you want to start with a Zoomdata chart template and customize it, the following steps will provide useful guidance even where they are not directly applicable.
  2. Import and include any necessary libraries
  3. Prepare the DOM for Rendering
  4. Configure Zoomdata to Supply the Necessary Data
  5. Add Controls to the Chart
  6. Code the Rendering of the Chart
  7. Enable the Chart to Resize based on changes to its DOM element
  8. Adding Tooltips
  9. Adding Context Menus

SELECTING A BLANK TEMPLATE

Use these steps to open the Chart Studio, select a template, and begin your work.

  1. Log in to the Zoomdata application.
  2. Select Settings and then select Chart Studio .
  3. Under Create a New Chart From , select the Blank template option.
    When you select a chart template, the Add New Chart dialog opens. It contains a default list of chart variables for the new chart.


    This guide refers to an example using a simple chart built using ECharts 2.0. You will have to adapt these steps for your chart.
  4. Select default values for each the variables. For example, you will indicate which data field is the default Group By . As you begin to build the chart, you can change the available chart variables and their default values, but for now, provide defaults as applicable.
    • Enter a Name for the chart.
    • Select a data source from the list of Sources to use with your template during the development of your custom chart template. You will be able to configure other data sources to work with the custom chart template later
    • Select a Group By field and a Group By Limit , and configure a Group By Sort .
      In our example, we use the name Simple Bar Chart . You have to select a field to be the default value for Group By . The fields available to you depend upon your data Source .
  5. Select Accept to confirm your work and continue. The dialog closes and the Chart Studio opens with a code window and a preview window.

The Blank template initializes with some statements pre-populated:

  • add an axis label to the chart
  • log the HTML element to which the chart is attached
  • an empty controller.update() method, which you will implement in subsequent steps
  • an empty controller.resize() method, which you will implement in subsequent steps

Continue to the following steps to build the sample chart.

Back to top

IMPORTING AND INCLUDING ANY NECESSARY LIBRARIES

Zoomdata ships with a number of charting libraries already imported for use. To view a list of available libraries or to include them in your chart project, see Including a Library in Your Chart . Your chart may require charting libraries other than those included by default with Zoomdata charts. You can import new charting library for use with Zoomdata and then include the library in your charting project.

In our example, we include the ECharts library (version 3.2.3) found at http://echarts.baidu.com/download.html . To follow the example, you must download this library, import it to Zoomdata, and then include it in your charting project using the links above.

Back to top

PREPARING THE DOM FOR RENDERING

Every charting library expects different steps taken to prepare for rendering a chart. It is important to understand how your charting library works. Typically, you need to perform these steps to prepare the DOM for rendering.

  1. Define the DOM element for rendering
  2. Instantiate the chart
  3. Link the chart to the intended DOM area

In our example chart, we carry out these steps in the following chunk of code. Your code will depend on the library that you use and the design decisions that you make.

// Create a DOM element to contain the chart
var chartContainer = d3.select(controller.element)
.append('div')
.attr('class', 'chart-container')
.style('width', '100%')
.style('height', '100%')
.node();

// Instantiate the chart in the chart container
var chart = echarts3.init(chartContainer);

The first statement initiates a variable to hold the DOM element using the D3 library. Note:

  • Zoomdata populates controller.element with the DOM element in which the visualization is to be rendered.
  • We do not use controller.element itself because we may want to adjust it and doing so could affect the outer, holding element and would affect the broader application environment.
  • The code above then creates a div inside the DOM element from controller.element ; we will use this div for rendering our chart.
  • The div's width and height are set to 100% so that the DOM element completely fills whatever space is allowed for it by its parent element, held by controller.element .

The second statement uses the ECharts library to instantiate an empty chart in our chart container.

Back to top

CONFIGURING ZOOMDATA TO SUPPLY THE NECESSARY DATA

Configuring Zoomdata to supply the data necessary for your chart requires two stages. First, you must set up the chart variables in that your chart will use. Then you must configure your data source with default fields (columns) to be used to supply those variable with values.

Setting Up Variables in Chart Studio

Your chart template must be prepared to receive data from Zoomdata using variables that your chart can access. Zoomdata allows charts to query data in either a grouped or ungrouped manner, but not both. A grouped variable uses data grouped by an attribute, whereas ungrouped variables keep the column's rows on the table as a distinct data items, without grouping them. By default, your chart queries data as groups. If you select UnGrouped , you will lose your grouped variables; if you re-select Grouped , you will lose your ungrouped variables.

To set up grouped variables:

  1. Select Manage and then select Variables . By default, each chart has a single preconfigured variable called Group By . You can reconfigure Group By or select +Add to create a new variable.
  2. For each variable that you need to create:
    1. Provide a name for the variable in the field that says, by default, Group By , Group By 2 , Group By 3 , or so forth.
      In our simple bar chart example, we name our chart variables Group By and Metric . In our bar chart, Group By will provide the names of the bars, and Metric will provide their height.
    2. Select a variable type using the pull-down menu. The default type is Group . Depending on the type of variable you select, you may be prompted to provide a Group Type , Metric Type , or another variable type. You may also be prompted to select whether the group is the Color Attribute , that is, the attribute by which the chart is color coded.
    3. When you have configured all necessary variables, select Accept .
      Remember, these chart variables do not refer directly to your data. Instead, they refer to the parts of your chart used to visualize data, like X-Axis. The contents of a chart variable like X-Axis might be Product Department, Zip Code , or User Gender , however your end user chooses.

In our simple bar chart example, we create two chart variables: Group By and Metric , as seen below.

Continue to the following steps to configure your data source to supply data to your chart.

Configuring Your Data Source to Supply Data to Your Chart

For a data source to work with a chart, it must be configured to supply data to the variables expected by your chart.

  1. Select Setting s and then select Sources .
  2. Select the data source that you are using to test your chart template and then select Charts .
  3. Select the Custom tab and then scroll through the list to find your custom chart template.
  4. Select your custom chart template. A dialog opens showing a list of all the variables required by your chart template, as determined in the steps for Setting up Variables in Chart Studio .
    Our simple bar chart example requires the following fields, which are based on the chart variables that we configured in Setting Up Variables in Chart Studio .

    If you recall, Metric was not listed when we first saw these options. That is because we had not yet created it as a chart variable.
  5. Use the pull-down menus to assign a field from your data source to each variable. Use the fields to assign each required value such as Group Limit .
  6. Select Save when you are done.
  7. Select Setting s and then select Chart Studio , and then select your chart template to return to the Chart Studio and resume editing your chart template.

Continue to the following steps to code your chart to render with data from Zoomdata.

Back to top

ADDING CONTROLS TO THE CHART

Zoomdata makes it easy to add controls to your custom chart so users can change the settings of chart variables. These controls make it possible for users to switch attributes, metrics, and so forth.

To add or remove controls to your chart, you need to return to Chart Studio by selecting Setting s and then Chart Studio . In Chart Studio, you can add different types of control:

  • Sidebar controls and time bar - control filters, sorting, colors, and the time range of displayed data
  • Axis Labels - used to pick groups and metrics displayed by a chart

Adding, Removing, or Configuring Sidebar and Time Bar controls

Zoomdata enables you to add, remove, and configure controls for your chart when it is used in the Zoomdata client application. These controls are part of the Zoomdata client application and only appear when the chart is used in the Zoomdata client app.

To add, remove, or configure sidebar and time bar controls:

  1. Select Manage and then select Controls .
    The Manage Controls dialog opens.
  2. Select or unselect controls to match the configuration that you need.
  3. Select Accept to confirm your choices, or Close to close the dialog without confirming them.

Adding and Configuring Axis Labels

Zoomdata enables you to add and configure axis labels in your chart when it is used in the Zoomdata client application. These labels can be used to identify and select the data displayed in the chart. These labels are part of the Zoomdata client application and only appear when the chart is used in the Zoomdata client app. The Zoomdata Javascript client library used for embedding charts does provide the data needed to create similar components in custom applications.

To add and configure axis labels:

For each axis label, add the following code,

controller.createAxisLabel(
{
picks: ' Group By ',
position: ' bottom ',
orientation: ' horizontal ',
popoverTitle: ' Group '
}
);

in which:

  • picks designates the chart variable to be displayed and selected by the label. Replace Group By with a chart variable from your variable configuration.
  • position designates the position of the label relative to the chart. Options are top , bottom , left , and right .
  • orientation designates the orientation of the label. Options are horizontal and vertical . For labels positioned on the left or right, these orientation options control whether the label faces inward or outward from the chart.
  • popoverTitle designates the title of the picker. This optional parameter, if provided, overrides the name of the chart variable provided in picks .

In our example code, we have two chart variables, both of which we want to expose to chart viewers so that chart viewers can click them and change the data presented by each. The code for configuring these variables follows.

controller.createAxisLabel(
{
picks: 'Group By',
position: 'bottom',
orientation: 'vertical',
popoverTitle: 'Attribute'
}
);

controller.createAxisLabel(
{
picks: 'Metric',
position: 'left',
orientation: 'vertical',
popoverTitle: 'Metric'
}
);

Back to top

CODE THE RENDERING OF THE CHART

To code your chart to render, you need to return to Chart Studio by selecting Setting s and then Chart Studio .

Zoomdata calls the update(data, progress) method each time new data becomes available. The data is passed into update in the parameter data . The parameter progress is a number from 0 to 100 indicating the percent completion of the data sharpening and delivery process. A lot depends on your charting library.

In our example code, no pre-rendering or initial rendering is required by the ECharts library. We need only provide ECharts with its expected parameters, and it will do the rest. Each time we give the same chart new data, it manages the transformation of the chart to represent the new data.
controller.update = function(data, progress) {
// Receiving Data

// This method is from the ECharts library
chart.setOption(
{
xAxis: {
type: 'category',
data: categoryAxisData(data)
},
yAxis: {
type: 'value'
},
series: [
{
type: 'bar',
data: valueAxisData(data)
}
]
}
);
};

In the sample above, note:

  • The method called, setOption() , is an ECharts method. The library that you use will have its own methods and required parameters.
  • categoryAxisData() and valueAxisData() are methods that we create to get relevant bits of data from the data parameter passed to update() by Zoomdata. We could put that code here, but the best practice is to modularize it.

Understanding How Zoomdata Supplies Data to a Chart

Whenever new data is available to your chart, Zoomdata passes that data as an array of objects to your controller.update(data, progress) method. At the start of your update() method, you can insert a statement like

console.log("data: ", data);

to log the contents of data for review.

In your chart, this data can be accessed using expressions like data[0].current.count or data[0].group[0] . If you change the chart variable settings using the axis labels that you created , you will see the data available in the packets change.

Switching Metric from Volume (called 'count' in our code and data) to Price:sum has added a metric to our bundle of data, and changing the Group By parameter from Product Group to User City has changed the type of value that we see in group .

Getting Data About Your Chart's Current Settings

It is not really a viable option to manually glean data that you need from the data array that Zoomdata passes to your update() function. This approach is too limiting because if your chart's viewer switches the metric from, for example, Volume ( count ) to Price:sum , your expression data[0].current.count will no longer be the data that your user wants.

Zoomdata's controller object contains a member, dataAccessors[] , to deal with this problem. The dataAccessors[] array contains an member object for each chart variable in variables configuration. Each member also contains methods for using that dataAccessor and identifying the data to which it refers.

Our example simple bar chart has two chart variables: Group By and Metric . Consequently, controller has two items in its dataAccessors array:
  • controller.dataAccessors['Group By']
  • controller.dataAccessors['Metric']

For ease of use, you can create a variable for each dataAccessor. Our example simple bar chart uses the following code.

var groupAccessor = controller.dataAccessors['Group By'];
var metricAccessor = controller.dataAccessors['Metric'];

Each dataAccessor has a method called raw(datum) . When you pass raw() a data item from the data array, raw() extracts the correct bit of data based on the dataAccessor's current value, which is based on the chart variable's current setting. Thus, if the chart viewer selects user income for the current Y-Metric , controller.dataAccessor['Y-Axis'].raw(data[0]) returns the user income from the first data object in the data array.

Getting data from Zoomdata in the Visualization Framework is pretty straightforward, as we've seen above. What to do with your data once you have gotten it - that's a different matter. Different charting libraries expect data in different formats. As a result, it's not really possible to make a one-size-fits-all set of steps to guide you through that process. The following information based on our simple bar charts example, using the ECharts library, may be of some assistance.

An Example of Supplying Data to a Chart

Our example simple bar chart uses the ECharts library to do its rendering. To render a bar chart, ECharts wants a few bits of data. We supplied that data using the functions categoryAxisData() , to identify the groups, which we have listed on the X axis, and valueAxisData() , to identify the values to present and thereby the calculated bar heights and scales.

We pass the full data array to categoryAxisData() , which was passed into update() . We use the array's map() function to create an array of the names of all the aggregation included in the data. The name of each aggregation is retrieved by using the correct dataAccessor.

function categoryAxisData(data) {
return data.map(function(d) {
return groupAccessor.raw(d);
});
}

Using console.log() to log groupAccessor.raw(d) will show the names of aggregations in the attribute currently selected by the chart variable Group By , which is indicated by groupAccessor . For instance, if we were grouping by an attribute called color , the aggregations might be red , purple , blue , green , yellow , and orange . The dataAccessor method raw() for that chart variable would return red , purple , blue , green , yellow , and orange as data for those aggregations came in. Our function call, data.map() only builds an array from those values and then returns the array.

For axis values, ECharts wants a slightly more complicated object. For each aggregation, ECharts wants:

  • name - so it can map the data to a bar
  • value - so it knows how large to make each bar

Additionally, we add into the object a model , which is really just the original data from Zoomdata. We add this model into the object we give ECharts so that when ECharts renders a bar, we will be able to access the original data through the bar. This object is important for rendering tooltips and context menus for each bar.

function valueAxisData(data) {
return data.map(function(d) {
return {
name: groupAccessor.raw(d),
value: metricAccessor.raw(d),
model: d
};
});
}

We use the methods shown above, essentially, to repackage the data provided by Zoomdata into the format expected by ECharts. That, and calling EChart's chart rendering function, setOption() , is the heart of rendering a chart using data from Zoomdata. Subsequent steps will explain how to render tooltips and context menus in the Zoomdata environment, as well as how to enable your chart to resize when its DOM element changes size.

Back to top

ENABLE THE CHART TO RESIZE BASED ON CHANGES TO ITS DOM ELEMENT

Your chart needs to be able to resize itself to respond to changes in the size of its DOM element. Zoomdata calls the controller.resize() method when it needs to resize your chart. Accordingly, you must provide a definition for this method. When Zoomdata calls controller.resize() , it passes a new height, width, and size string. The size string is used to describe non-desktop screen sizes. You can use it to make decisions about alternate renderings of your chart.

The code in your controller.resize() must:

  • assign the new height and width passed to controller.resize() to your chart's height and width variables
  • trigger a re-rendering of the chart or otherwise take into account the new size of the chart's DOM element
controller.resize = function(h, w, size) {
chartParameters.height = height;
chartParameters.width = width;
renderChart();
};

Our simple sample chart uses the following code to accomplish these tasks.

controller.resize = function(newWidth, newHeight) {
chart.resize();
};

Back to top

ADDING TOOLTIPS

Zoomdata enables you to add and configure tooltips in your chart when it is used in the Zoomdata client application. These tooltips can be used to identify and select the data displayed in the chart. These tooltips are part of the Zoomdata client application and only appear when the chart is used in the Zoomdata client app. The Zoomdata Javascript client library used for embedding charts does provide the data needed to create similar components in custom applications.

To add a tooltip, you must use your charting library's event handling system to trigger a call to controller.tooltip.show() .  In our simple bar chart example, we pass a callback function to the ECharts event handler, on() , which it will call when the mouse is moves over a chart component.

chart.on('mousemove', function(param) {
controller.tooltip.show(
{
event: param.event.event,
data: function() {
return param.data.model;
},
color: function() {
return param.color;
}
}
);
});

chart.on('mouseout', function(param) {
controller.tooltip.hide();
});

The callback function receives a single paramater, which we call param . param is the chart component where the event was triggered, for example, one of the bars of a bar chart. We use param to populate members in an object that we pass to controller.tooltip.show() , which we call in the callback function. The members of this object are:

  • event , which is the event that triggered the tooltip to show.
  • data , which we populate with the original data item from data[] that was passed to update() . We attached this data item to the object used by ECharts to render the bar when we supplied the data to the chart .
  • color , which is the color used to render the chart component.

The controller.tooltip object also has a hide() method that you can use to hide the tooltip after it has been rendered.

Back to top

ADDING CONTEXT MENUS

Zoomdata enables you to add and configure context menus in your chart when it is used in the Zoomdata client application. These context menus can be used to identify and select the data displayed in the chart. These context menus are part of the Zoomdata client application and only appear when the chart is used in the Zoomdata client app. The Zoomdata Javascript client library used for embedding charts does provide the data needed to create similar components in custom applications.

To add a context menu, you must use your charting library's event handling system to trigger a call to controller.menu.show() .  In our simple bar chart example, we pass a callback function to the ECharts event handler, on() , which it will call when the mouse is clicked on a chart component.

chart.on('click', function(param) {
controller.menu.show(
{
event: param.event.event,
data: function() {
return param.data.model;
}
}
);
});

The callback function receives a single paramater, which we call param . param is the chart component where the event was triggered, for example, one of the bars of a bar chart. We use param to populate members in an object that we pass to controller.menu.show() , which we call in the callback function. The members of this object are:

  • event , which is the event that triggered the menu to show.
  • data , which we populate with the original data item from data[] that was passed to update() . We attached this data item to the object used by ECharts to render the bar when we supplied the data to the chart .

The controller.menu object also has a hide() method that you can use to hide the menu after it has been rendered.

Back to top

SUMMARY

The preceding steps walk you through each of the high-level tasks necessary to implement a custom chart. The specific steps for converting data from Zoomdata to a format useful for your chart, as well as other steps, will depend on your charting library. The steps above work through a simple example to show the major features of the Visualization Framework that you can use as a basis for integrating your chart into the gallery of Zoomdata charts.

Back to top

Was this topic helpful?