Public
Edited
Apr 30, 2024
Also listed in…
Terrain
Insert cell
Insert cell
Insert cell
viewof map = {
const target = html`<div style="width:100%;height:500px;">`;
yield target;
const canvasFunction = function (bbox, resolution, pixelRatio, size, projection) {
const [width, height] = size.map(e => Math.floor(e));
const cv = document.createElement("canvas");
cv.width = width;
cv.height = height;
const ctx = cv.getContext("2d");
createHillShadeMap(width, height, bbox).then(cv2 => {
const img = new Image();
img.src = cv2.toDataURL();
img.onload = function(){
ctx.clearRect(0,0,width,height);
ctx.drawImage(img,0,0,width,height);
map.render();
};
});

return cv;
};
const layer = new ol.layer.Image({
source: new ol.source.ImageCanvas({
canvasFunction,
ratio: 1,
interpolate: false,
}),
// opacity: 0.5,
});
const projection = "EPSG:4326";

const map = new ol.Map({
target,
pixelRatio: 1,
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
layer,
],

view: new ol.View({
center: ol.proj.fromLonLat([138.73, 35.36], projection),
zoom: 12,
projection,
}),
});
return target;
}
Insert cell
createHillShadeMap = async function (width, height, bbox) {

//Get elevation data
const img = await je.getImage({
collection: "https://s3.ap-northeast-1.wasabisys.com/je-pds/cog/v1/JAXA.EORC_ALOS.PRISM_AW3D30.v3.2_global/collection.json",
bbox, //[west,south,east,north]
width, //px
height, //px

//Bilinear resampling is required to calculate slopes
bilinearResampling: true,
});
const data = img.getData();

//HTML canvas element for drawing an image
const cv = document.createElement("canvas");
cv.width = width;
cv.height = height;
const ctx = cv.getContext("2d");
const imgdata = ctx.getImageData(0, 0, width, height);

//Approximate distance of pixels [m] (Earth's polar radius 6356752 [m])
const mppx = 6356752 * (data.bbox[3] - data.bbox[1]) * (Math.PI / 180) / height;
// hc: Elevation of the center pixel [m]
// dh: Elevation difference in north-south direction (Elevation of south pixel - Elevation of north pixel) [m]
// Simplified as dh << mppx
const getRGB = function(hc,dh){
if(isNaN(dh)) dh = 0;
if(isNaN(hc)) hc = 0;
return 255 * (0.5 + 0.3 * dh / mppx - hc * 0.00003);
};

//Processing each pixel
for (let j = 1; j < height - 1; j++) {
let index = j * width;
for (let i = 0; i < width; i++) {
const hn = data.data[index - width];
const hc = data.data[index];
const hs = data.data[index + width];
const rgb = getRGB(hc,hs - hn);
imgdata.data.set([rgb, rgb, rgb, 255], index << 2);
index++;
}
}

ctx.putImageData(imgdata, 0, 0);
return cv;
}
Insert cell
je = require("https://data.earth.jaxa.jp/api/javascript/v1.2.3/jaxa.earth.umd.js");
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more