@springernature/nn-charts
Version:
Visualization for DAS products
403 lines (376 loc) • 17.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
var d3 = _interopRequireWildcard(require("d3"));
var _common = require("../../utils/common");
var _legends = require("../../utils/legends");
var _columnTransition = require("../../utils/column-transition");
var _shapeGeneration = require("../../utils/shape-generation");
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/*
ColumnChart class definition
*/
var ColumnChart = exports["default"] = /*#__PURE__*/function () {
// ColumnChart constructor definition
function ColumnChart(data, element, loadingStartedCb, loadingEndedCb) {
_classCallCheck(this, ColumnChart);
// Store callback functions for pre loading and post loading of chart
this.loadingStartedCallback = loadingStartedCb;
this.loadingEndedCallback = loadingEndedCb;
// function call to implement chart responsiveness after window resizing
// this.window = window.addEventListener("resize", () => {
// const el = this;
// alertSize(el); // function call to get current browser window dimensions
// getChartMargins(el);
// columnChartOnWindowResize(el /* , dataCategoryLength */);
// });
this.config = {
isLayerSelected: false,
// boolean var to trigger if a category layer is selected or not
isPreviousLayerSelected: false,
// boolean var to trigger if a category layer is selected or not
stickyActiveLabel: null /* acitvated if user has clicked on data rectangle to freeze layer highlighting */,
selectedLayer: null /* has a data layer/horizon been selected? if so, this will not be blank/null */,
data: data ? data : [],
// formatPercent: d3.format(".0%"), // format for percent labelling
// formatNumber: d3.format(","), // format for number labelling
chartGroupTranslateOffset: {
x: 100,
y: 125
},
baseContainerDiv: "column-chart",
heightToWidthRatio: 0.4,
svgBasePanelClassNames: ["base-panel"],
onloadChart: "yStackMax",
firstloadedChart: "stacked" /* "percent" "stacked" , "grouped" */,
clickedChartType: "stacked" /* "percent" "stacked" , "grouped" */,
arrayOfYears: [] /* flat array to contain all data years to populate xTime chart axis labels */,
yAxisRoundings: {
yGroupMax: 50,
// y-axis rounding value for grouped column chart
yStackMax: 1000,
// y-axis rounding value for stacked column chart
percent: 100 // y-axis rounding value for 100% stacked column chart
// grouped: 50, // y-axis rounding value for grouped column chart
// stacked: 100, // y-axis rounding value for stacked column chart
// percent: 100, // y-axis rounding value for 100% stacked column chart
},
xAxisDataKey: "year",
yAxisDataKey: "totalArticles",
dataCategories: "categories",
legend: {
visible: true,
position: "bottom",
//top, bottom
placement: "center",
// left , right, center
classNames: ["legend-container"],
swatchSymbol: "square" /* square, circle, rect, */,
swatchSymbolDimensions: {
rect: {
x: 0,
y: 0,
rectWidth: 25,
rectHeight: 25
},
circle: {
cx: 0,
cy: 0,
r: 5
}
},
categoryLabelTranslation: {
x: 5,
y: 15
},
legendGroupWidth: 40,
legendGroupHeight: 0,
legendCategories: [],
translation: {
x: null,
y: 75
},
legendCategoryTranslation: {
x: 0,
y: 22.5
},
legendPlacement: "bottom-center" /* bottom-center, top-center, bottom-left, top-left, bottom-right, top-right */,
legendAlignment: "horizontal" /* "vertical", 'horizontal' */
},
axis: {
x: {
position: "bottom" /* "top" */,
classNames: ["axis", "x-axis"],
ticks: {
enable: true,
color: "#000",
thickness: 1,
transition: {}
},
tickLabels: {
enable: true,
textSize: "10px",
color: "#000"
},
title: {
enable: true,
text: "Year Published In",
orientation: "horizontal",
fill: "none",
stroke: "#d8d8d8",
strokeWidth: 0.5,
/* vertically orientated defintion, at side of y-axis */
axisOffset: 50,
rotation: 0,
textAnchor: "middle"
},
gridLines: true,
color: "#000",
textSize: "10px",
orientation: "horizontal",
type: "linear"
},
y: {
position: "left" /* "right" */,
classNames: ["axis", "y-axis"],
ticks: {
enable: true,
color: "#000",
thickness: 1
},
tickLabels: {
enable: true,
textSize: "10px",
color: "#000"
},
gridLines: {
enable: true,
/* yet to envoke styling via SASS & BEM */
fill: "none",
stroke: "#d8d8d8",
strokeWidth: 0.5,
strokeArray: "5 5"
},
title: {
enable: true,
text: "Number of Publications",
orientation: "vertical" /* "horizontal" */,
fill: "none",
stroke: "#d8d8d8",
strokeWidth: 0.5,
// /* vertically orientated defintion, at side of y-axis */,
axisOffset: -70,
rotation: 270,
textAnchor: "middle"
/* horizontal orientated defintion, at top of y-axis */
// axisOffset: -30,
// rotation: 0,
// textAnchor: "start",
},
color: "#000",
textSize: "10px",
orientation: "horizontal",
type: "linear"
}
},
column: {
bgColor: "#eee"
},
transition: {},
screenSize: 6,
margins: {
1: {
top: 125,
right: 100,
bottom: 75,
left: 50
},
2: {
top: 125,
right: 100,
bottom: 75,
left: 50
},
3: {
top: 125,
right: 100,
bottom: 75,
left: 50
},
4: {
top: 125,
right: 100,
bottom: 75,
left: 50
},
5: {
top: 125,
right: 100,
bottom: 75,
left: 50
},
6: {
top: 105,
right: 100,
bottom: 100,
left: 50
}
},
theme: {
groupColours: ["#E85043", "#FACC28", "#008AFF", "#1FA87F"]
},
interactionElements: {
chart: "rectangle",
legend: "legend-group"
},
tooltip: {
tooltip: null,
width: 300,
// width of tooltip
height: 150 // height of tooltip
},
selectedLayerIndex: 0 /* what is the currently selected data category layer Index? */
};
this.element = element;
}
/*
name: init
description: function to initial building of chart
arguments: none
returns: none
calls: drawColumnChart
called from: textDemo.js (nn-charts-poc)
*/
return _createClass(ColumnChart, [{
key: "init",
value: function init() {
try {
var el = this;
// loop through all data elements
el.config.data.forEach(function (d, i) {
el.config.arrayOfYears.push(d[el.config.xAxisDataKey]); // push year object element onto array
});
el.config.yearArrayLength = el.config.arrayOfYears.length;
// function call to draw new chart at point of page load
// determine container dimnensions (width, height)
el.config.containerWidth = (0, _common.getContainerWidth)(this.element, el.config.yearArrayLength, this.config.margins, 30);
el.config.containerHeight = (0, _common.getContainerHeight)(el.config.containerWidth, el.config.heightToWidthRatio);
//
// update chart legend horizontal (x) offset positioning
el.config.legend.translation.x = el.config.containerWidth - el.config.margins[el.config.screenSize].right;
// extract legend categories into array for building legend
el.config.legend.categories = d3.keys(el.config.data[0][el.config.dataCategories]);
// determine container dimnensions (width, height)
el.config.chartWidth = el.config.containerWidth - el.config.margins[el.config.screenSize].left - el.config.margins[el.config.screenSize].right;
el.config.chartHeight = el.config.containerHeight - el.config.margins[el.config.screenSize].top - el.config.margins[el.config.screenSize].bottom;
d3.select(el.element).selectAll("*").remove();
// call Method to create base SVG panel
// first param is classNames of base containing DIV defined in component (in navigator-webapp) to which to attach chart.
// second param is classNames to give to this base SVG panel
el.loadingStartedCallback();
el.config.svgPanel = (0, _shapeGeneration.createBaseSVGPanel)(el.element, el.config.svgBasePanelClassNames, el.config.containerWidth, el.config.containerHeight, el.config.chartGroupTranslateOffset);
// call methods to create x-axis
// first get data to define axis domain
var xAxisData = (0, _common.getColumnChartAxisData)(el.config.data, el.config.xAxisDataKey);
// define new scaleband x-axis
var xAxisScale = (0, _common.createScaleBandXAxis)(xAxisData, el.config.containerWidth - el.config.margins[el.config.screenSize].left - el.config.margins[el.config.screenSize].right);
//
// call methods to create bars
var dataCategories = (0, _common.getColumnChartAxisData)(el.config.data, el.config.dataCategories);
var dataCategoriesList = (0, _common.getDataToDrawColumnChartCategories)(dataCategories);
el.config.dataCategoryLength = dataCategoriesList[0].length;
var dataLayersData = (0, _common.generateLayersForColumnChart)(dataCategoriesList, el.config.dataCategoryLength);
var yStackMax = (0, _common.getStackMax)(dataLayersData);
var yGroupMax = (0, _common.getGroupMax)(dataLayersData);
//
// call methods to create y-axis
// first get data to define axis domain
var yAxisData = (0, _common.getColumnChartAxisData)(el.config.data, el.config.yAxisDataKey);
// define new linear y-axis
var yAxisScale = (0, _common.createLinearYAxis)(el.config.chartHeight, yStackMax, el.config.onloadChart === "yStackMax" ? yStackMax : el.config.yAxisRoundings[el.config.onloadChart]);
// position new y-axis
var position_yAxis = (0, _common.positionAxis)(yAxisScale, el.config.axis.y);
// append new y-axis
var append_yAxis = (0, _common.appendAxis)(position_yAxis, el.config.axis.y, el.config.svgPanel, 0);
// append full width gridlines to chart y-axis
var yAxisGridLines = (0, _common.appendYAxisGridLines)(el.config.containerWidth - el.config.margins[el.config.screenSize].left - el.config.margins[el.config.screenSize].right, el.config.axis.y.gridLines, el.config.axis.y.classNames);
// append main title onto y-axis
var yAxisTitle = (0, _common.appendYAxisTitle)(el.config.axis.y.title, d3.max(yAxisScale.range()), el.config.axis.y);
//var element = d3.select(el.element).node();
var scrollableGroup = el.config.svgPanel.append("g").attr("class", "scrollable-group");
// .attr("width", element.getBoundingClientRect().width)
// .attr("style", "overflow: auto");
// position new x-axis
var position_xAxis = (0, _common.positionAxis)(xAxisScale, el.config.axis.x);
// append new x-axis
var append_xAxis = (0, _common.appendAxis)(position_xAxis, el.config.axis.x, scrollableGroup, el.config.chartHeight);
// modify labels to make them meaningful (d3.scaleBand() defaults to index integer category labels)
var xAxisLabels = (0, _common.modifyAxisLabels)("x", el.config.data, el.config.xAxisDataKey);
// append main title onto x-axis
var xAxisTitle = (0, _common.appendXAxisTitle)(el.config.axis.x.title, d3.max(xAxisScale.range()), el.config.axis.x);
(0, _legends.createLegends)(el.config.svgBasePanelClassNames, el.config.legend, el.config.theme.groupColours);
var dataLayersElements = (0, _common.generateLayerGroupsForColumnChart)(scrollableGroup, dataLayersData, el.config.theme.groupColours);
var rectBars = (0, _common.generateBarsForColumnChart)(dataLayersElements, el.config.chartHeight, xAxisScale);
if (el.config.clickedChartType == "stacked") {
(0, _columnTransition.transitionStacked)(xAxisScale, yAxisScale, rectBars, el.config.svgPanel, position_yAxis, el, yStackMax);
} else if (el.config.clickedChartType == "grouped") {
(0, _columnTransition.transitionGrouped)(xAxisScale, yAxisScale, rectBars, el.config.svgPanel, position_yAxis, el, yGroupMax, dataCategoryLength);
} else if (el.config.clickedChartType == "percent") {
(0, _columnTransition.transitionPercent)(xAxisScale, yAxisScale, rectBars, el.config.svgPanel, position_yAxis);
}
// act on user selecting HTML reset button.
// d3.selectAll(".resetChart").on("click", function () {
// document.getElementById("resetChart").disabled = true;
// d3.select("#resetChart").classed("disabled", true);
// resetChart(
// xAxisScale,
// yAxisScale,
// rectBars,
// position_yAxis,
// position_xAxis,
// el,
// yStackMax,
// yGroupMax
// );
// });
// act on user selecting an alternative chart type button.
d3.selectAll(".chartType").on("click", function () {
// document.getElementById("resetChart").disabled = false;
// d3.select("#resetChart").classed("disabled", false);
el.config.clickedChartType = this.value;
//
// call function to change chart type.
(0, _common.changeChart)(xAxisScale, yAxisScale, rectBars, el.config.svgPanel, position_yAxis, position_xAxis, el, yStackMax, yGroupMax, el.config.dataCategoryLength);
});
(0, _common.alertSize)(el); // function call to get current browser window dimensions
(0, _common.getChartMargins)(el); // call function to get exact margin defintion based on screen width
//columnChartOnWindowResize(el); // window resize function
// update styling to correct form for onloadcharttype (defined in el.config.firstloadedChart)
// remove 'chartType' class from all chart type selction buttons
d3.selectAll(".chartType").classed("selected", false);
// add 'chartType' class to newly selcted chart type selection button
d3.selectAll(".chartType." + el.config.clickedChartType).classed("selected", true);
var chartElement = el.config.interactionElements.chart;
d3.selectAll("." + chartElement).on("mouseover", function (d) {
var ele = d3.select(this).attr("id");
var index = ele.substring(ele.indexOf("_") + 1, ele.length);
(0, _common.mouseover)(this, index, d, xAxisData, el, el.config.svgBasePanelClassNames, el.config.dataCategoryLength);
});
d3.selectAll("." + chartElement).on("mouseout", function () {
(0, _common.mouseleave)(this, el);
});
el.loadingEndedCallback();
} catch (error) {
console.error("Error in ColumnChart.init function: ", error);
}
}
}]);
}();