gpw-data-viewer.html 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <!doctype html>
  2. <html>
  3. <meta charset="utf-8">
  4. <head>
  5. <title>gpw data viewer</title>
  6. <style>
  7. canvas {
  8. max-width: calc(100% - 16px);
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <canvas></canvas>
  14. </body>
  15. <script type="module">
  16. async function loadFile(url) {
  17. const req = await fetch(url);
  18. return req.text();
  19. }
  20. function parseData(text) {
  21. const data = [];
  22. const settings = {data};
  23. let max;
  24. let min;
  25. // split into lines
  26. text.split('\n').forEach((line) => {
  27. // split the line by whitespace
  28. const parts = line.trim().split(/\s+/);
  29. if (parts.length === 2) {
  30. // only 2 parts, must be a key/value pair
  31. settings[parts[0]] = parseFloat(parts[1]);
  32. } else if (parts.length > 2) {
  33. // more than 2 parts, must be data
  34. const values = parts.map((v) => {
  35. const value = parseFloat(v);
  36. if (value === settings.NODATA_value) {
  37. return undefined;
  38. }
  39. max = Math.max(max === undefined ? value : max, value);
  40. min = Math.min(min === undefined ? value : min, value);
  41. return value;
  42. });
  43. data.push(values);
  44. }
  45. });
  46. return Object.assign(settings, {min, max});
  47. }
  48. function drawData(file) {
  49. const {min, max, ncols, nrows, data} = file;
  50. const range = max - min;
  51. const ctx = document.querySelector('canvas').getContext('2d');
  52. // make the canvas the same size as the data
  53. ctx.canvas.width = ncols;
  54. ctx.canvas.height = nrows;
  55. // but display it double size so it's not too small
  56. ctx.canvas.style.width = px(ncols * 2);
  57. // fill the canvas to dark gray
  58. ctx.fillStyle = '#444';
  59. ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  60. // draw each data point
  61. data.forEach((row, latNdx) => {
  62. row.forEach((value, lonNdx) => {
  63. if (value === undefined) {
  64. return;
  65. }
  66. const amount = (value - min) / range;
  67. const hue = 1;
  68. const saturation = 1;
  69. const lightness = amount;
  70. ctx.fillStyle = hsl(hue, saturation, lightness);
  71. ctx.fillRect(lonNdx, latNdx, 1, 1);
  72. });
  73. });
  74. }
  75. function px(v) {
  76. return `${v | 0}px`;
  77. }
  78. function hsl(h, s, l) {
  79. return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
  80. }
  81. loadFile('resources/data/gpw/gpw_v4_basic_demographic_characteristics_rev10_a000_014mt_2010_cntm_1_deg.asc')
  82. .then(parseData)
  83. .then(drawData);
  84. </script>
  85. </html>