additional_plugins/serendipity_event_osm/ressources/osm.js

192 lines
5.9 KiB
JavaScript
Raw Normal View History

2020-01-31 06:12:07 +01:00
const dateToColor = date => {
2020-02-27 02:16:38 +01:00
const minDate = new Date(date.getFullYear(), date.getMonth() - 1, 0);
const maxDate = new Date(date.getFullYear(), date.getMonth(), 0);
return "hsl(" + ((date.getTime() - minDate.getTime()) / (maxDate.getTime() - minDate.getTime())).toFixed(3) + "turn, 100%, 50%)";
2020-01-31 06:12:07 +01:00
};
2020-09-16 11:23:34 +02:00
window.addEventListener("load", () => {
2020-02-27 02:16:38 +01:00
document.querySelectorAll("div.map").forEach(divMap => {
const popup = document.createElement("div");
popup.setAttribute("class", "ol-popup");
const overlay = new ol.Overlay({
element: popup
});
popup.onclick = () => {
overlay.setPosition(undefined);
};
2020-01-31 06:12:07 +01:00
const dataset = divMap.dataset;
const articles = geo.articles
.filter(article => ["all", "none"].includes(dataset.category) || article.categories.includes(parseInt(dataset.category)));
const tracks = geo.tracks
.filter(track => dataset.path.split("\n").some(y => track.url.startsWith(y)));
const features = articles.map((article, id) => {
const feature = new ol.Feature(new ol.geom.Point(ol.proj.fromLonLat(article.location.reverse())));
2020-02-27 02:16:38 +01:00
feature.setId(id);
return feature;
});
2020-01-31 06:12:07 +01:00
2020-02-27 02:16:38 +01:00
const osmSource = new ol.source.OSM();
const layers = [
new ol.layer.Tile({source: osmSource, preload: Infinity}),
2020-02-27 02:16:38 +01:00
new ol.layer.Vector({
source: new ol.source.Vector({features: features}),
2020-02-27 02:16:38 +01:00
style: feature => {
const id = feature.getId();
const article = articles[id];
const date = new Date(article.date * 1000);
2020-01-31 06:12:07 +01:00
2020-02-27 02:16:38 +01:00
return new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({color: dateToColor(date)})
})
});
2020-08-13 08:57:17 +02:00
},
2020-02-27 02:16:38 +01:00
zIndex: Infinity
})
];
const unixTime = Date.now() / 1000;
for (const track of tracks) {
const source = new ol.source.Vector({
url: track.url,
format: new ol.format.GPX()
});
source.on("featuresloadend", event => {
track.distance = event.features
.filter(feature => feature.getGeometry().getType() === "MultiLineString")
.map(feature => ol.sphere.getLength(feature.getGeometry()))
.reduce((a, b) => a + b, 0);
});
const color = dateToColor(new Date(track.date * 1000));
const lineDash = track.date > unixTime ? [3, 6] : undefined;
const layer = new ol.layer.VectorImage({
source: source,
style: feature => feature.getGeometry().getType() === "MultiLineString"
? new ol.style.Style({
stroke: new ol.style.Stroke({
2022-05-19 02:33:23 +02:00
color: color,
width: 3,
2022-05-19 02:33:23 +02:00
lineDash: lineDash
})
})
: undefined
2020-02-27 02:16:38 +01:00
});
layers.push(layer);
}
const map = new ol.Map({
controls: ol.control.defaults.defaults({rotate: false}).extend([
2020-02-27 02:16:38 +01:00
new ol.control.FullScreen(),
new ol.control.OverviewMap({
layers: [
new ol.layer.Tile({source: osmSource})
]
}),
new ol.control.ScaleLine({
bar: true,
minWidth: 120
})
]),
interactions: ol.interaction.defaults.defaults({
2020-02-27 02:16:38 +01:00
altShiftDragRotate: false,
pinchRotate: false
}),
layers: layers,
overlays: [overlay],
target: divMap,
view: new ol.View({
center: ol.proj.fromLonLat([dataset.longitude, dataset.latitude]),
zoom: dataset.zoom
2020-02-27 02:16:38 +01:00
})
});
2020-02-27 02:16:38 +01:00
map.on("singleclick", event => {
const makeItem = object => {
2020-03-13 01:42:14 +01:00
const title = document.createTextNode(object.title);
2020-02-27 02:16:38 +01:00
const li = document.createElement("li");
2020-03-13 01:42:14 +01:00
li.appendChild(object.url !== null
? (() => {
const a = document.createElement("a");
a.appendChild(title);
a.setAttribute("href", object.url);
a.setAttribute("title",
(object.author !== undefined ? object.author + ", " : "")
+
new Date(object.date * 1000).toLocaleString(undefined, {
year: "numeric",
month: "long",
day: "2-digit",
hour: "2-digit",
minute: "2-digit"
})
+
(object.distance !== undefined
? ", " + (object.distance / 1000).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}) + "km"
: ""
)
);
2020-03-13 01:42:14 +01:00
return a;
})()
: title
)
2020-02-27 02:16:38 +01:00
return li;
};
2020-01-31 06:12:07 +01:00
const foundArticles = [];
const foundTracks = [];
2020-02-27 02:16:38 +01:00
map.forEachFeatureAtPixel(event.pixel, (feature, layer) => {
const id = feature.getId();
if (id !== undefined) {
foundArticles.push(id);
2020-02-27 02:16:38 +01:00
} else {
const url = layer.getSource().getUrl();
const id = tracks.findIndex(track => track.url === url);
foundTracks.push(id);
2020-02-27 02:16:38 +01:00
}
}, {hitTolerance: 10});
foundArticles.sort();
foundTracks.sort();
2020-02-27 01:32:55 +01:00
if (foundArticles.length || foundTracks.length) {
2020-02-27 02:16:38 +01:00
const initUl = title => {
const ul = document.createElement("ul");
ul.setAttribute("data-title", title);
return ul;
};
const ulArticles = foundArticles
.map(x => makeItem(articles[x]))
.reduce((x, y) => {x.appendChild(y); return x;}, initUl("Articles"));
const ulTracks = foundTracks
.map(x => makeItem(tracks[x]))
.reduce((x, y) => {x.appendChild(y); return x;}, initUl("Tracks"));
popup.innerHTML = (foundArticles.length ? ulArticles.outerHTML : "") + (foundTracks.length ? ulTracks.outerHTML : "");
overlay.setPosition(foundArticles.length ? ol.proj.fromLonLat(
[0, 1].map(latLon => foundArticles
.map(x => articles[x].location[latLon])
.reduce((x, y) => x + y, 0) / foundArticles.length
)
2020-02-27 02:16:38 +01:00
) : event.coordinate);
} else {
overlay.setPosition(undefined);
}
});
map.on("pointermove", event => {
const pixel = map.getEventPixel(event.originalEvent);
const hit = map.hasFeatureAtPixel(pixel, {hitTolerance: 10});
divMap.style.cursor = hit ? "pointer" : "";
});
map.on("rendercomplete", event => {
const distance = tracks
.filter(track => track.date < unixTime)
.map(track => track.distance)
.reduce((a, b) => a + b, 0);
document.querySelectorAll("span.distance-counter[data-category=\"" + dataset.category + "\"]").forEach(span => {
span.innerHTML = (distance / 1000).toFixed(0);
});
});
2020-02-27 02:16:38 +01:00
});
2020-08-13 08:57:17 +02:00
});