Skip to content

Commit

Permalink
color work
Browse files Browse the repository at this point in the history
  • Loading branch information
morandd committed Nov 24, 2024
1 parent 7b25a59 commit 806cda4
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 157 deletions.
2 changes: 1 addition & 1 deletion src/components/COGURL.astro
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

<div class="cogurl">
<input type="text" placeholder="URL to any GeoTIFF"
data-badvalue="https://data.sustainability.nilu.no/fairicube/ua2018_mosaic_raster_10m_cog_2_3_B1.tif"
data-value="https://data.sustainability.nilu.no/fairicube/ua2018_mosaic_raster_10m_cog_2_3_B1.tif"
value="https://data.sustainability.nilu.no/fairicube/r05_treecover2018_100m_b1_COG.tif"
/>
<button>View</button>
Expand Down
39 changes: 36 additions & 3 deletions src/components/ChoosePalette.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<label><input type="radio" name="palette" value="d3.interpolateTurbo" />Turbo</label>
<label><input type="radio" name="palette" value="d3.interpolateBlues" />Blues</label>
<label><input type="radio" name="palette" value="d3.interpolateGnBu" />GnBu</label>
<label><input type="radio" name="palette" value="rgb"/>True Color</label>
<label class="qgis"><input type="radio" name="palette" value="qgis" />QGIS</label>
<label class="truecolor"><input type="radio" name="palette" value="rgb"/>True Color</label>
<label class="invertpalette"><input type="checkbox" name="invertpalette"/>Invert</label>
</div>
</div>
Expand All @@ -20,17 +21,35 @@ document.querySelector('input[name="invertpalette"]')?.addEventListener('change'
document.dispatchEvent(new Event('newpalette'));
});


// Add an event listener for the "newpalette" event. If localStorage.palette=rgb hide the Invert checkbox
document.addEventListener('newpalette', () => {
const palette = localStorage.getItem('palette');
const invertCheckbox = document.querySelector('label.invertpalette') as HTMLLabelElement;
invertCheckbox.style.opacity = palette==='rgb' ? '0' : '1';
invertCheckbox.style.opacity = (palette==='rgb'||palette==='qgis') ? '0' : '1';

const qg = localStorage.getItem('QGISColorfile') || '';
const qgisLabel = document.querySelector('label.qgis') as HTMLLabelElement;
if (qg.length>0) qgisLabel.style.opacity = '1';
else qgisLabel.style.opacity = '0';

// Ensure the correct radio button is checked
const paletteRadio = document.querySelector(`input[name="palette"][value="${palette}"]`) as HTMLInputElement;
if (paletteRadio) paletteRadio.checked = true;
});

// Add an event listener for the "newbandcount" event. Show the True Color option if bandcount>1
document.addEventListener('newbandcount', () => {
const bandcount = localStorage.getItem('bandcount') ?? '1';
const rgbLabel = document.querySelector('.choosepalette .truecolor') as HTMLLabelElement;
if (rgbLabel) rgbLabel.style.display = bandcount==='1' ? 'none' : 'initial';
});

// Add click handlers for the palette radio buttons
document.querySelectorAll('input[name="palette"]').forEach( (radio : Element) => {
// Trigger a "palette" event when the palette is changed
(radio as HTMLInputElement).onchange = (e) => {
console.log('palette changed to', (e.target as HTMLInputElement).value);
localStorage.setItem('palette', (e.target as HTMLInputElement).value);
document.dispatchEvent(new Event('newpalette'));
};
Expand All @@ -46,6 +65,17 @@ document.addEventListener('newsource', () => {
if (rgbLabel) rgbLabel.style.display = isTiff ? 'initial' : 'none';
});


// On page load, if localStorage.palette is set check the radio button
document.addEventListener('DOMContentLoaded', () => {

const palette = localStorage.getItem('palette');
if (!palette) return;
const radio = document.querySelector(`input[name="palette"][value="${palette}"]`);
if (!radio) return;
(radio as HTMLInputElement).checked = true;
});

</script>

<style>
Expand All @@ -61,6 +91,7 @@ document.addEventListener('newsource', () => {

div {
pointer-events: auto;

padding: 1rem;
opacity: 0.5;
transition: all 0.1s;
Expand All @@ -77,7 +108,9 @@ document.addEventListener('newsource', () => {
gap: 1rem;
label {
cursor: pointer;
font-family: 'Inter', sans-serif;
* {
cursor: pointer;
}
}
}
input{
Expand Down
30 changes: 21 additions & 9 deletions src/components/Colorbar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,32 @@ document.addEventListener('newsource', updateColorbar);


function updateColorbar() {
console.log('updateColorbar');

const colorbar = document.getElementById('colorbar');
if (!colorbar) return;

const palette = localStorage.getItem('palette') || 'd3.interpolateBlues';
colorbar.innerHTML = '';

const palette = localStorage.getItem('palette');
colorbar.style.display = (palette=='rgb') ? 'none' : 'flex';

if (palette=='qgis') {
const values = JSON.parse(localStorage.getItem('QGISColorfileValues') || '[]');
for (const value of values){
const div = document.createElement('div');
div.innerHTML = value.toFixed(2);
colorbar.appendChild(div);
}
colorbar.style.background = getPaletteAsGradient();
return;
}

const min : number = parseFloat(localStorage.getItem('min') ?? '0');
const max : number = parseFloat(localStorage.getItem('max') ?? '1');
const nmiddletics = (min==0 && max==1) ? 0 : 3;
// Get Ntics evenly spaced between min and max
const middltics = d3.range(min, max, (max-min)/(nmiddletics-1));
const labels = [...middltics.map(t => t.toFixed(0)), max.toFixed(0)];
colorbar.innerHTML = '';
const labels = [...middltics.map(t => t.toFixed(3)), max.toFixed(3)];
for (let i = 0; i < labels.length; i++){
let div = document.createElement('div');
div.innerHTML = labels[i]; // Value
Expand All @@ -45,11 +56,11 @@ function updateColorbar() {
position: absolute;
bottom: 50px;
right: 50px;
width: 200px;
width: 400px;
height: 5px;
background: none;
background: red;
border-radius: 5px;
background-color: none;
background-color: red;
backdrop-filter: blur(5px);
padding: 10px;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
Expand All @@ -61,8 +72,9 @@ function updateColorbar() {
justify-content: space-between;
align-items: center;
div {
mix-blend-mode: plus-lighter;
color: white;
mix-blend-mode: difference;
font-size: 1em;
color: whit;
}
}
</style>
120 changes: 44 additions & 76 deletions src/components/Map.astro
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import 'ol/ol.css';
import * as ol from 'ol';
import TileLayer from 'ol/layer/WebGLTile';
import Map from 'ol/Map.js';
import Source from 'ol/source/ImageTile.js';
import View from 'ol/View.js';

import {getGeotiffMinmaxFromAuxXML} from '../scripts/getGeotiffMinmaxFromAuxXML.js';
import type {Extent} from 'ol/extent';

Expand All @@ -17,7 +21,9 @@ import { transformExtent, Projection, get as getProjection, fromLonLat } from 'o
import {register,fromEPSGCode} from 'ol/proj/proj4';
import STAC from 'ol-stac';
import proj4 from 'proj4'
import * as d3 from 'd3';
import {getQGISColorfile} from '../scripts/parseQGISColorfile.js';
import {useGeographic} from 'ol/proj.js';


let source : any = null;
let layer : TileLayer | null = null;
Expand All @@ -26,10 +32,17 @@ let flag_styleIsSet = false; // This is used to prevent setting the style multip
// Register EPSG:3035
//proj4.defs("EPSG:3035","+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crs");
proj4.defs("EPSG:31256","+proj=tmerc +lat_0=0 +lon_0=16.3333333333333 +k=1 +x_0=0 +y_0=-5000000 +ellps=bessel +towgs84=551.7,162.9,467.9,6.04,1.96,-11.38,-4.82 +units=m +no_defs +type=crs");

register(proj4); // Make projections defined in proj4 (with proj4.defs()) available in OpenLayers. Req

const baselayer = new OldTileLayer({source:new OSM()});
if (!localStorage.getItem('palette')) {
console.log('No palette set. Setting to d3.interpolateBlues');
localStorage.setItem('palette', 'd3.interpolateBlues');
}

//useGeographic();


//const baselayer = new OldTileLayer({source:new OSM()});
const googleview = new ol.View({
projection: 'EPSG:3857',
//center: [16.2,48.2],zoom:10 // Vienna
Expand All @@ -40,6 +53,17 @@ googleview.setCenter( fromLonLat([-77.1778,26.4858], googleview.getProjection())
googleview.setCenter( fromLonLat([-10,55.2], googleview.getProjection())); googleview.setZoom(6); // Copenhagen
googleview.setCenter( fromLonLat([16.2,48.2], googleview.getProjection())); googleview.setZoom(10); // Vienna

const baselayer = new TileLayer({
source: new Source({
attributions:
'Tiles © <a href="https://services.arcgisonline.com/ArcGIS/' +
'rest/services/World_Topo_Map/MapServer">ArcGIS</a>',
url:
'https://server.arcgisonline.com/ArcGIS/rest/services/' +
'World_Topo_Map/MapServer/tile/{z}/{y}/{x}',
})
});


const map = new ol.Map({
target: 'map',
Expand Down Expand Up @@ -98,25 +122,35 @@ async function buildMapForGeotiff() {
}
});

getQGISColorfile();

// Create the source and layer

source = new GeoTIFF({sources: [geotiffSource], normalize: true});
source = new GeoTIFF({sources: [geotiffSource], normalize: false});
layer = new TileLayer({source});


// Set timeout for 5 seconds. If flag_styleIsSet false at that time, print a warning to console that we haven't loaded any tiles.
setTimeout(() => {
if (!flag_styleIsSet) window.newToast({title: 'Error', message: `After 5s, no tiles have been loaded...`});

if (!flag_styleIsSet) {
window.newToast({ok:false, message: `Could nor load dataset.`});
}
}, 5000);

localStorage.setItem('bandcount', '1');
document.dispatchEvent(new Event('newbandcount'));

// Callback on tile load. This is used to set the style
source.on('tileloadend', (event) => {

if (flag_styleIsSet) return; // If the style has already been set, do nothing
flag_styleIsSet = true; // Set the flag

window.newToast(`Got image with ${event.target.bandCount} bands`);
//window.newToast(`Got image with ${event.target.bandCount} bands`);
localStorage.setItem('bandcount', event.target.bandCount.toString());
document.dispatchEvent(new Event('newbandcount'));

if (layer) (layer as TileLayer).setStyle(getInterpolateBand1AsColor()); // Set the style

});
Expand Down Expand Up @@ -155,79 +189,13 @@ async function buildMapForGeotiff() {


// Add a listener for the "newpalette" event
document.addEventListener('newpalette', updateGeotiffColors);
function updateGeotiffColors(){
if (!layer) {
console.error('No layer to update colors for');
return;
}
document.addEventListener('newpalette', () => {
if (!layer) return;
(layer as TileLayer).setStyle(getInterpolateBand1AsColor()); // Set the style
}




async function buildMapForSTACItem() {

// Which STAC item to load?
let stac_json = localStorage.getItem('stac');


if (!stac_json) return buildMapForGeotiff();


const layer = new STAC({url: stac_json});


// Try to fetch and parse an {url}.aux.xml file. The file is an XML file with metadata about the GeoTIFF
/*const minmax = await getGeotiffMinmaxFromAuxXML(url);
if (minmax) {
geotiffSource.min = minmax[0];
geotiffSource.max = minmax[1];
console.log(`Used .tif.aux.xml to find min=${geotiffSource.min}, max=${geotiffSource.max}`);
}
*/



layer.on('sourceready', () => {
const view = map.getView();
view.fit(layer.getExtent() as Extent);

});

layer.on('assetsready', () => {
// Assign titles for e.g. a layerswitcher
for (const sublayer of layer.getLayersArray()) {
const stac = sublayer.get('stac');
let title;
if (stac.isAsset() || stac.isLink()) {
title = stac.getMetadata('title') || stac.getKey();
} else {

const firstDataAsset = stac.getAssets().find(d=>d.roles.includes("data"));
if (firstDataAsset) {
localStorage.setItem('url', firstDataAsset.href);
buildMapForGeotiff();
} else {
console.error(`No asset with role "data" found in ${stac_json}`);
}

}

sublayer.set('title', title);
}
});



// Create the map
map.setLayers([baselayer,layer]);
map.render();


}; // function buildMapForSTACItem




Expand All @@ -236,10 +204,10 @@ map.render();



buildMapForSTACItem(); // Execute this on page load
buildMapForGeotiff(); // Execute this on page load

// Add a listener for the "newsource" event
document.addEventListener('newsource', buildMapForSTACItem);
document.addEventListener('newsource', buildMapForGeotiff);



Expand Down
Loading

0 comments on commit 806cda4

Please sign in to comment.