Functionnal toolbar and indicators

This commit is contained in:
l_samenv
2024-08-06 13:53:58 +02:00
parent 2b829248cd
commit 83d45e511f
5 changed files with 250 additions and 75 deletions

View File

@ -1,6 +1,6 @@
.control-global{
width: 30px;
height: 30px;
width: 28px;
height: 28px;
border: 1px solid dimgray;
box-sizing: border-box;
transition: border 0.25s;

View File

@ -1,18 +1,40 @@
class DatesIndicator extends HTMLElement{
constructor(oldestTimestamp, newestTimestamp){
constructor(timestamp){
super();
this.oldestDate = this.timestampToString(oldestTimestamp);
this.newestDate = this.timestampToString(newestTimestamp);
this.formattedDate = this.timestampToString(timestamp);
}
dayNumberToName(dayNumber){
switch(dayNumber){
case 0:
return "Sun";
case 1:
return "Mon";
case 2:
return "Tue";
case 3:
return "Wed";
case 4:
return "Thu";
case 5:
return "Fri";
case 6:
return "Sat";
}
}
timestampToString(timestamp){
let date = new Date(timestamp);
return date.toUTCString();
let dayName = this.dayNumberToName(date.getDay());
let day = date.getDate();
let month = date.getMonth();
let year = date.getFullYear();
return dayName + ", " + day.toString().padStart(2, "0") + "/" + month.toString().padStart(2, "0") + "/" + year ;
}
update(oldestTimestamp, newestTimestamp){
this.oldestDate = this.timestampToString(oldestTimestamp);
this.newestDate = this.timestampToString(newestTimestamp);
update(timestamp){
this.formattedDate = this.timestampToString(timestamp);
this.render()
}
@ -24,9 +46,7 @@ class DatesIndicator extends HTMLElement{
this.innerHTML = `
<link rel="stylesheet" href="components/states_indicator/dates/dates.css">
<div class="dates">
${this.oldestDate}
->
${this.newestDate}
${this.formattedDate}
</div>
`
}

View File

@ -7,20 +7,21 @@
justify-content: flex-end;
}
.panel.graphics span{
margin: 0 1em;
.panel.graphics span:first-child{
display: none;
/* margin: 0 1em;
display: flex;
user-select: none;
-webkit-user-select: none;
-webkit-user-select: none; */
}
.panel.graphics div{
/* .panel.graphics div{
margin-left: 1em;
cursor: pointer;
}
} */
#control_bar{
height: 100%;
height: 28px;
background-color: dimgray;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
@ -28,7 +29,8 @@
padding-right: 12px;
display: flex;
column-gap: 5px;
margin-left: 100px;
margin-left: 120px;
margin-top: 2px;
}
/*********************/

View File

@ -24,12 +24,15 @@
text-align: center;
background-color: #303030;
color: white;
padding: 6px 6px 6px 6px;
/* padding: 6px 6px 6px 6px; */
position: absolute;
z-index: 20;
width: 100%;
height: 30px;
}
.panel:not(.graphics){
padding: 6px 6px 6px 6px;
}
.slide-close-icon {
transition: 0.4s;

View File

@ -217,26 +217,21 @@ let globalControls = (function (){
function loadControls(panel){
let controlBar = document.createElement("div");
controlBar.id = "control_bar"
controlBar.id = "control_bar";
panel.appendChild(controlBar);
let jumpControl = new Control("res/jump.png", "res/jump_blocked.png", "Jump", dummyCallback);
let goToNowControl = new Control("res/go_to_now.png", "res/go_to_now_blocked.png", "Go to now", dummyCallback);
let goToNowControl = new Control("res/go_to_now.png", "res/go_to_now_blocked.png", "Go to now", graphs.gotoNow);
let zoomInControl = new Control("res/zoom_in.png", "res/zoom_in_blocked.png", "Zoom in", dummyCallback);
let zoomOutControl = new Control("res/zoom_out.png", "res/zoom_out_blocked.png", "Zoon out", dummyCallback);
let shiftOlderControl = new Control("res/shift_older.png", "res/shift_older_blocked.png", "Shift to older", dummyCallback);
let shiftNewerControl = new Control("res/shift_newer.png", "res/shift_newer_blocked.png", "Shift to newer", dummyCallback);
let zoomInControl = new Control("res/zoom_in.png", "res/zoom_in_blocked.png", "Zoom in (time)", graphs.zoomIn);
let zoomOutControl = new Control("res/zoom_out.png", "res/zoom_out_blocked.png", "Zoon out (time)", graphs.zoomOut);
let shiftOlderControl = new Control("res/shift_older.png", "res/shift_older_blocked.png", "Shift to older", graphs.shiftOlder);
let shiftNewerControl = new Control("res/shift_newer.png", "res/shift_newer_blocked.png", "Shift to newer", graphs.shiftNewer);
let xyControl = new Control("res/y_direction.png", "res/x_direction.png", "Time<->Y zoom", dummyCallback, dummyCallback);
let cursorControl = new Control("res/remove_cursor.png", "res/remove_cursor_blocked.png", "Remove cursor",dummyCallback);
let legendsControl = new Control("res/display_legends.png", "res/remove_legends.png", "Legends", dummyCallback, dummyCallback);
let now = Date.now();
let old = now - 1000*3600;
let dates = new DatesIndicator(old, now);
let liveState = new LiveStateIndicator();
let xyControl = new Control("res/y_direction.png", "res/x_direction.png", "Time<->Y zoom (one graph)", graphs.toggleZoomMode, graphs.toggleZoomMode);
let cursorControl = new Control("res/remove_cursor.png", "res/remove_cursor_blocked.png", "Remove cursor", graphs.removeCursor);
let legendsControl = new Control("res/display_legends.png", "res/remove_legends.png", "Legends", graphs.displayAllLegends, graphs.hideAllLegends);
controlBar.appendChild(jumpControl)
controlBar.appendChild(goToNowControl)
@ -253,12 +248,6 @@ let globalControls = (function (){
controlBar.appendChild(legendsControl);
legendsControl.changeToAlt();
panel.appendChild(dates)
panel.appendChild(liveState);
liveState.changeToDisable();
liveState.style.marginLeft = "auto"; //sticks element to the right
dates.style.marginLeft = "auto";
controlsMap[jumpKey] = jumpControl;
controlsMap[goToNowKey] = goToNowControl;
controlsMap[zoomInKey] = zoomInControl;
@ -267,7 +256,7 @@ let globalControls = (function (){
controlsMap[shiftNewerKey] = shiftNewerControl;
controlsMap[xyKey] = xyControl;
controlsMap[cursorKey] = cursorControl;
controlsMap[legendsKey] = legendsControl;
controlsMap[legendsKey] = legendsControl;
}
function getControlsMap(){
@ -280,6 +269,39 @@ let globalControls = (function (){
}
})();
let datesKey = "dates-indicator";
let liveKey = "live-indicator";
let globalIndicators = (function (){
let indicatorsMap = {}
function loadIndicators(panel){
let leftDate = Date.now() - 30*60*1000;
let datesIndicator = new DatesIndicator(leftDate);
let liveIndicator = new LiveStateIndicator();
panel.appendChild(datesIndicator);
panel.appendChild(liveIndicator);
liveIndicator.changeToDisable();
liveIndicator.style.marginLeft = "auto"; //sticks element to the right
datesIndicator.style.marginLeft = "auto";
indicatorsMap[datesKey] = datesIndicator;
indicatorsMap[liveKey] = liveIndicator;
}
function getIndicatorsMap(){
return indicatorsMap;
}
return {
loadIndicators: loadIndicators,
getIndicatorsMap: getIndicatorsMap
}
})()
let graphs = (function (){
let dataset_to_graph_map = {}; // a dictionnary mapping a variable name to a two values array, containing its graph index and its position inside the graph
let blocks, liveMode=true, top_vars=[], bottom_vars=[];
@ -305,6 +327,8 @@ let graphs = (function (){
let resolution = undefined;
let created = false;
let container = document.createElement('div');
container.classList.add("graphs-container");
@ -398,11 +422,17 @@ let graphs = (function (){
* @param {boolean} mode - Tells if we are in live mode or not
*/
function setLiveMode(mode=null) {
if (mode !== null) liveMode = mode;
if (mode !== null){
liveMode = mode;
if(mode) globalIndicators.getIndicatorsMap()[liveKey].changeToEnable();
else globalIndicators.getIndicatorsMap()[liveKey].changeToDisable();
}
if (liveMode && cursorLinePos === null)
gotoNowElm.innerHTML = '';
// gotoNowElm.innerHTML = '';
globalControls.getControlsMap()[goToNowKey].changeToAlt();
else
gotoNowElm.innerHTML = 'go to now';
// gotoNowElm.innerHTML = 'go to now';
globalControls.getControlsMap()[goToNowKey].changeToMain();
}
/**
@ -564,6 +594,7 @@ let graphs = (function (){
function setMinMax(min, max){
currentMaxTime = max;
currentMinTime = min;
globalIndicators.getIndicatorsMap()[datesKey].update(currentMinTime);
for (let gr of graph_array) {
if (gr) gr.setMinMax(min, max);
}
@ -594,7 +625,8 @@ let graphs = (function (){
legendFlag = true;
let trect = evt.target.getBoundingClientRect();
let X = evt.clientX - trect.x, Y = evt.clientY - trect.y;
showLegends(true, false);
displayAllLegends();
// showLegends(true, false);
cursorLine(X);
setLiveMode();
update();
@ -720,6 +752,36 @@ let graphs = (function (){
}
}
function zoomIn(){
console.log("Zoomed in !");
let someGraph = graph_array[0];
let xTk = someGraph.chart.options.scales.xAxes[0].ticks;
let pZoom = 0.2; //window width for the zoom (a proportion of the current window, centered)
let delta = (xTk.max - xTk.min)*pZoom/2;
xTk.max -= delta;
xTk.min += delta;
if (liveMode && xTk.max < lastTime) setLiveMode(false);
setMinMax(xTk.min, xTk.max);
updateAuto();
}
function zoomOut(){
console.log("Zoomed out !");
let someGraph = graph_array[0];
let xTk = someGraph.chart.options.scales.xAxes[0].ticks;
let pZoom = 0.2; //window width for the zoom (a proportion of the current window, centered)
let delta = (xTk.max - xTk.min)*pZoom/2;
xTk.max += delta;
xTk.min -= delta;
if (liveMode && xTk.max < lastTime) setLiveMode(false);
setMinMax(xTk.min, xTk.max);
updateAuto();
}
/**
* Function called at each mouse wheel step.
* If zoom mode in x mode, disables liveMode if the visualisaiton window is older than the last known value and sets axis min and max
@ -778,6 +840,32 @@ let graphs = (function (){
resolution = Math.ceil((timeDelta / container.getBoundingClientRect().width)/1000)
}
function shiftOlder(){
let someGraph = graph_array[0];
let xTk = someGraph.chart.options.scales.xAxes[0].ticks;
let pShift = 0.2; //shift size the pan (a proportion of the current window)
let delta = (xTk.max - xTk.min)*pShift;
xTk.max -= delta;
xTk.min -= delta;
if (liveMode && xTk.max < lastTime) setLiveMode(false);
setMinMax(xTk.min,xTk.max);
updateAuto();
}
function shiftNewer(){
let someGraph = graph_array[0];
let xTk = someGraph.chart.options.scales.xAxes[0].ticks;
let pShift = 0.2; //shift size the pan (a proportion of the current window)
let delta = (xTk.max - xTk.min)*pShift;
xTk.max += delta;
xTk.min += delta;
if (liveMode && xTk.max < lastTime) setLiveMode(false);
setMinMax(xTk.min,xTk.max);
updateAuto();
}
/**
* The function called when the viewing window is moved by the mouse.
*
@ -826,6 +914,7 @@ let graphs = (function (){
*/
function gotoNow() {
cursorLine(null);
globalControls.getControlsMap()[cursorKey].changeToAlt();
if (!liveMode) {
setMinMax(graphs.now() - (currentMaxTime - currentMinTime), graphs.now());
}
@ -877,51 +966,58 @@ let graphs = (function (){
activateUpdates();
container.parentNode.querySelector('.panel').classList.add('graphics');
let graphicsPanel = container.parentNode.querySelector('.panel')
graphicsPanel.classList.add('graphics');
if(!created){
globalControls.loadControls(graphicsPanel);
globalIndicators.loadIndicators(graphicsPanel);
}
gotoNowElm.addEventListener('click', gotoNow);
// gotoNowElm.addEventListener('click', gotoNow);
//gotoNowElm.innerHTML = "go to now";
container.parentNode.querySelector('.panel span').appendChild(gotoNowElm);
// container.parentNode.querySelector('.panel span').appendChild(gotoNowElm);
// Removes the cursor then applies the changes
function removeCursor(evt=null) {
graphs.cursorLine(null);
graphs.update();
}
// function removeCursor(evt=null) {
// graphs.cursorLine(null);
// graphs.update();
// }
if (isTouchDevice) {
doubleTap(removeCursor);
} else {
window.addEventListener('dblclick', removeCursor);
showLegends(true, false);
adjustLegends();
let zoomMode = document.createElement('div');
// let zoomMode = document.createElement('div');
/**
* Sets the HTML button for the y-zoom depending on the current mode
*/
function setInnerZoomMode(){
if (currentZoomMode == 'y') {
zoomMode.innerHTML = "<strong>&#9746;</strong> y-zoom";
} else {
zoomMode.innerHTML = "<strong>&#9744;</strong> y-zoom";
}
prevTime = null; // reset zoom speed time
}
setInnerZoomMode();
// function setInnerZoomMode(){
// if (currentZoomMode == 'y') {
// zoomMode.innerHTML = "<strong>&#9746;</strong> y-zoom";
// } else {
// zoomMode.innerHTML = "<strong>&#9744;</strong> y-zoom";
// }
// prevTime = null; // reset zoom speed time
// }
// setInnerZoomMode();
/**
* Inverts the zoom mode (x<->y)
*/
function toggleZoomMode(){
if (currentZoomMode == 'y')
currentZoomMode = 'x';
else
currentZoomMode = 'y';
setInnerZoomMode();
for (let gr of graph_array) {
if (gr) gr.setZoomMode(currentZoomMode);
}
}
zoomMode.addEventListener('click', toggleZoomMode);
container.parentNode.querySelector('.panel span').appendChild(zoomMode);
// function toggleZoomMode(){
// if (currentZoomMode == 'y')
// currentZoomMode = 'x';
// else
// currentZoomMode = 'y';
// setInnerZoomMode();
// for (let gr of graph_array) {
// if (gr) gr.setZoomMode(currentZoomMode);
// }
// }
// zoomMode.addEventListener('click', toggleZoomMode);
// container.parentNode.querySelector('.panel span').appendChild(zoomMode);
}
// The cross to display "main" panel at the location of the graphs
@ -943,7 +1039,39 @@ let graphs = (function (){
console.log("MAIN")
currentSwiper.slideNext();
});
container.parentNode.querySelector('.panel span').appendChild(gotoMainElm);
// container.parentNode.querySelector('.panel span').appendChild(gotoMainElm);
if(!created){
graphicsPanel.appendChild(gotoMainElm);
created = true;
}
}
function setInnerZoomMode(){
if (currentZoomMode == 'y') {
globalControls.getControlsMap()[xyKey].changeToAlt();
} else {
globalControls.getControlsMap()[xyKey].changeToMain();
}
prevTime = null; // reset zoom speed time
}
// Callbacks
function toggleZoomMode(){
if (currentZoomMode == 'y')
currentZoomMode = 'x';
else
currentZoomMode = 'y';
setInnerZoomMode();
for (let gr of graph_array) {
if (gr) gr.setZoomMode(currentZoomMode);
}
}
function removeCursor(evt=null) {
graphs.cursorLine(null);
globalControls.getControlsMap()[cursorKey].changeToAlt();
graphs.update();
}
/**
@ -981,6 +1109,16 @@ let graphs = (function (){
//bringToFront(null);
}
function displayAllLegends(){
showLegends(true, false);
globalControls.getControlsMap()[legendsKey].changeToAlt();
}
function hideAllLegends(){
showLegends(false, false);
globalControls.getControlsMap()[legendsKey].changeToMain();
}
/**
* Adjust the legend window depending on the position of the last legend
*/
@ -1080,6 +1218,7 @@ let graphs = (function (){
cursorElement.style.display = 'block';
cursorElement.style.left = (cursorLinePos - 1) + 'px';
cursorElement.style.height = window.innerHeight + 'px';
globalControls.getControlsMap()[cursorKey].changeToMain();
}
return cursorLinePos;
}
@ -1141,6 +1280,16 @@ let graphs = (function (){
setLiveMode: setLiveMode,
cursorLine: cursorLine,
bringToFront: bringToFront,
// Exposing callbacks for controls and indicators
gotoNow: gotoNow,
displayAllLegends: displayAllLegends,
hideAllLegends: hideAllLegends,
toggleZoomMode: toggleZoomMode,
removeCursor: removeCursor,
zoomOut: zoomOut,
zoomIn: zoomIn,
shiftOlder: shiftOlder,
shiftNewer: shiftNewer,
}
})();
@ -1484,6 +1633,7 @@ function Graph(gindex, container, x_label, y_label, tag, scaleType = "linear"){
} else {
graphs.cursorLine(null);
legend.style.display = 'none';
globalControls.getControlsMap()[legendsKey].changeToMain();
}
}