{"id":28727455,"url":"https://github.com/rylern/temperaturemap","last_synced_at":"2026-02-18T02:02:03.325Z","repository":{"id":71612554,"uuid":"413432739","full_name":"Rylern/TemperatureMap","owner":"Rylern","description":"Tutorial for creating a temperature map with Mapbox and OpenWeatherMap","archived":false,"fork":false,"pushed_at":"2022-10-13T15:59:29.000Z","size":398,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-24T18:29:23.250Z","etag":null,"topics":["average-heatmap","heatmap","interpolation-heatmap","map","mapbox","mapbox-gl-js","openweathermap-api","temperature","temperature-map"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rylern.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-10-04T13:27:21.000Z","updated_at":"2025-07-07T23:43:30.000Z","dependencies_parsed_at":"2023-07-13T14:30:50.860Z","dependency_job_id":null,"html_url":"https://github.com/Rylern/TemperatureMap","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Rylern/TemperatureMap","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rylern%2FTemperatureMap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rylern%2FTemperatureMap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rylern%2FTemperatureMap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rylern%2FTemperatureMap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rylern","download_url":"https://codeload.github.com/Rylern/TemperatureMap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rylern%2FTemperatureMap/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29566366,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T00:47:08.760Z","status":"online","status_checked_at":"2026-02-18T02:00:09.468Z","response_time":162,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["average-heatmap","heatmap","interpolation-heatmap","map","mapbox","mapbox-gl-js","openweathermap-api","temperature","temperature-map"],"created_at":"2025-06-15T14:41:01.676Z","updated_at":"2026-02-18T02:02:03.319Z","avatar_url":"https://github.com/Rylern.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Create a temperature map with Mapbox and OpenWeatherMap\n\n\n\nA temperature maps shows the current temperature in a color scale, from blue (cold) to red (hot). In this tutorial, I will show how to create a web-based temperature map using JavaScript, Mapbox, and OpenWeatherMap.\n\nTo follow this tutorial, you just need some knowledge in web development (HTML, CSS, Javascript).\n\nWe will:\n\n* Create a map using Mapbox.\n* Fetch temperature data using OpenWeatherMap.\n* Use a custom Mapbox layer to display a color scale of the temperature.\n\nThe result is displayed [here](https://rylern.github.io/TemperatureMap/) and the source code is accessible [here](https://github.com/Rylern/TemperatureMap).\n\n## 1. Setting up the project\n\nThe first step is to set up the web page. Since it's only a web application running on a client side, we just need a HTML and a JavaScript file.\n\nCreate an empty `map.js` file. This file will contain the map creation and the retrieval of weather data. Then, create an `index.html` file with the following code:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eTemperature map\u003c/title\u003e\n        \u003cstyle\u003e\n            body { margin: 0; padding: 0; }\n            #map { position: absolute; top: 0; bottom: 0; width: 100%; }\n        \u003c/style\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv id=\"map\"\u003e\u003c/div\u003e\n        \u003cscript src=\"map.js\"\u003e\u003c/script\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nWe just add a `map` div that takes the entire available space. It will contain the map.\n\n## 2. Creating the map\n\nTo display a map in our web page, we need a map provider. [Many exist](https://en.wikipedia.org/wiki/List_of_online_map_services), but we will use [Mapbox](https://www.mapbox.com/) in this tutorial because it is highly customizable and free up to 50,000 map load per month (which means that 50,000 monthly requests on your web page can be made). \n\nFirst, create a [Mapbox account](https://account.mapbox.com/auth/signup/). Then, go to your [profile page](https://account.mapbox.com/) and copy your default public token. This is used to identify yourself when requesting map data.\n\nWe can now add the map on our web page. Mapbox provides SDK for different platforms (Android, iOS, Unity) so since we want to create a web application we are going to use Mapbox GL JS. This SDK can be installed via a npm module, or by simply including the JavaScript and CSS files in the `\u003chead\u003e` of our HTML file:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n        \u003ctitle\u003eTemperature map\u003c/title\u003e\n        \u003clink href=\"https://api.mapbox.com/mapbox-gl-js/v2.3.0/mapbox-gl.css\" rel=\"stylesheet\"\u003e\n        \u003cscript src=\"https://api.mapbox.com/mapbox-gl-js/v2.3.0/mapbox-gl.js\"\u003e\u003c/script\u003e\n        \u003cstyle\u003e\n            body { margin: 0; padding: 0; }\n            #map { position: absolute; top: 0; bottom: 0; width: 100%; }\n        \u003c/style\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n        \u003cdiv id=\"map\"\u003e\u003c/div\u003e\n        \u003cscript src=\"map.js\"\u003e\u003c/script\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\nIn the `map.js` file, add the following lines:\n\n```javascript\nmapboxgl.accessToken = 'your_mapbox_access_token';\t\t// past your default public token\n\nconst map = (window.map = new mapboxgl.Map({\n    container: 'map',\t\t\t\t\t\t\t// 'map' is the id of the HTML div\n    style: 'mapbox://styles/mapbox/light-v10'\n}));\n```\n\nThis is the simplest way of creating a map. The `style` parameter will determine how your map will look like. Mapbox provides [default styles](https://docs.mapbox.com/api/maps/styles/#mapbox-styles), but you can also create your own by using [Mapbox Studio](https://studio.mapbox.com/).\n\nOther parameters, such as the inital zoom and geographical centerpoint of the map, can be specified. You will find all available parameters on the [API documentation](https://docs.mapbox.com/mapbox-gl-js/api/map/).\n\n## 3. Gathering weather data\n\nThe next step is to collect data on the current weather by the mean of a weather API. [Several free providers exist](https://rapidapi.com/blog/access-global-weather-data-with-these-weather-apis/). For this tutorial, I chose to use OpenWeatherMap.\n\n[OpenWeatherMap](https://openweathermap.org/) is an online service that provides among other things global weather data. To use this API, you will have to create an account and get your [API key](https://home.openweathermap.org/api_keys). The free plan includes 60 calls to the API per minute.\n\nThe documentation for getting the current weather data is available [here](https://openweathermap.org/current). In this tutorial, we will fetch the current temperature in degree Celsius by geographic coordinates. Therefore, the URLs will be like: `https://api.openweathermap.org/data/2.5/weather?units=metric\u0026lat=latitude\u0026lon=longitude\u0026appid=apiKey`.\n\nSince the goal of this tutorial is to create a temperature map, we want to fetch the temperature at different locations that cover the entire globe. In geography, latitude goes from -90° to 90°, and longitude from -180° to 180°. However, Mapbox uses the Web Mercator projection, which projects the poles at infinity, so we cannot see the poles. Therefore, let's define some points going from -80° to 80° for the latitude.\n\n```javascript\nconst startingLatitude = -80;\nconst startingLongitude = -180;\nconst endingLatitude = 80;\nconst endingLongitude = 180;\nconst n = 10;\t\t\t\t\t// n² is the number of points\n\nconst points = [];\nfor (let i=0; i \u003c n; i++) {\n    for (let j=0; j \u003c n; j++) {\n        points.push({\n            lat: startingLatitude + i * (endingLatitude - startingLongitude)/n,\n            lng: startingLongitude + j * (endingLatitude - startingLongitude)/n,\n            val: 0\t\t\t\t// val will store the temperature\n        })\n    }\n}\n```\n\nEach element of the `points` array is an object with a latitude, a longitude,  and a value corresponding to the temperature for that location. We set the default temperature to 0, so now let's get the real value:\n\n```javascript\nconst startingLatitude = -80;\nconst startingLongitude = -180;\nconst endingLatitude = 80;\nconst endingLongitude = 180;\nconst n = 10;\n\n(async() =\u003e {\n    const points = [];\n    for (let i=0; i \u003c n; i++) {\n        for (let j=0; j \u003c n; j++) {\n            points.push({\n                lat: startingLatitude + i * (endingLatitude - startingLatitude)/n,\n                lng: startingLongitude + j * (endingLongitude - startingLongitude)/n,\n                val: 0\n            })\n        }\n    }\n    // Create the URLs\n    const baseUrl = \"https://api.openweathermap.org/data/2.5/weather?units=metric\u0026lat=\";\n    const apiKey = 'your_weather_api_key';\n    const urls = points.map(point =\u003e baseUrl + point.lat + \"\u0026lon=\" + point.lng + \"\u0026appid=\" + apiKey);\n    // Fetch the weather data\n    const weathers = await Promise.all(urls.map(async url =\u003e {\n        const response = await fetch(url);\n        return response.text();\n    }));\n    // Set the temperature\n    points.forEach((point, index) =\u003e {\n        point.val = JSON.parse(weathers[index]).main.temp;\n    })\n})();\n```\n\nThree steps are done here:\n\n* First, we need to define the URLs which will be used to communicate with the weather API. We use the model URL presented above and we set the latitude and longitude of the previously defined points. Remember to set your API key available [here](https://home.openweathermap.org/api_keys).\n\n* Then, we perform the requests with the `fetch(url)` function. Since it's an asynchronous operation and we need to wait for it to finish, we use the keyword `await`. The function `Promise.all()` is used to perform all the requests in parallel, and, with the keyword `await`, we wait for all requests to finish. `await` has to be inside an `async` function, so we surround the whole code with `(async() =\u003e {})();`. If you don't understand this part, here is the equivalent code if we had only one URL to fetch:\n\n  ```javascript\n  (async() =\u003e {\n      const response = await fetch(url);\n      const weather = await response.text();\n  })();\n  ```\n\n  We fetch a response from an URL, and then we store the content of the response in the `weather` variable. These two operations are asynchronous, so we need to use `await`.\n\n* We have now a `weathers` array containing some weather data for all our `points`, so we just need to extract the temperature by using the [documentation](https://openweathermap.org/current#current_JSON).\n\nWe have now an array of locations with associated temperatures. \n\n## 4. Creating the color scale\n\nWe can now create the color scale by providing the array of `points` to the map.\n\nEach element of a Mapbox map is part of a layer: there is a layer for roads, tunnels, parks, countries, for every type of label... So the color scale we want to add to the map will be implemented by a layer defined by us.\n\nMapbox natively provides a heatmap layer. This is close to what we want, but not exactly. Take a look on these pictures:\n\n![Density heatmap](images/densityHeatmap.png)\n\n![Average heatmap](images/averageHeatmap.png)\n\nThe Mapbox heatmap layer can represent the **density** of points in an area (like on the first picture). The color doesn't depend on the value of a point but on the density of points (actually the value can change the color but it is mainly the density that will affect the color).\n\nFor our temperature map, we want a heatmap that can define a color to any location by making an **average** of the values of the surroundings points (like on the second picture).\n\nI created a way of representing this type of heatmap. The project is available on GitHub [here](https://github.com/Rylern/InterpolateHeatmapLayer). Download the `interpolateHeatmapLayer.js` file, place it in your working folder and include it before the `map.js` script:\n\n```html\n\u003cbody\u003e\n    \u003cdiv id=\"map\"\u003e\u003c/div\u003e\n    \u003cscript src=\"interpolateHeatmapLayer.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"map.js\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n```\n\nYou can now call the `interpolateHeatmapLayer.create()` function to create the layer, and add it to the map. Here the whole script:\n\n```javascript\nmapboxgl.accessToken = 'your_mapbox_access_token';\n\nconst startingLatitude = -80;\nconst startingLongitude = -180;\nconst endingLatitude = 80;\nconst endingLongitude = 180;\nconst n = 10;\n\n(async() =\u003e {\n    const points = [];\n    for (let i=0; i \u003c n; i++) {\n        for (let j=0; j \u003c n; j++) {\n            points.push({\n                lat: startingLatitude + i * (endingLatitude - startingLatitude)/n,\n                lng: startingLongitude + j * (endingLongitude - startingLongitude)/n,\n                val: 0\n            })\n        }\n    }\n\n    const baseUrl = \"https://api.openweathermap.org/data/2.5/weather?units=metric\u0026lat=\";\n    const apiKey = 'your_weather_api_key';\n    const urls = points.map(point =\u003e baseUrl + point.lat + \"\u0026lon=\" + point.lng + \"\u0026appid=\" + apiKey);\n\n    const weathers = await Promise.all(urls.map(async url =\u003e {\n        const response = await fetch(url);\n        return response.text();\n    }));\n\n    points.forEach((point, index) =\u003e {\n        point.val = JSON.parse(weathers[index]).main.temp;\n    })\n\n\n    const map = (window.map = new mapboxgl.Map({\n        container: 'map',\n        style: 'mapbox://styles/mapbox/light-v10'\n    }));\n    \n    // When the map is loaded, create and the color scale layer\n    map.on('load', () =\u003e {\n        const layer = interpolateHeatmapLayer.create({\n            points: points,\t\t\t\t// use our array of points\n            layerId: 'temperature'\t\t// define an ID for the layer\n        });\n        map.addLayer(layer);\n    });\n})();\n```\n\nThe color scale layer can only be added when the map is loaded, so we add an handler to the `load` event. The layer expects at least:\n\n* An array of points, each point being an object containing a latitude `lat`, a longitude `lon`, and a value `val`.\n* An ID, which is the unique Mapbox layer name.\n\nOther parameters are:\n\n* `opacity`: a number between 0 and 1 describing the transparency of the color.\n* `minValue`: define the value corresponding to the blue color. When it's not defined, this is the lowest temperature of `points` which is represented by the blue color. There is also `maxValue` for the red color.\n* `framebufferFactor`: number between 0 and 1. In short, if the framebuffer factor is around 0, the computation will be faster but less accurate and the opposite if it's around 1. The default value is 0.3. Take a look at the `readme` file of the [GitHub project](https://github.com/Rylern/InterpolateHeatmapLayer) if you want to know what exactly this parameter is.\n* `p`: a factor affecting the computation of the color, from 0 to around 15. A high value makes the color uniform around each point. Once again, take a look at the [GitHub project](https://github.com/Rylern/InterpolateHeatmapLayer) if you want to know more.\n* `roi`: list of coordinates (like `points`) defining the area of interest, aka the area where the temperature map will be present. By default, the entire world is colored.\n* `valueToColor`: function defining the range of color of the temperature map. By default, a low temperature is colored blue, a medium green and a high red.\n\nRight now, the temperature is represented above everything else on the map. Instead, it would be better to have the different labels above the temperature map, so we are going to use the second parameter of the [map.addLayer()](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#addlayer) function. The Mapbox documentation states that this parameter is the \"ID of an existing layer to insert the new layer before, resulting in the new layer appearing visually beneath the existing layer\". The layers are defined in the `style` parameter of the map, so we need to find the lowest label layer of the `light-v10` style (the one used here).\n\nTo do this, go to [Mapbox Studio](https://studio.mapbox.com), create a new style, and choose the Monochrome template with the light variation. Then, go to the `Layers` tab on the left panel. All labels appear, the first ones being the upper layers (appearing above the others on the map).  The last layer with `label` written on it is `road-label`. Therefore, perform the following modifications to your script:\n\n```javascript\n// ...\n(async() =\u003e {\n    // ...\n    map.on('load', () =\u003e {\n        const layer = interpolateHeatmapLayer.create({\n            points: points,\n            layerId: 'temperature'\n        });\n        map.addLayer(layer, 'road-label');\n    });\n})();\n```\n\nThe temperature map is now below the labels. \n\n## 5. Conclusion\n\nYou know now how to create a temperature map with Mapbox and OpenWeatherMap. I wrote this article to provide an example of using the interpolate heatmap layer, but it can also be used for visualizing generic geographical data. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frylern%2Ftemperaturemap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frylern%2Ftemperaturemap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frylern%2Ftemperaturemap/lists"}