dateien aufgeteilt, basic layer

This commit is contained in:
mrbesen 2021-04-28 09:24:48 +02:00
parent 70628d637d
commit 65a25ce564
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
3 changed files with 313 additions and 293 deletions

View File

@ -4,75 +4,23 @@
<title>Speedtest.net map</title>
<meta charset="utf-8" />
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel="stylesheet" href="main.css" type="text/css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" type="text/css">
<style>
#statusbox p { margin: 0; }
.error {
color: red;
}
.success {
color: darkgreen;
}
.map {
height: 800px;
width: 100%;
}
.ol-popup {
position: absolute;
background-color: white;
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
min-width: 280px;
white-space: nowrap;
}
.ol-popup:after, .ol-popup:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
</head>
<body>
<h1>SpeedTest.net file mapper</h1>
<hr />
<form action="javascript:void(0);">
<input type="file" name="file" id="files" oninput="trigger(event)" multiple />
<button type="button" onclick="trigger(event)">OK</button>
<input type="file" name="file" id="files" accept=".csv,text/csv" oninput="trigger(event)" multiple />
<button type="button" onclick="triggerImport(event)">OK</button>
</form>
<h3>Status:</h3>
<div id="statusbox"></div>
<div id="overlaytest"></div>
<div id="layerlist">
</div>
<div id="map" class="map"></div>
<div id="popup" class="ol-popup">
@ -80,241 +28,6 @@
<div id="popup-content"></div>
</div>
<script>
//class defs
class Entry {
constructor(data) {
this.date = data[0].replaceAll("/", ".").replace(",", "");
this.conntype = data[1];
this.loc = [parseFloat(data[3]), parseFloat(data[2])]; // long, lat
this.speed = [parseFloat(data[4]), parseFloat(data[6])]; // dl, up
this.size = [parseInt(data[5]), parseInt(data[7])]; // dl, up
this.ping = parseInt(data[8]);
this.server = data[9];
this.intIP = data[10];
this.extIP = data[11];
this.url = data[12];
}
toHTML() {
return this.conntype.toUpperCase() + " [" + this.date + "] " + "<br />\n" + this.speedStr + "<br />\nPing: " + this.ping + "ms<br />\n<a target=\"_blank\"href=\"" + this.url + "\">result Page&#128279;</a><br />\n";
}
get speedStr() {
return this.speed[0].toFixed(2) + " Mbps ↓ / " + this.speed[1].toFixed(2) + " Mbps ↑";
}
};
/** @type {HTMLDivElement} */
var statusBox = document.getElementById("statusbox");
var overlaytest = document.getElementById("overlaytest");
var popupcontainer = document.getElementById('popup');
var popupcontent = document.getElementById('popup-content');
var popupcloser = document.getElementById('popup-closer');
var zoomstart = 15;
var dotradius = 5;
var isInit = false;
var entryList = [];
//init map
var overlay = new ol.Overlay({
element: popupcontainer,
autoPan: true,
autoPanAnimation: {
duration: 250,
},
});
popupcloser.onclick = function () {
popupcontent.innerHTML = "";
overlay.setPosition(undefined);
popupcloser.blur();
return false;
};
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([0, 0]),
zoom: zoomstart
}),
overlays: [overlay]
});
var highlightStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: dotradius,
fill: new ol.style.Fill({color: 'green'})
})
});
var defaultStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: dotradius,
fill: new ol.style.Fill({color: 'red'})
})
});
//liste of features, that have the highlighted style
var highlighted = [];
// event listener
map.on("pointermove", e => {
var newhighlighted = [];
//gather overlay information
var fids = []; //lsit of currently hovered feature ids
map.forEachFeatureAtPixel(e.pixel, feature => {
var fid = feature.getProperties().id;
fids.push(fid);
feature.setStyle(highlightStyle);
newhighlighted.push(feature);
})
if(newhighlighted.length > 0) {
//remove highlight style from non hovered elements
highlighted.filter(h => newhighlighted.indexOf(h) == -1).forEach(h => h.setStyle(defaultStyle));
highlighted = newhighlighted;
}
// display information
if(fids.length > 0) {
popupcontent.innerHTML = "";
overlay.setPosition(e.coordinate);
}
for(var i = 0; i < fids.length; ++i) {
var entry = entryList[fids[i]];
console.log(entry);
//print entry
popupcontent.innerHTML += entry.toHTML();
if(i+1 < fids.length)
popupcontent.innerHTML += "<hr />\n";
}
});
function showError(error) {
var span = document.createElement('p');
span.classList.add('error');
span.innerHTML = `Error: ${error}`;
statusBox.appendChild(span);
}
function showSuccess(success) {
var span = document.createElement('p');
span.classList.add('success');
span.innerHTML = `Success: ${success}`;
statusBox.appendChild(span);
}
function clearStatus() {
statusBox.innerHTML = "";
}
function addElement(data, features) {
var elem = new Entry(data);
var id = entryList.length;
entryList.push(elem);
var dot = ol.proj.fromLonLat(elem.loc);
if(!isInit) {
isInit = true;
map.setView(new ol.View({center: dot, zoom: zoomstart}));
console.log(dot);
}
var feat = new ol.Feature({
geometry: new ol.geom.Point(dot),
type: 'point',
id: id
});
features.push(feat);
}
function loadedFile(text) {
var lines = text.split("\n");
var features = [];
for(var i = 1; i < lines.length; ++i) {
var line = lines[i];
if(line.length < 10) continue;
var date = line.substr(1, 17);
line = line.substr(20);
var lineSplit = line.split(",");
lineSplit = [date ,... lineSplit];
addElement(lineSplit, features);
}
updateMap(features);
}
function updateMap(features) {
var sourceLayer = new ol.source.Vector({
features
});
var vectorLayer = new ol.layer.Vector({
source: sourceLayer,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 4,
fill: new ol.style.Fill({color: 'red'})
})
})
});
map.addLayer(vectorLayer);
}
function loadFile(file) {
console.log("loadFile: " + file.name);
console.log(file);
var text = file.text();
text.then(t => loadedFile(t));
}
function trigger(event) {
console.log("OK");
clearStatus();
isInit = false;
//try to read the files
var filelist = document.getElementById("files").files;
if(filelist.length == 0) {
showError("No file selected");
return false;
}
var successC = 0;
for(var i = 0; i < filelist.length; ++i) {
var f = filelist[i];
if(f.type == "text/csv") {
loadFile(f);
successC ++;
} else {
showError(`The file <i>${f.name}</i> is not in the csv format`);
}
}
showSuccess("Loaded " + successC + " files");
return false;
}
</script>
<script src="main.js"></script>
</body>
</html>

56
main.css Normal file
View File

@ -0,0 +1,56 @@
#statusbox p { margin: 0; }
.error {
color: red;
}
.success {
color: darkgreen;
}
.map {
height: 800px;
width: 100%;
}
/* popup related */
.ol-popup {
position: absolute;
background-color: white;
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
padding: 15px;
border-radius: 10px;
border: 1px solid #cccccc;
bottom: 12px;
left: -50px;
min-width: 280px;
white-space: nowrap;
}
.ol-popup:after, .ol-popup:before {
top: 100%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ol-popup:after {
border-top-color: white;
border-width: 10px;
left: 48px;
margin-left: -10px;
}
.ol-popup:before {
border-top-color: #cccccc;
border-width: 11px;
left: 48px;
margin-left: -11px;
}
.ol-popup-closer {
text-decoration: none;
position: absolute;
top: 2px;
right: 8px;
}
button.off {
background-color: red; /* placeholder */
}

251
main.js Normal file
View File

@ -0,0 +1,251 @@
//class defs
class Entry {
constructor(data) {
this.date = data[0].replaceAll("/", ".").replace(",", "");
this.conntype = data[1].toUpperCase();
this.loc = [parseFloat(data[3]), parseFloat(data[2])]; // long, lat
this.speed = [parseFloat(data[4]), parseFloat(data[6])]; // dl, up
this.size = [parseInt(data[5]), parseInt(data[7])]; // dl, up
this.ping = parseInt(data[8]);
this.server = data[9];
this.intIP = data[10];
this.extIP = data[11];
this.url = data[12];
}
toHTML() {
return this.conntype + " [" + this.date + "] " + "<br />\n" + this.speedStr + "<br />\nPing: " + this.ping + "ms<br />\n<a target=\"_blank\"href=\"" + this.url + "\">result Page&#128279;</a><br />\n";
}
get speedStr() {
return this.speed[0].toFixed(2) + " Mbps ↓ / " + this.speed[1].toFixed(2) + " Mbps ↑";
}
};
/** @type {HTMLDivElement} */
var statusBox = document.getElementById("statusbox");
var layerlist = document.getElementById("layerlist");
var popupcontainer = document.getElementById('popup');
var popupcontent = document.getElementById('popup-content');
var popupcloser = document.getElementById('popup-closer');
var zoomstart = 15;
var dotradius = 5;
var isInit = false;
var entryList = [];
var layers = {}; //mapping of layers: name -> layerobj
//init map
var overlay = new ol.Overlay({
element: popupcontainer,
autoPan: true,
autoPanAnimation: {
duration: 250,
},
});
popupcloser.onclick = function () {
popupcontent.innerHTML = "";
overlay.setPosition(undefined);
popupcloser.blur();
return false;
};
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: ol.proj.fromLonLat([0, 0]),
zoom: zoomstart
}),
overlays: [overlay]
});
var highlightStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: dotradius,
fill: new ol.style.Fill({color: 'green'})
})
});
var defaultStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: dotradius,
fill: new ol.style.Fill({color: 'red'})
})
});
//liste of features, that have the highlighted style
var highlighted = [];
// event listener
map.on("pointermove", e => {
var newhighlighted = [];
//gather overlay information
var fids = []; //list of currently hovered feature ids
map.forEachFeatureAtPixel(e.pixel, feature => {
var fid = feature.getProperties().id;
fids.push(fid);
feature.setStyle(highlightStyle);
newhighlighted.push(feature);
})
if(newhighlighted.length > 0) {
//remove highlight style from non hovered elements
highlighted.filter(h => newhighlighted.indexOf(h) == -1).forEach(h => h.setStyle(defaultStyle));
highlighted = newhighlighted;
}
// display information
if(fids.length > 0) {
popupcontent.innerHTML = "";
overlay.setPosition(e.coordinate);
}
for(var i = 0; i < fids.length; ++i) {
var entry = entryList[fids[i]];
//console.log(entry);
//print entry
popupcontent.innerHTML += entry.toHTML();
if(i+1 < fids.length)
popupcontent.innerHTML += "<hr />\n";
}
});
function showError(error) {
var span = document.createElement('p');
span.classList.add('error');
span.innerHTML = `Error: ${error}`;
statusBox.appendChild(span);
}
function showSuccess(success) {
var span = document.createElement('p');
span.classList.add('success');
span.innerHTML = `Success: ${success}`;
statusBox.appendChild(span);
}
function clearStatus() {
statusBox.innerHTML = "";
}
function addElement(elem, features) {
var id = entryList.length;
entryList.push(elem);
var dot = ol.proj.fromLonLat(elem.loc);
if(!isInit) {
isInit = true;
map.setView(new ol.View({center: dot, zoom: zoomstart}));
console.log(dot);
}
var feat = new ol.Feature({
geometry: new ol.geom.Point(dot),
type: 'point',
id: id
});
features.push(feat);
}
function loadedFile(text, filename) {
var lines = text.split("\n");
var featuresLTE = [];
var features = [];
for(var i = 1; i < lines.length; ++i) {
var line = lines[i];
if(line.length < 10) continue;
var date = line.substr(1, 17);
line = line.substr(20);
var lineSplit = line.split(",");
lineSplit = [date ,... lineSplit];
var elem = new Entry(lineSplit);
if(elem.conntype == "LTE") {
addElement(elem, featuresLTE);
} else {
addElement(elem, features);
}
}
addLayer(featuresLTE, filename + " LTE");
addLayer(features, filename + " nonLTE");
}
function addLayer(features, name) {
var sourceLayer = new ol.source.Vector({
features
});
var vectorLayer = new ol.layer.Vector({
source: sourceLayer,
style: defaultStyle
});
layers[name] = vectorLayer;
map.addLayer(vectorLayer);
//add button to list
layerlist.innerHTML += `${name}: <button type="button" onclick="triggerLayer(event, '${name}')">toggle</button><button type="button" onclick="triggerLayer(event, '${name}')">30%</button><br />\n`
}
function loadFile(file) {
console.log("loadFile: " + file.name);
console.log(file);
var text = file.text();
text.then(t => loadedFile(t, file.name));
}
function triggerImport(event) {
clearStatus();
isInit = false;
//try to read the files
var filelist = document.getElementById("files").files;
if(filelist.length == 0) {
showError("No file selected");
return false;
}
var successC = 0;
for(var i = 0; i < filelist.length; ++i) {
var f = filelist[i];
try {
loadFile(f);
++successC;
} catch(e) {
showError(`The file <i>${f.name}</i> is not in the csv format`);
}
}
if(successC > 0)
showSuccess("Loaded " + successC + " files");
return false;
}
function triggerLayer(btnevent, layername) {
var btn = btnevent.target;
var btnname = btn.innerText;
var mode = btn.classList.contains("off"); // true = layer is off, false = layer is on
if(mode) btn.classList.remove("off");
else btn.classList.add("off");
var layer = layers[layername];
if(btnname == "30%")
layer.setOpacity(mode ? 1 : 0.3);
else
layer.setVisible(mode);
}