+page.svelte 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. <script>
  2. import { onMount } from 'svelte';
  3. import 'mapbox-gl/dist/mapbox-gl.css';
  4. let { data } = $props();
  5. let mapEl = $state();
  6. let webglError = $state(false);
  7. function webgl2Available() {
  8. const canvas = document.createElement('canvas');
  9. canvas.width = 1;
  10. canvas.height = 1;
  11. return Boolean(canvas.getContext('webgl2'));
  12. }
  13. onMount(() => {
  14. let map;
  15. let observer;
  16. let cancelled = false;
  17. (async () => {
  18. if (!data.mapboxKey || !mapEl) return;
  19. const mod = await import('mapbox-gl');
  20. const mapboxgl = mod.default?.Map ? mod.default : globalThis.mapboxgl;
  21. const workerMod = await import('mapbox-gl/dist/mapbox-gl-csp-worker.js?worker');
  22. if (cancelled || !mapEl || !mapboxgl?.Map) return;
  23. if (!webgl2Available()) {
  24. webglError = true;
  25. return;
  26. }
  27. mapboxgl.workerClass = workerMod.default;
  28. mapboxgl.accessToken = data.mapboxKey;
  29. map = new mapboxgl.Map({
  30. container: mapEl,
  31. style: 'mapbox://styles/mapbox/dark-v11',
  32. center: [-79.048, 33.553],
  33. zoom: 10,
  34. failIfMajorPerformanceCaveat: false
  35. });
  36. const resize = () => map?.resize();
  37. map.on('load', resize);
  38. requestAnimationFrame(resize);
  39. observer = new ResizeObserver(resize);
  40. observer.observe(mapEl);
  41. })();
  42. return () => {
  43. cancelled = true;
  44. observer?.disconnect();
  45. map?.remove();
  46. };
  47. });
  48. </script>
  49. <svelte:head>
  50. <title>Gallery — Lee Morgan</title>
  51. <meta name="description" content="Photo galleries on a map." />
  52. </svelte:head>
  53. <div class="gallery">
  54. <h1 class="sr-only">Gallery</h1>
  55. {#if webglError}
  56. <p class="missing">This browser could not start WebGL, which the map needs to draw.</p>
  57. {:else if data.mapboxKey}
  58. <div class="map" bind:this={mapEl}></div>
  59. {:else}
  60. <p class="missing">Set the MAPBOX_KEY environment variable to load the map.</p>
  61. {/if}
  62. </div>
  63. <style>
  64. .gallery {
  65. position: absolute;
  66. inset: 0;
  67. }
  68. .map {
  69. position: absolute;
  70. inset: 0;
  71. }
  72. .map :global(.mapboxgl-canvas-container),
  73. .map :global(.mapboxgl-canvas) {
  74. width: 100%;
  75. height: 100%;
  76. }
  77. .map :global(.mapboxgl-ctrl-attrib) {
  78. background: transparent;
  79. color: var(--muted);
  80. }
  81. .map :global(.mapboxgl-ctrl-attrib a) {
  82. color: var(--muted);
  83. }
  84. .sr-only {
  85. position: absolute;
  86. width: 1px;
  87. height: 1px;
  88. padding: 0;
  89. margin: -1px;
  90. overflow: hidden;
  91. clip: rect(0, 0, 0, 0);
  92. white-space: nowrap;
  93. border: 0;
  94. }
  95. .missing {
  96. margin: 0;
  97. padding: 2rem;
  98. color: var(--muted);
  99. }
  100. </style>