Ievgenii Spitsyn Avatar

Ievgenii Spitsyn

Ievengenii is a web developer whose focus is to create interactive web applications. Prior to joining Zoomdata, he worked with banks to test personnel modules, data processing systems, and managed the companies CMS. Ievengenii enjoys snowboarding, diving, paintballing and traveling the world in his free time.

4 min read · December 21st 2017 (originally published at Medium)

How to build Zoomdata Visualizations

Blog Post Intro Image

Zoomdata offers a rich set of predefined templates and the possibility to build your own visualizations based on defined templates.

Zoomdata provides several ways to get aggregated or plain data form a database, let’s take a look at the details of each of these mechanisms.

Link to working example IevgenySp/zoomdata-samples

Visualization Web Component creation described in: Creating Visualization Web Component

Client configuration

// Name of the database source
var source = 'My IMPALA Source';

// Path configuration
var application = {
  secure: true,
  host: 'developer.zoomdata.com',
  port: 443,
  path: '/zoomdata-2.6',
};

// Configuration of query that will be send to backend
var credentials = {
  key: 'KVKWiD8kUl',
};

Credentials key can be obtained from the saved dashboard interactive link:

Share Dashboard

The query configuration includes parameters such as timezone, type of time player representation, data filters and aggregations by groups and metrics.

// Configuration of query that will be send to backend
var queryConfig = {
  filters: [],
  groups: [
    {
      name: 'gender',
      limit: 200,
      sort: {
        dir: 'asc',
        name: 'gender',
      },
    },
  ],
  metrics: [
    {
      name: 'sales',
      func: 'sum',
    },
  ],
};

The visualization template is an entity with objectFields which describe visualization meta data: the metrics, groups aggregations, color and other parameters. There is a possibility to create custom visualizations based on selected templates.

// Configuration of selected visualization template
var vizConfig = {
  element: document.getElementById('chart3'),
  config: queryConfig,
  source: { name: 'My IMPALA Source' },
  visualization: 'Bars',
};

Create and run query (runQuery)

function runQuery() {
  ZoomdataSDK.createClient({
    credentials: credentials,
    application: application,
  }).then(function(client) {
    client
      .createQuery({ name: source }, queryConfig)
      .then(function(query) {
        client.runQuery(query, buildViz);
      })
      .catch(function() {});
  });
}

The method returns a promise with Query Client which allows the query to run and get data from the web-socket which passes directly to visualization (buildViz).

Create client, run query and listen for a data thread (run)

function run() {
  ZoomdataSDK.createClient({
    credentials: credentials,
    application: application,
  }).then(function(client) {
    client
      .createQuery({ name: source }, queryConfig)
      .then(function(query) {
        client.run(query).then(function(thread) {
          thread.on('thread:message', function(data) {
            buildViz(data, runVizContainer);
          });
        });
      })
      .catch(function() {});
  });
}

This is the same as in the previous example the method returns a promise with Query Client which allows the query to run and listen for a data thread to obtain data for building visualization.

Visualize template directly via Zoomdata API (visualize)

function visualize() {
  if (visualizeViz !== null) {
    visualizeViz.remove();
  }

  ZoomdataSDK.createClient({
    credentials: credentials,
    application: application,
  })
    .then(function(client) {
      return client.visualize(vizConfig).then(function(viz) {
        visualizeViz = viz;
      });
    })
    .catch(err => console.log(err));
}

Apart from other two methods client.visualize builds the selected visualization template based on the provided data and does not allow it to pass the custom chart source code.

Visualization code

Visualizations can be built based on different JS libraries. It can be D3, ECharts, Plotly, and many others. As an example in this article let’s take a look at the visualization code, written on ParticleS library — Zoomdata library for building high performing charts.

function buildViz(data, container) {
  var element = container ? container : runQueryVizContainer;

  element.innerHTML = '';

  var colors = ['#ffc65f', '#0197b7'];

  // Convert data to format understandable by ParticleS library
  var chartData = data.map(function(obj, index) {
    var hoverColor =
      'rgba(' +
      utils
        .hexToRGB(colors[index])
        .concat([0.3])
        .join(',') +
      ')';

    return {
      data: [
        {
          value: obj.group[0],
          format: 'string',
        },
        {
          value: obj.current.metrics.sales.sum,
          format: 'integer',
        },
      ],
      style: {
        color: colors[index],
        hoverColor: hoverColor,
        thickness: 85,
      },
    };
  });

  // Select Vertical Bars template
  var chart = new ParticleS.CHARTS.CUSTOM.VerticalBarsRoundedWhiteSchema();

  chart.options.resize.delay = 25;
  chart.appendTo(element);

  // Add tooltips to charts
  // Listen for chart elements events, invoke tooltip on chart elements
  chart.on('bar:mouseenter, circle:mouseenter', function(evt, particle, mouse) {
    var header = tooltip.createHeader(
      utils.format(particle.data[0].format, particle.data[0].value),
    );
    var table = tooltip.createTable();
    var row = tooltip.createRow();
    var cell1 = tooltip.createCell('Volume');
    var cell2 = tooltip.createCell(
      utils.format(particle.data[1].format, particle.data[1].value),
    );
    table.addRow(row);
    row.addCell(cell1);
    row.addCell(cell2);

    cell2.style.textAlign = 'right';
    cell2.style.fontWeight = 'bold';

    tooltip.show();
    tooltip.color(particle.style.color);
    tooltip.position({ x: mouse.offset.x, y: mouse.offset.y });

    tooltip.clear();
    tooltip.append(header);
    tooltip.append(table);
  });

  chart.on('bar:mouseleave, circle:mouseleave', function(evt, bar, mouse) {
    tooltip.hide();
  });

  chart.layer.canvas.addEventListener('mouseout', function() {
    setTimeout(function() {
      tooltip.hide();
    }, 10);
  });

  chart.layer.canvas.addEventListener('mouseout', function() {
    setTimeout(function() {
      tooltip.hide();
    }, 10);
  });

  // Refresh chart with data
  chart.refresh(chartData);
}

runQueryBtn.addEventListener('click', runQuery);
runBtn.addEventListener('click', run);
visualizeBtn.addEventListener('click', visualize);

The visualization tooltip can be initialized with the next lines of code:

var tooltip = new ParticleS.Tooltip([], { left: -100, right: -100 }, {});
var utils = ParticleS.Utils;

tooltip.appendTo(document.body);

Any other JS chart library can be used in similar ways for building custom charts with Zoomdata. In the next articles I will show you how to build Zoomdata visualizations using ECharts and D3 libraries, and which key methods can be used in Zoomdata native template visualizations.