This post is the second part of the blog series – Unlocking Custom Visualizations in Oracle Analytics. The previous blog introduced foundational setup, file structure, and initial commands required to create a plug-in skeleton, culminating in a simple text message display.

In this post, you’ll learn how to enhance the plug-in to render a basic HTML-based bar chart visualization using D3.js. The chart illustrates the relationship between a numerical and a categorical variable, using hard-coded data for simplicity. Here’s an example of the expected output:

Expected Outcome

Expected Output

                                                                                         Fig. 1: Bar Chart Custom Plug-in

File Structure Recap

As outlined in the first part of the series, the plug-in directory consists of several files. For this post, only two files need modifications:

  • barChart.js

  • barChartstyles.css

Custom Files

                                                                                                   Fig 2: File Structure

Enhance the barChart.js File

The barChart.js file serves as the core of the plug-in, encapsulating the logic and handling the rendering of the chart. Follow these steps to create the bar chart:

1. Import Libraries

Begin by importing the necessary libraries and modules, including D3.js, in the define block:

define([
        'jquery',
        'obitech-framework/jsx',
        'obitech-report/datavisualization',
        'obitech-reportservices/datamodelshapes',
        'obitech-reportservices/events',
        'd3js',                                                //D3 V6 library
        'knockout',
        'ojs/ojattributegrouphandler',
        'obitech-framework/messageformat',
        'skin!css!com-company-barchart/barChartstyles'],
        
function($,
         jsx,
         dataviz,
         datamodelshapes,
         events,
         definitions,
         logger,
         messages,
         euidef,
         data,
         d3,
         ko,
         attributeGroupHandler
         )

Ensure that the order of imports in the define and function blocks matches. For instance, datamodelshapes and d3 in the define block must align with their respective variable names in the function block.

Note: The D3.js library is represented by a variable corresponding to D3 v6. If you prefer using a different version, such as D3 v5, replace D3js with D3v5js in the define block.

2. Define the Render Function

BarChart.prototype.render = function(oTransientRenderingContext)

The render function generates the visualization. Follow these steps to implement the bar chart logic:

Step A: Initialize the Container

Retrieve the root container and define its properties. By default, the code generates a line starting with “$(elcontainer).htm…”. Replace it with these lines:

var elContainer = this.getContainerElem();

var htmlContent = "<div class='barcharttest' id='barcharttest'></div>";
$(elContainer).html(htmlContent);
var width = $(elContainer).width() - 20;
var height = $(elContainer).height() - 20;

Step B: Load the Data

The dataset used for this plug-in is as follows:

Year

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

Sale

202

215

179

199

134

134

230

40

143

34

176

                                                             Fig 3: Sample Dataset

Convert the dataset into JSON format:

data: [
          { "sale": "202", "year": "2000" },
          { "sale": "215", "year": "2001" },
          ….
        ]

Step C: Create an SVG Element

Append an SVG element to the container. You can also add margins to the SVG image:

var svgConfig = {
                id:"barcharttest",
                width:width,
                height:height
                };
// append svg element
          var bodySelection = d3.select("#barcharttest");
          
          var svgSelection  = bodySelection.append("svg")
                    .attr("id", svgConfig.id)
                    .attr("width",svgConfig.width)
                    .attr("height",svgConfig.height);

This code fragment also adds a group element to the SVG element.

Step D: Define Scales

Set up linear scales for the x and y axes:

// Create x scale
      var xScale = d3.scale.linear()
          .range([svgConfig.margin.left, svgConfig.width - svgConfig.margin.right])
          .domain([
               d3.min(chartConfig.data, function(d) { return +d.year; }) - 1,
               d3.max(chartConfig.data, function(d) { return +d.year; })
          ]);

      // Create y scale
      var yScale = d3.scale.linear()
      .range([svgConfig.height - svgConfig.margin.top,   svgConfig.margin.bottom])
      .domain([
          134,
          d3.max(chartConfig.data, function(d) { return +d.sale; })
      ]);

Step E: Render Bars

Use the scales to position and size the bars in the chart:

// create bars
          svgSelection.selectAll("rect")
                   .data(chartConfig.data)
                   .enter()
                   .append("rect")
                   .attr("x", function(d) {
                    return xScale(+d.year) - chartConfig.barWidth/2;
                   })
                   .attr("y", function(d) {
                    return yScale(d.sale) - svgConfig.margin.bottom;
                   })
                   .attr("width", chartConfig.barWidth)
                   .attr("height", function(d) {
                    return svgConfig.height - yScale(d.sale);
                   })
                   .attr("fill", function(d) {
                    return "rgb(90, 0, " + (+d.sale) + ")";
                   })

Step F: Generate Axes for the Chart

Generate and position the x and y axes:

// Create the axes using the scales
      var xAxis = d3.svg.axis()
        .scale(xScale)
        .tickFormat(d3.format("d"));
    
      var yAxis = d3.svg.axis()
        .orient("left")
        .scale(yScale);

Now, append these axes to the chart and position them using the transform property.

// Add x-axis to chart
      svgSelection.append("g")
        .attr("id", "xAxis")
        .attr("class", "axis")
        .call(xAxis);
    
      // Position the x-axis vertically using transform property
      d3.select("#xAxis")
        .attr("transform", "translate(0," + (svgConfig.height - svgConfig.margin.bottom) + ")");
    
      // Add y-axis to chart
      svgSelection.append("g")
        .attr("id", "yAxis")
        .attr("class", "axis")
        .call(yAxis);
    
      // Position the y-axis using transform property
      d3.select("#yAxis")
        .attr("transform", "translate(" + svgConfig.margin.left + ",0)");
    }

Enhance the barChartstyles.css File

Customize the appearance of the chart with features such as font family, size, and color.

.axis path, .axis line {
    fill: none;
    stroke: #777;
    shape-rendering: crispEdges;
}
.axis text {
    font-family: Lato;
    font-size: 13px;
}
rect {
    -moz-transition: all 0.3s;
    -webkit-transition: all 0.3s;
    -o-transition: all 0.3s;
    transition: all 0.3s;
}
rect:hover{
    fill: orange;
}

Set up the Icon for the Plug-in

Update the .png file to set your plug-in icon. Be sure to retain the original file naming convention.

Once you’ve updated these files, do a gradle clean build run to get these changes reflected:

C:\custom-plugins>.\gradlew clean build run

Final Output

                                                                                         Fig 4: Final Output of the Bar Chart Plug-in

With these steps, the plug-in now renders a basic bar chart using hardcoded data. You can adapt the process outlined here for other custom plug-ins.

Call to Action

Are you ready to take your custom plug-in development to the next level? Start experimenting with the steps outlined in this post to create your own bar chart visualization. Don’t forget to explore Part 1, if you’re just starting out, and stay tuned for Part 3, where you’ll delve into integrating external data sources and exploring grammar properties to create more dynamic visualizations.