Skip to content

Instantly share code, notes, and snippets.

@fxi
Created February 20, 2019 11:02
Show Gist options
  • Save fxi/27467b2508810de4c3d43cdf570a5a6a to your computer and use it in GitHub Desktop.
Save fxi/27467b2508810de4c3d43cdf570a5a6a to your computer and use it in GitHub Desktop.
Custom code to animate a serie of images in MapX custom code view
/**
* Custom method for custom view in map-x
* Parameters for onInit and onClose function ;
* @param {Object} o Options
* @param {Object} o.view Map-x view object
* @param {Object} o.map mapbox-gl map object
* @param {String} o.idView If of the view
* @param {String} o.idSource Id of the source
* @param {Element} o.elLegend Element containing the legend
*
*/
return {
onClose: function(o) {
console.log("Custom view closed");
/**
* Remove source and layers
*/
o._destroy();
},
onInit: function(o) {
console.log("Custom view added");
var busy = false;
var layers = [
"Mogadisho_Landsat7_20010628-531",
"Mogadisho_Landsat7_20031227-531",
"Mogadisho_Landsat7_20040924-531",
"Mogadisho_Landsat7_20070309-531",
"Mogadisho_Landsat7_20090314-531",
"Mogadisho_Landsat7_20120118-531",
"Mogadisho_Landsat7_20140616-531",
"Mogadisho_Landsat7_20160214-531",
"Mogadisho_Landsat7_20180102-531"
];
var stepsBack = 9;
var images;
var map = o.map;
var stepCurrent = 0;
var idCurrent;
var bbxCurrent;
var renderedOnce = false;
/**
* Set custom legend
*/
o.elLegend.innerText = "Time filter (2001 - 2018)";
o.elLegend.style = "margin-bottom:15px";
/**
* Init
*/
makeInput();
recalc();
/**
* Destroy function
*/
o._destroy = function() {
console.log("destroy");
map.off("moveend", recalc);
removeLayers();
};
/**
* Patch events
* destroy is not called when view is unchecked OR when layer stack is evaluted...
*/
if (!window.patchDestroy) {
window.patchDestroy = {};
}
if (window.patchDestroy[o.idView]) {
var d = window.patchDestroy[o.idView];
if (d instanceof Function) {
d();
window.patchDestroy[o.id] = null;
}
}
window.patchDestroy[o.idView] = function() {
o._destroy()
}
var elCheck = document.getElementById("check_view_enable_MX-9NTPU-NYUM0-KAS45")
elCheck.addEventListener("change", patchDestroy);
function patchDestroy() {
if (!this.checked) {
o._destroy();
this.removeEventListener("change", patchDestroy);
}
}
/**
*
* HELPERS
*/
function recalc() {
if (!isBusy() && extentChanged()) {
isBusy(true);
console.log("recalc!");
fetchAll(layers)
.then(createLayers)
.then(showLayer)
.then(function() {
map.once("moveend", recalc);
});
}
}
function firstRender() {
if (renderedOnce === false) {
renderedOnce = true;
return true;
}
return false;
}
function createLayers(images) {
return new Promise(function(resolve, reject) {
images.forEach(function(image) {
var idNew = o.idView + "@" + image.step;
var l = {
id: idNew,
source: {
type: 'image',
url: image.url,
coordinates: image.bbx
},
type: 'raster',
paint: {
'raster-opacity': 0,
'raster-opacity-transition': {
'duration': 1000
}
}
};
removeLayer(idNew);
map.addLayer(l, "mxlayers");
});
resolve(0);
});
}
function showLayer(step) {
isBusy(true);
step = step && step.constructor === Event ?
this.value * 1 :
step * 1 ||
stepCurrent || 0;
stepCurrent = step;
var idStep = o.idView + "@" + step;
forEachLayers(function(layer) {
var id = layer.id;
if (idStep === id) {
idCurrent = id;
map.setPaintProperty(id,
'raster-opacity',
1);
} else {
setTimeout(function() {
if (id !== idCurrent) {
map.setPaintProperty(id,
'raster-opacity',
0);
}
}, 100);
}
});
isBusy(false);
}
function forEachLayers(cb) {
/**
* Get all currently displayed layer with the same
* prefix ID
*/
var layers = mx.helpers.getLayerByPrefix({
id: 'map_main',
prefix: o.idView
});
layers.forEach(function(layer) {
cb(layer);
});
}
function removeLayers() {
forEachLayers(function(layer) {
removeLayer(layer.id);
});
}
function removeLayer(id) {
var src = map.getSource(id);
var ol = map.getLayer(id);
if (ol) {
map.removeLayer(id);
}
if (src) {
map.removeSource(id);
}
}
function fetchAll(layers) {
var bbxArray = getBoundsLatLngArray();
return new Promise(function(resolve, reject) {
console.log("fetch all!");
var urlImages = [];
var loaded = 0;
function pushImageUrl(res) {
loaded++;
loadProgress(loaded / stepsBack);
urlImages.push({
step: res.pos,
layer: res.layer,
url: res.url,
bbx: bbxArray
});
if (loaded === stepsBack) {
resolve(urlImages);
}
}
for (var i = 0, iL = stepsBack; i < iL; i++) {
layer = layers[i];
getImageUrlBlob(layer, i)
.then(pushImageUrl);
}
});
}
function loadProgress(p) {
p = p * 100;
mx.helpers.progressScreen({
enable: p < 100,
id: "download_images",
percent: p,
text: " Downloading data ( " + Math.ceil(p) + "% )"
});
}
function makeInput() {
console.log("Create input !");
var elInputDate = document.createElement("INPUT");
elInputDate.setAttribute("type", "range");
elInputDate.setAttribute("min", "0");
elInputDate.setAttribute("max", stepsBack - 1);
elInputDate.setAttribute("step", "1");
elInputDate.setAttribute("value", 0);
elInputDate.style = "margin-top:15px";
elInputDate.addEventListener("input", showLayer);
o.elLegend.parentElement.appendChild(elInputDate);
}
function getBoundsMeter() {
var b = map.getBounds();
var ne = degreesToMeters(b.getEast(), b.getNorth());
var sw = degreesToMeters(b.getWest(), b.getSouth());
return {
n: ne.y,
s: sw.y,
e: ne.x,
w: sw.x
};
}
function getBoundsMeterString() {
var b = getBoundsMeter();
return b.w + "," + b.s + "," + b.e + "," + b.n;
}
function extentChanged() {
return getBoundsMeterString() !== bbxCurrent;
}
function isBusy(set) {
if (typeof set !== "undefined") {
busy = set;
} else {
console.log("Is busy ? " + (busy ? 'yes' : 'no') + "!");
}
return busy === true;
}
function getBoundsLatLngArray() {
var b = map.getBounds();
var nw = b.getNorthWest();
var se = b.getSouthEast();
return [
[
nw.lng, nw.lat
],
[
se.lng, nw.lat
],
[
se.lng, se.lat
],
[
nw.lng, se.lat
]
];
}
function getTilesUrlLayer(layer) {
var res = window.document.body.getBoundingClientRect();
bbxCurrent = getBoundsMeterString();
return 'https://datacore.unepgrid.ch/geoserver' +
'/MAPX/wms?REQUEST=GetMap&' +
'layers=' + layer +
'&WIDTH=' + res.width +
'&HEIGHT=' + res.height +
'&bbox=' + bbxCurrent +
'&SRS=EPSG:3857&' +
'version=1.1.1&format=image/png&transparent=true';
}
function getImageUrlBlob(layer, pos) {
var url = getTilesUrlLayer(layer);
return fetch(url)
.then(function(response) {
return response.blob();
}).then(function(blob) {
return {
layer: layer,
url: window.URL.createObjectURL(blob),
pos: pos
};
});
}
function degreesToMeters(lon, lat) {
var x = lon * 20037508.34 / 180;
var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
y = y * 20037508.34 / 180;
return {
x: x,
y: y
};
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment