I have an angularjs application that is running on electron. I have created 4 chart components and have initialized them during application startup. I have also synchronized their tools tips during application startup
I have two pages, and in page1 i am hiding the highcharts component and in page2 i am redrawing the charts with new data (i am not creating a new instance but reusing the same chart component).
whenever i redraw the charts or hover over the charts, the memory increases a lot and dosent go down.
can someone please help with this
this is the js file
angular.module('myApp', ['ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/page1.html',
controller: 'Page1Controller'
})
.when('/page2', {
templateUrl: 'pages/page2.html',
controller: 'Page2Controller'
})
.otherwise({
redirectTo: '/'
});
})
.controller('MainController', function ($scope, $timeout) {
let chartConfig = {
chart: {
type: 'line',
height: 200,
width: 1700,
marginTop: 0,
marginRight: 0,
marginBottom: 0, // The zoom selection band color.
animation: false,
reflow: false,
},
plotOptions: {
series: {
cursor: 'pointer', // Sets the cursor to 'pointer'
},
},
title: {
text: null // Don't display a title
},
credits: {
enabled: false // Don't display credits
},
legend: {
enabled: false // Don't display a legend
},
xAxis: {
tickInterval: (24 * 60 * 60 * 1000) / 8,
type: 'datetime', // X axis represents time (in msec)
crosshair: {
color: '#FFFFFF',
dashStyle: 'Solid',
width: 2
},
minPadding: 0.0015,
maxPadding: 0.0015,
align: 'center',
gridLineWidth: 1,
gridLineColor: '#4E4E4E',
tickLength: 0,
tickPixelInterval: 202,
lineWidth: 0,
categories: [],
},
yAxis: {
title: {
text: 'Values'
},
reserveSpace: true,
minPadding: 0,
maxPadding: 0,
gridLineWidth: 1, // No Y axis grid lines
gridLineColor: '#4E4E4E',
lineWidth: 2,
},
tooltip: {
animation: false,
followPointer: false,
cache: false,
},
series: [{
name: 'Sample Data',
animation: false,
data: []
}]
};
$scope.showChart = true;
let charts = [];
function initializeCharts() {
for (var i = 0; i < 4; i++) {
let contString = "container-" + (i + 1).toString();
let chart = Highcharts.chart(contString, chartConfig);
charts.push(chart);
}
}
function debounce(func, delay) {
let timeout;
return function () {
const context = this;
const args = arguments;
clearTimeout(timeout); // Clear the previous timeout
timeout = setTimeout(function () {
func.apply(context, args);
}, delay);
};
}
function synchronizeCharts() {
charts.forEach((chart, index) => {
const container = chart.container;
const onMouseMove = function (e) {
const event = chart.pointer.normalize(e);
charts.forEach((c, i) => {
if (i !== index && c.pointer) {
c.pointer.runPointActions(event);
}
});
}
const debouncedSynchronizeTooltips = debounce(onMouseMove, 100);
if (!container.dataset.tooltipSync) {
container.addEventListener('mousemove', debouncedSynchronizeTooltips);
container.dataset.tooltipSync = 'true';
}
});
}
function generateData() {
var data = [];
for (var i = 0; i < 1440; i++) {
var randomValue = Math.floor(Math.random() * (90 - 60 + 1)) + 60;
data.push(randomValue);
}
return data;
}
function generateAxis() {
var axis = [];
var now = (new Date()).getTime();
for (var i = 0; i < 1440; i++) {
axis.push(now - i * 3600 * 10000);
}
axis.reverse();
return axis;
}
function removeChartListeners(chart) {
const clone = chart.container.cloneNode(true);
chart.container.parentNode.replaceChild(clone, chart.container);
chart.container = clone
}
function removeDetachedNodes(chart) {
const spans = document.querySelectorAll('span');
spans.forEach(span => {
if(!document.body.contains(span)) {
span.remove();
span = null;
}
});
}
$scope.refreshChart = function () {
if ($scope.showChart) {
charts.forEach(chart => {
removeDetachedNodes(chart);
});
$scope.showChart = !$scope.showChart;
}
else {
// synchronizeCharts();
const axisData = generateAxis();
charts.forEach(chart => {
chart.xAxis[0].setCategories(axisData, false); // Avoid immediate redraw
chart.series[0].setData(generateData(), false);
});
charts.forEach((chart) => chart.redraw(false));
$scope.showChart = !$scope.showChart;
}
}
function ApplicationStartup() {
initializeCharts();
synchronizeCharts();
}
ApplicationStartup();
})
.controller('Page1Controller', function ($scope, $location) {
$scope.navigateToPage2 = function () {
$location.path('/page2');
};
$scope.refreshChart();
})
.controller('Page2Controller', function ($scope, $location) {
$scope.navigateToPage1 = function () {
$location.path('/');
};
$scope.refreshChart();
});
this is the html file
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="UTF-8">
<title>AngularJS Electron App</title>
<script src=".6.0.min.js"></script>
<script src=".8.2/angular.min.js"></script>
<script src=".8.2/angular-route.js"></script>
<script src=".js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainController">
<div ng-view></div>
<div ng-show="showChart">
<div id="container-1"></div>
<div id="container-2"></div>
<div id="container-3"></div>
<div id="container-4"></div>
</div>
</body>
</html>
using the following package json
{
"name": "angularjs-electron-app",
"version": "1.0.0",
"description": "AngularJS (v1.8.7) app running on Electron",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^35.0.1",
"express": "^4.21.2"
},
"dependencies": {
"highcharts": "^10.2.0"
}
}