diff --git a/index.html b/index.html index afc866dda0e1fafccd1913bd719c4257177daf01..d28e2a8112e00f876d261f4400b6c8fd92ecbef6 100644 --- a/index.html +++ b/index.html @@ -11,8 +11,7 @@ <meta name="author" content="" /> <title>Dashboard - iCity Bosch</title> <link href="css/styles.css" rel="stylesheet" /> - <link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.css" rel="stylesheet" /> - + <link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" @@ -31,8 +30,6 @@ <script src="https://code.highcharts.com/stock/modules/exporting.js"></script> <script src="https://code.highcharts.com/stock/modules/export-data.js"></script> - <!-- chart.js library --> - <!-- <script src="https://cdn.jsdelivr.net/npm/chart.js@3.2.1/dist/chart.min.js"></script> --> <!-- Apexcharts lib --> <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script> <link rel="stylesheet" href="css/styles.css" /> @@ -59,16 +56,36 @@ <!-- chart.js library --> <!-- <script src="https://cdn.jsdelivr.net/npm/chart.js@3.2.1/dist/chart.min.js"></script> --> - <!-- chart.js library --> - <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> - <!-- for gesture recogintion --> - <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/0.7.7/chartjs-plugin-zoom.min.js"></script> + <!-- chart.js library --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> + <!-- for gesture recogintion --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script> + + <!-- chart.js library --> + + <!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.css" integrity="sha512-/zs32ZEJh+/EO2N1b0PEdoA10JkdC3zJ8L5FTiQu82LR9S/rOQNfQN7U59U9BC12swNeRAz3HSzIL2vpp4fv3w==" crossorigin="anonymous" referrerpolicy="no-referrer" /> --> + <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js" integrity="sha512-d9xgZrVZpmmQlfonhQUvTR7lMPtO7NkZMkA0ABN3PHCbKA5nqylQ/yWlFAyY6hYgdF1Qh6nYiuADWwKB4C2WSw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> --> + <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/0.7.7/chartjs-plugin-zoom.min.js" integrity="sha512-8E9fPF4pjWxI0dpprpn4WYeciAMo2kh6xN0COFxvTfurMttjZzih/sBp+Fxu49Zr6IUSp4sqWY6KLecnqOCwxA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> --> + + <script + src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.2.0/chart.min.js" + integrity="sha512-VMsZqo0ar06BMtg0tPsdgRADvl0kDHpTbugCBBrL55KmucH6hP9zWdLIWY//OTfMnzz6xWQRxQqsUFefwHuHyg==" + crossorigin="anonymous" + referrerpolicy="no-referrer" + ></script> + <script + src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.0.0-rc/chartjs-plugin-zoom.min.js" + integrity="sha512-Vo3Q1pGza0B8qnI5DYBIV1o09d+S5W0gDu5azuXVIZsGPnFLUb+McK8dExyuqITZlgoS9ueRs98KDcwng/b4sw==" + crossorigin="anonymous" + referrerpolicy="no-referrer" + ></script> + + <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script> <script defer src="js/appCesium.js"></script> <script defer src="js/appChart.js"></script> - <!-- <script defer src="js/testzoom.js"></script> --> + <script defer src="js/createPlotlyPlots.js"></script> </head> <body class="sb-nav-fixed"> <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark"> @@ -118,18 +135,26 @@ </div> </div> </div> + <div class="row"> <div class="col-xl-6"> <div class="card mb-4"> <div class="card-header"> - <i class="fas fa-chart-line mr-1"></i> - Line Chart Example + <i class="fas fa-chart-area mr-1"></i> + Inflow with Chart.JS and Zoom Plugin </div> <div class="card-body"> - <div id="chart-apex-line" width="100%" height="40"></div> + <canvas + id="inflowChartCanvas" + style="max-width: 100%; max-height: 600px" + ></canvas> + <button id="reset_zoom" class="btn btn-light"> + Reset zoom + </button> </div> </div> </div> + <div class="col-xl-6"> <div class="card mb-4"> <div class="card-header"> @@ -137,51 +162,62 @@ Area Chart Example </div> <div class="card-body"> - <div id="chart-apex-heatmap" width="100%" height="40"></div> + <div + id="chart-apex-heatmap" + width="100%" + height="40" + style="max-width: 100%; max-height: 500px" + ></div> </div> </div> </div> + </div> + <!-- end row --> - <div class="col-xl-6"> + <div class="row"> + <div class="col-xl-12"> <div class="card mb-4"> <div class="card-header"> - <i class="fas fa-chart-area mr-1"></i> - Test Chart.js + <i class="fas fa-globe mr-1"></i> + PLotly Ribbon plot </div> <div class="card-body"> - <canvas id="lineChart" width="400" height="400"></canvas> - - <button id="reset_zoom_line">Reset zoom</button> - - <button id="disable_zoom_line">Disable zoom</button> - - <button id="enable_zoom_line">Enable zoom</button> - + <div + id="RibbonPlot" + width="100%" + height="40" + > + <!-- Plotly chart will be drawn inside this DIV --> + </div> </div> </div> </div> + </div> + <!-- end row --> - <!-- <div class="col-xl-6"> + <div class="row"> + <div class="col-xl-6"> <div class="card mb-4"> <div class="card-header"> <i class="fas fa-chart-area mr-1"></i> - Test Scatter Chart.js + 2d heatmap </div> - <div class="card-body" > - <canvas id="scatterChart" width="400" height="400"></canvas> - - <button id="reset_zoom">Reset zoom</button> - - <button id="disable_zoom">Disable zoom</button> - - <button id="enable_zoom">Enable zoom</button> + <div class="card-body"> + <div + id="heatmap2d" + width="100%" + height="40" + style="max-width: 100%; max-height: 600px" + > + <!-- Plotly chart will be drawn inside this DIV --> + </div> </div> </div> - </div> --> - - - + </div> </div> + <!-- end row --> + + <!-- </div> --> </div> </main> <footer class="py-4 bg-light mt-auto"> diff --git a/public/js/appChart.js b/public/js/appChart.js index fa0dad649618e1ac093612cf392b0635aabbcb30..b80dddc96a49288cd3e2843dbdf6b065a020abfc 100644 --- a/public/js/appChart.js +++ b/public/js/appChart.js @@ -441,7 +441,8 @@ followNextLink( // drawHeatMapAC2(observationArr); ///////////// use chart.js for line chart - +///// check this out : https://stackoverflow.com/questions/57343566/zoom-function-for-chart-js + //////////////////////////////// function renameKey(obj, oldKey, newKey) { obj[newKey] = obj[oldKey]; @@ -463,135 +464,237 @@ followNextLink( let jsonFromArr2 = jsonFromArr; jsonFromArr2.forEach((obj) => renameKey(obj, "1", "y")); + + - var ctx = document.getElementById("lineChart").getContext("2d"); - var lineChart = new Chart(ctx, { - type: "line", - data: { - datasets: [ - { - label: "Inflow (Vorlauf)", - data: [12, 19, 3, 5, 2, 3], - borderColor: ["rgba(255, 99, 132, 0.2)"], - fill: false, - }, - ], - }, - options: { - scales: { - y: { - beginAtZero: false, - }, - }, + /////////////////////////////////////////////////// + function prep2dHistogramData(jsonData) { + var resList = []; + + const L = jsonData.length; + + var startVal = 1; + var currentDay = 1; + var hourInMonth = 0; + + var x = []; + var y = []; + var z = []; + for (var d = 0; d < L; d++) { + let tmpDate = new Date(jsonData[d].x); + // let datum = tmpDate.getDate(); // gets the day of the month 1...31 + let hour = tmpDate.getHours(); + let day = tmpDate.getUTCDate(); + let month = tmpDate.getUTCMonth(); // gets the month as numeric value + + if (currentDay == day) { + x.push([startVal, startVal + 1]); + y.push([hourInMonth,hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + hourInMonth++; + } else { + resList.push({x:x, y:y, z:z } ); + var x = []; + var y = []; + var z = []; + currentMonth += 1; + startVal += 2; + hourInMonth = 0; + + x.push([startVal, startVal + 1]); + y.push([hourInMonth,hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + } - // pan: { - // enabled: true, - // mode: "x", - // speed: 10, - // threshold: 10, - // }, - // zoom: { - // enabled: true, - // drag: false, - // mode: "y", - // speed: 0.5, - // // sensitivity: 0.1, - // // limits: { - // // max: 10, - // // min: 0.5, - // // }, - // }, - }, - }); - + } // end of for loop + + // add results for last month as else statement will not be reached for the december + // as the condition d < L will be true before the condition currentMonth === month can be evaluated + + // re-activate following line when i have more than one data point for the next month + // resList.push({x:x, y:y, z:z } ); + + return resList; + } - $('#reset_zoom_line').click(function(){ - lineChart.resetZoom(); - console.log(lineChart); - }); - $('#disable_zoom_line').click(function(){ - lineChart.ctx.canvas.removeEventListener('wheel', lineChart._wheelHandler); - }); - $('#enable_zoom_line').click(function(){ - lineChart.ctx.canvas.addEventListener('wheel', lineChart._wheelHandler); - }); + /////////////////////////////////////////////////// + function prepRibbonData(jsonData) { + var resList = []; + + const L = jsonData.length; - + var startVal = 2; + var currentMonth = 0; + var hourInMonth = 0; + var x = []; + var y = []; + var z = []; + for (var d = 0; d < L; d++) { + let tmpDate = new Date(jsonData[d].x); + // let datum = tmpDate.getDate(); // gets the day of the month 1...31 + let hour = tmpDate.getHours(); + let month = tmpDate.getUTCMonth(); // gets the month as numeric value + + if (currentMonth == month) { + x.push([startVal, startVal + 1]); + y.push([hourInMonth,hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + hourInMonth++; + } else { + resList.push({x:x, y:y, z:z } ); + var x = []; + var y = []; + var z = []; + currentMonth += 1; + startVal += 2; + hourInMonth = 0; + + x.push([startVal, startVal + 1]); + y.push([hourInMonth,hourInMonth]); + z.push([jsonData[d].y, jsonData[d].y]); + } + + } // end of for loop + + // add results for last month as else statement will not be reached for the december + // as the condition d < L will be true before the condition currentMonth === month can be evaluated + + // re-activate following line when i have more than one data point for the next month + // resList.push({x:x, y:y, z:z } ); + + return resList; + } + /////////////////////////////////////////////////// + let datx=[]; + let daty=[]; + const MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + for (var u = 0; u<jsonFromArr.length ; u++){ + daty.push(jsonFromArr2[u].y); + let date = new Date(jsonFromArr2[u].x); + let datum = date.getDate(); + let month = MONTH[date.getMonth()]; + let hour = date.getHours() + ":00"; + let newDateStr = datum + "/" + month + "-" + hour; + datx.push(newDateStr); + } -///////////////////////////////////////// - -// var ctx_scatterChart = document.getElementById("scatterChart"); -// var scatterChart = new Chart(ctx_scatterChart, { -// type: 'bar', -// data: { -// labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], -// datasets: [{ -// label: '# of Votes', -// data: [12, 19, 3, 5, 2, 3], -// backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], -// borderColor: ["Blue", "Yellow", "Green", "Purple", "Orange", "Red"], -// borderWidth: 1, -// }] -// }, -// options: { -// scales: { -// yAxes: [{ -// ticks: { -// beginAtZero:false -// } -// }] -// }, -// // Container for pan options -// pan: { -// // Boolean to enable panning -// enabled: true, - -// // Panning directions. Remove the appropriate direction to disable -// // Eg. 'y' would only allow panning in the y direction -// mode: 'xy', - -// speed: 10 -// }, - -// // Container for zoom options -// zoom: { -// // Boolean to enable zooming -// enabled: true, -// // Zooming directions. Remove the appropriate direction to disable -// // Eg. 'y' would only allow zooming in the y direction -// mode: 'x', -// } -// } -// }); - - - -// $('#reset_zoom').click(function(){ -// scatterChart.resetZoom(); -// console.log(scatterChart); -// }); - -// $('#disable_zoom').click(function(){ -// scatterChart.ctx.canvas.removeEventListener('wheel', scatterChart._wheelHandler); -// }); - -// $('#enable_zoom').click(function(){ -// scatterChart.ctx.canvas.addEventListener('wheel', scatterChart._wheelHandler); -// }); + // $('#reset_zoom').click(function(){ + // scatterChart.resetZoom(); + // console.log(scatterChart); + // }); + // $('#disable_zoom').click(function(){ + // scatterChart.ctx.canvas.removeEventListener('wheel', scatterChart._wheelHandler); + // }); + // $('#enable_zoom').click(function(){ + // scatterChart.ctx.canvas.addEventListener('wheel', scatterChart._wheelHandler); + // }); + ////////////////////////////////////////// +// const chart1LineTitle = "Inlet flow (Vorlauf)"; +// const chart1LineYAxisTitle = "Temperature (°C)"; -////////////////////////////////////////// + + const inflowChart = new Chart('inflowChartCanvas', { + type: 'line', + data: { + labels: datx, + datasets: [{ + label: 'Inflow Temperature in °C', + data: daty, + fill: false, + borderColor: 'rgb(75, 192, 192,0.3)', + backgroundColor: 'rgba(153, 102, 255, 0.2)', + // tension: 0.1 + }] + }, + + options: { + // responsive: true, + scales: { + xAxes: [{ + display: true, + scaleLabel: { + display: true, + labelString: 'Month' + } + }], + yAxes: [{ + display: true, + scaleLabel: { + display: true, + labelString: 'Value' + } + }] + }, + + plugins: { + // title: { + // display: true, + // text: 'Inlet Flow Temperature' + // }, + + + zoom: { + pan: { + // Boolean to enable panning + enabled: true, + + // Panning directions. Remove the appropriate direction to disable + // Eg. 'y' would only allow panning in the y direction + mode: "xy", + + speed: 1, + }, + zoom: { + wheel: { + enabled: true, + }, + pinch: { + enabled: false + }, + mode: 'x', + } + } + + } // end of plugins + } // end of options + }); + $('#reset_zoom').click(function(){ + inflowChart.resetZoom(); + }); + // drawHeatMapAC2(observationArr); + var loadJS = function(url, implementationCode, location){ + //url is URL of external file, implementationCode is the code + //to be called from the file, location is the location to + //insert the <script> element + + var scriptTag = document.createElement('script'); + scriptTag.src = url; + + scriptTag.onload = implementationCode; + scriptTag.onreadystatechange = implementationCode; + + location.appendChild(scriptTag); + }; + + var preppedData = prepRibbonData(jsonFromArr2); + + loadJS('js/createPlotlyPlots.js', makeRibbonPlot(preppedData), document.body); + loadJS('js/createPlotlyPlots.js', makeHeatmap(preppedData), document.body); + + + /////////////////////////////////////// }); // this closes the followLink.then ({ .... }) diff --git a/public/js/createPlotlyPlots.js b/public/js/createPlotlyPlots.js new file mode 100644 index 0000000000000000000000000000000000000000..b05d2bd2b9622beba1c6a7cd280595ba5cb1971d --- /dev/null +++ b/public/js/createPlotlyPlots.js @@ -0,0 +1,128 @@ +function makeRibbonPlot(dat) { + // https://plotly.com/javascript/ribbon-plots/ + var trace1 = { + x: dat[0].x, + y: dat[0].y, + z: dat[0].z, + name: "January", + // colorscale: dat[0].colorscale, + type: "surface", + showscale: false, + }; + var trace2 = { + name: "Feburary", + x: dat[1].x, + y: dat[1].y, + z: dat[1].z, + // colorscale: dat[1].colorscale, + type: "surface", + showscale: false, + }; + var trace3 = { + name: "March", + x: dat[2].x, + y: dat[2].y, + z: dat[2].z, + // colorscale: dat[2].colorscale, + type: "surface", + showscale: false, + }; + var trace4 = { + name: "April", + x: dat[3].x, + y: dat[3].y, + z: dat[3].z, + // colorscale: dat[3].colorscale, + type: "surface", + showscale: false, + }; + var trace5 = { + name: "May", + x: dat[4].x, + y: dat[4].y, + z: dat[4].z, + // colorscale: dat[4].colorscale, + type: "surface", + showscale: false, + }; + var trace6 = { + name: "June", + x: dat[5].x, + y: dat[5].y, + z: dat[5].z, + // colorscale: dat[5].colorscale, + type: "surface", + showscale: false, + }; + + var data = [trace1, trace2, trace3, trace4, trace5, trace6]; + + var layout = { + title: "Inlet flow (per month)", + showlegend: true, + autosize: true, + width: 1400, + height: 800, + xaxis: { + tickmode: "array", + tickvals: [2.5, 4.5, 6.5, 8.5, 10.5, 12.5], + ticktext: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], + }, + hoverlabel: { + bgcolor: "black", + }, + scene: { + xaxis: { + title: "Month ", + tickmode: "array", + tickvals: [2.5, 4.5, 6.5, 8.5, 10.5, 12.5], + ticktext: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], + }, + yaxis: { title: "Hours in a month" }, + zaxis: { title: "Temperature (°C)" }, + }, + }; + Plotly.newPlot("RibbonPlot", data, layout); + + function make2dHistogram(dat) { + ////////////////////////////// + // make heatmap or 2d histogram plot + + var x = []; + var y = []; + for (var i = 0; i < 500; i++) { + x[i] = Math.random(); + y[i] = Math.random() + 1; + } + + var data = [ + { + x: x, + y: y, + z: x, + type: "histogram2d", // try this type as well 'histogram2dcontour' or this one 'histogram2d' + }, + ]; + Plotly.newPlot("heatmap2d", data); + } + + ///////////////////////////////////// + + function makeHeatmap(dat) { + var data = [ + { + z: [ + [1, null, 30, 50, 1], + [20, 1, 60, 80, 30], + [30, 60, 1, -10, 20], + ], + x: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], + y: ["Morning", "Afternoon", "Evening"], + type: "heatmap", + hoverongaps: false, + }, + ]; + + Plotly.newPlot("heatmap2d", data); + } +} diff --git a/public/js/prepRibbonData.js b/public/js/prepRibbonData.js new file mode 100644 index 0000000000000000000000000000000000000000..29b33e1a252f6a54434e06666ae9a723991ee871 --- /dev/null +++ b/public/js/prepRibbonData.js @@ -0,0 +1,39 @@ +function prepRibbonData(jsonData) { + let resList = []; + + let resJson = { + x: [], + y: [], + z: [], + }; + + const L = jsonData.length; + + var startVal = 2; + var currentMonth = 0; + + for (var d = 0; d < L; d++) { + let tmpDate = new Date(jsonData[d].x); + // let datum = tmpDate.getDate(); // gets the day of the month 1...31 + let month = date.getMonth(); // gets the month as numeric value + + if (currentMonth === month) { + resJson.x.push([startVal, startVal + 1]); + resJson.y.push([tmpDate, tmpDate]); + resJson.z.push([jsonData[d].y, jsonData[d].y]); + } else { + resList.push(resJson); + resJson.x = []; + resJson.y = []; + resJson.z = []; + currentMonth += 1; + startVal += 2; + } + } // end of for loop + + // add results for last month as else statement will not be reached for the december + // as the condition d < L will be true before the condition currentMonth === month can be evaluated +// resList.push(resJson); + + return resList; +} diff --git a/test.html b/test.html index 8f938180d98bca3ebe1cccbee00e09ae1a5b095a..4fdb6cfea5d6fd2bebdffd436d63f2a0d2e25c73 100644 --- a/test.html +++ b/test.html @@ -1,50 +1,18 @@ <!DOCTYPE html> <html lang="en"> <head> - <meta charset="UTF-8"> - <meta http-equiv="X-UA-Compatible" content="IE=edge"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - - - <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> - <!-- chart.js library --> - <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script> - <script src="https://npmcdn.com/Chart.Zoom.js@0.3.0/Chart.Zoom.min.js"></script> - <!-- <script defer src="js/testzoom.js"></script> --> - - - - - - <title>Document</title> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Document</title> + <!-- Load plotly.js into the DOM --> + <script src='https://cdn.plot.ly/plotly-latest.min.js'></script> + <script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js'></script> + <script src='js/test.js'></script> </head> -<body> - <h1>test</h1> -<h1>test</h1> - -<h1>test</h1> - -<div style="max-width: 600px; max-height: 400px;" class="myChartDiv"> - <canvas id="myChart" width="600" height="400"></canvas> -</div> - -<button id="reset_zoom"> - Reset zoom -</button> - -<button id="disable_zoom"> - Disable zoom -</button> - -<button id="enable_zoom"> - Enable zoom -</button> - -<h1>test</h1> - -<script defer src="js/testzoom.js"></script> +<body> + <div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div> </body> +</html> - -</html> \ No newline at end of file