SAC Sunburst Widget - Hierarchical Data Visualizat...
Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
Our latest project, the SAC Sunburst Widget, is designed to bridge the gap between the standard visualization capabilities of SAP Analytics Cloud (SAC) and the cover the hierarchical data representation needs of users. With the Sunburst Widget, you can effortlessly visualize and explore multi-level data hierarchies, all by simply downloading the widget and integrating it with your SAC and data model.
But before we dive in, make sure you’ve read our previous blog post:
Transforming SAC with Custom Widgets (Part 1) – link
Transforming SAC with Custom Widgets (Part 2 – Gamify) – link
Building a Customizable Calculator Widget for SAC – Styling and Builder Panel – link
Transforming SAC with Custom Widgets (Part 4 – Custom Widgets Data Binding)– link
Gantt Chart Widget with Data Binding for SAP Analytics Cloud– link
REST API Integration for SAP Analytics Cloud – Gantt Chart Widget bidirectional – link
Introducing the SAC Cockpit Widget – Version Management, Auditing, Task Management - link
Back to our Sunburst Widget
SAP Analytics Cloud is undeniably a robust platform, but there's always room for enhancement. The Sunburst Widget is our answer to the need for an intuitive hierarchical data visualization tool within SAC. This widget allows users to interactively explore data layers, offering a comprehensive view of data distribution across multiple dimensions. The widget is designed to integrate seamlessly with SAC, ensuring a smooth user experience and will work out of the box.
The Code Structure
Before diving into the functionalities, let's familiarize ourselves with the widget's code structure:
Main JS Code (SunburstWidget.js): The core of our widget, dictating its look and behavior. You can view the full JavaScript code [here].
JSON Configuration (SunburstWidget.json): This file outlines the widget's properties, methods, events, and data bindings. You can view the full JSON code [here].
Key Components:
Functionality
The Sunburst Widget offers a dynamic, interactive visualization of hierarchical data. With Linked Analysis available the users can click on segments to drill down or up the hierarchy, providing a fluid exploration experience.
Data Binding Definition
Sunburst Widget expects a parent-child hierarchy to function properly. The hierarchy can be created and maintained in the public or private dimension . Later in the Builder panel, the hierarchy must be assigned under Dimension as shown below:
SAC Sunburst Model Definition
In our case, we kept it simple and only have one dimension and one measure for our demo purposes.
The "Global Sales" hierarchy is maintained as follows:
Widget Class Definition
The core of the widget is defined in the `SunburstWidget` class, which extends the `HTMLElement` class. The constructor initializes the widget:
- It attaches a shadow root, allowing for encapsulation of the widget's styles and structure.
- It sets up a resize observer to detect when the widget's size changes.
- It loads the D3.js library, which is essential for rendering the Sunburst chart.
- `onCustomWidgetBeforeUpdate`: This method is called before the widget updates. It's used to merge the current properties with the changed properties.
- `onCustomWidgetAfterUpdate`: This method is called after the widget updates. If the data binding changes, it triggers the `_updateData` method to handle the new data.
- `disconnectedCallback`: This method is called when the widget is removed from the DOM. It's used to disconnect the resize observer.
Segment Click Handling
The `_handleSegmentClick` method manages what happens when a segment of the Sunburst chart is clicked. It can set or remove filters based on the segment's selection status:
_handleSegmentClick(d) {
....
if (d.selected) {
linkedAnalysis.removeFilters();
d.selected = false; // Reset the selected flag
} else {
const selection = {};
const key = dimension.key;
const dimensionId = dimension.id;
selection[dimensionId] = d.data[key].id;
linkedAnalysis.setFilters(selection);
d.selected = true; // Set the selected flag
}
}
Resize Handling
The `_onResize` method is triggered when the widget's size changes. It re-renders the chart to fit the new size.
Data Update Handling
The `_updateData` method is responsible for handling new data. It checks the data's state, transforms it if necessary, and then triggers the chart rendering:
_updateData(dataBinding) {
.....
if (this._ready) {
// Check if dataBinding.data is an array
if (Array.isArray(dataBinding.data)) {
// Transform the flat data into a hierarchical structure
const hierarchicalData = this.transformToHierarchy(dataBinding.data);
this.currentData = this.transformToHierarchy(dataBinding.data);
// Render the chart with the hierarchical data
this._renderChart(hierarchicalData);
this._props.metadata = dataBinding.metadata;
} else {
console.error('Data is not an array:', dataBinding.data);
} } }
Rendering the Sunburst Chart
The `_renderChart` method is where the main logic is. It uses D3.js to render the Sunburst chart:
- It sets up the dimensions and the partition layout.
- It defines the color scale based on the top-level parents.
- It creates the SVG container and appends the Sunburst arcs.
- It handles the text labels within the arcs, ensuring they fit and are readable.
Data binding is a crucial aspect of any data visualization widget. It's the bridge between raw data and the visual representation. In the Sunburst Widget, data binding ensures that the hierarchical data is correctly represented in concentric circles.
Requirements and Prerequisites
For the Sunburst Widget to function correctly, the data must meet certain criteria:
Hierarchical Structure:The data should inherently have a hierarchical structure. This means that there should be parent-child relationships within the data. For instance, in a company's organizational structure, a CEO might be at the top, with managers below, followed by employees.
Unique Identifiers:Each data point should have a unique identifier. This ensures that parent-child relationships can be accurately mapped.
Consistent Data Points: The data should consistently have a dimension and a measure. Dimensions represent the categories or levels of hierarchy, while measures represent the quantitative values associated with each dimension.
Dimensions: These represent the hierarchical levels. For instance, in a dataset representing a company's sales, dimensions could be `Region > Country > City`.
The data might look something like this before being processed:
This method is the heart of the data binding process for the Sunburst Widget. It takes the flat data structure and transforms it into a hierarchical format suitable for the Sunburst chart.
Here's a step-by-step breakdown:
Initialize the Root: The method starts by creating a root node named "root" with an empty children array.
let hierarchy = { name: "root", children: [] };
Mapping: A map object is initialized to keep track of nodes by their unique identifiers.
let map = {};
Data Iteration:The method then iterates over each data item:
- It checks if the necessary dimensions exist.
- It creates a node with the label, value (from measures), and an empty children array.
- The node is then added to the map using its unique identifier.
- The parent of the node is determined. If the node has a parent (based on the parentId), it's added as a child to its parent node in the hierarchy.
data.forEach(item => { let node = {
name: item.dimensions_0.label,
value: item.measures_0 ? item.measures_0.raw : 0, // Also added a check for measures_0
children: []
}; map[item.dimensions_0.id] = node;
let parent = item.dimensions_0.parentId ? map[item.dimensions_0.parentId] : hierarchy;
parent.children.push(node);
});
Return the Hierarchy: After processing all data items, the method returns the hierarchy.
return hierarchy;
The result is a nested data structure that D3.js can easily use to render the Sunburst chart.
Design and Styling
The Sunburst Widget is a visually appealing representation of hierarchical data. It's not just about the data, though; the styling plays a crucial role in making the chart both informative and aesthetically pleasing. Let's dive into the styling aspects of the Sunburst Widget.
Basic Styling Setup
At the beginning of the code, a template element is created to hold the widget's HTML and styling. Inside this template, the styling is defined within the `<style>` tags.
Styling the Sunburst Arcs
The arcs in the Sunburst chart are styled using the `.sunburst-arc` class. A white stroke separates the arcs, and a transition effect is applied to the fill opacity for smooth visual feedback:
The Sunburst chart is rendered using D3.js, a powerful library for data visualization. D3.js allows for dynamic styling based on data. For instance, the color of each arc is determined by its parent:
const color = d3.scaleOrdinal()
.domain(topLevelParents)
.range(d3.schemeCategory10);
This code sets up a color scale using D3's built-in color schemes. Each top-level parent in the Sunburst chart gets a unique color from this scheme.
JSON Configuration
The `SunburstWidget.json` file is essentially a configuration file that provides SAP Analytics Cloud (SAC) with all the necessary information about the Sunburst Widget. This ensures that SAC can seamlessly integrate and interact with the widget.
Specifies how the widget binds to data in SAC. The widget expects two types of feeds: dimensions and measures. Dimensions represent categorical data, while measures represent numerical data.
The widgets will be freely accessible on our Github page [Github]. We believe in open-source development and the power of community collaboration.
Just download the JSON file for the SAC Cockpit and upload it in your SAC tenant under Custom Widgets as follows:
Integrating the SAC Sunburst Widget into SAC is a straightforward process. Once you have the `SunburstWidget.json` file ready, you can upload the widget to SAC through the Custom Widgets panel. After uploading, the SAC Widget will be available for use in your dashboards.