UNPKG

@springernature/nn-charts

Version:
404 lines (377 loc) 18.1 kB
"use strict"; 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 _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; } 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); } } }]); }();