{"id":13880842,"url":"https://github.com/googlemaps/js-three","last_synced_at":"2025-04-06T03:09:20.289Z","repository":{"id":36969012,"uuid":"373228121","full_name":"googlemaps/js-three","owner":"googlemaps","description":"Add ThreeJS objects to Google Maps.","archived":false,"fork":false,"pushed_at":"2024-04-08T14:03:11.000Z","size":16043,"stargazers_count":136,"open_issues_count":8,"forks_count":17,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-04-09T07:46:56.911Z","etag":null,"topics":["google-maps","googlemaps","maps","threejs","utility-library"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/googlemaps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2021-06-02T16:04:39.000Z","updated_at":"2024-08-19T08:00:09.598Z","dependencies_parsed_at":"2023-11-17T19:55:42.586Z","dependency_job_id":"aa72c0be-edaa-4c27-93fa-e829aaad30e5","html_url":"https://github.com/googlemaps/js-three","commit_stats":{"total_commits":692,"total_committers":5,"mean_commits":138.4,"dds":0.1445086705202312,"last_synced_commit":"ff569e98b7e6784b3167c37dda8113adb83a9857"},"previous_names":[],"tags_count":61,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlemaps%2Fjs-three","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlemaps%2Fjs-three/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlemaps%2Fjs-three/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/googlemaps%2Fjs-three/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/googlemaps","download_url":"https://codeload.github.com/googlemaps/js-three/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247427006,"owners_count":20937201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["google-maps","googlemaps","maps","threejs","utility-library"],"created_at":"2024-08-06T08:03:32.236Z","updated_at":"2025-04-06T03:09:20.266Z","avatar_url":"https://github.com/googlemaps.png","language":"TypeScript","readme":"# Google Maps ThreeJS Overlay View and Utilities\n\n[![npm](https://img.shields.io/npm/v/@googlemaps/three)](https://www.npmjs.com/package/@googlemaps/three)\n![Build](https://github.com/googlemaps/js-three/workflows/Test/badge.svg)\n![Release](https://github.com/googlemaps/js-three/workflows/Release/badge.svg)\n[![codecov](https://codecov.io/gh/googlemaps/js-three/branch/main/graph/badge.svg)](https://codecov.io/gh/googlemaps/js-three)\n![GitHub contributors](https://img.shields.io/github/contributors/googlemaps/js-three?color=green)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)\n[![](https://github.com/jpoehnelt/in-solidarity-bot/raw/main/static//badge-flat.png)](https://github.com/apps/in-solidarity)\n[![Discord](https://img.shields.io/discord/676948200904589322?color=6A7EC2\u0026logo=discord\u0026logoColor=ffffff)](https://discord.gg/jRteCzP)\n\n## Description\n\nAdd [three.js](https://threejs.org) objects to Google Maps Platform JS. The\nlibrary provides a `ThreeJSOverlayView` class extending `google.maps.WebGLOverlayView`\nand utility functions for converting geo-coordinates (latitude/longitude) to\nvectors in the coordinate system used by three.js.\n\n## Install\n\nAvailable via npm as the package [@googlemaps/three](https://www.npmjs.com/package/@googlemaps/three).\n\n```\nnpm i @googlemaps/three\n```\n\nAlternatively you can load the package directly to the html document using\nunpkg or other CDNs. In this case, make sure to load three.js before loading\nthis library:\n\n```\n\u003cscript src=\"https://unpkg.com/three/build/three.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://unpkg.com/@googlemaps/three/dist/index.min.js\"\u003e\u003c/script\u003e\n```\n\nWhen adding via unpkg, the package can be accessed as\n`google.maps.plugins.three`. A version can be specified by using\n`https://unpkg.com/@googlemaps/three@VERSION/dist/...`.\n\nThe third option to use it is via ES-Module imports, similar to how the\nthree.js examples work. For this, you first need to specify an\n[importmap](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap)\n(example using unpkg.com, but it works the same way with any other CDN\nor self-hosted files):\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"three\": \"https://unpkg.com/three/build/three.module.js\",\n      \"@googlemaps/three\": \"https://unpkg.com/@googlemaps/three/dist/index.esm.js\"\n    }\n  }\n\u003c/script\u003e\n```\n\nIn order to support browsers that don't yet implement importmap, you can\nuse the [es-module-shims package](https://github.com/guybedford/es-module-shims).\n\nAfter that, you can use three.js and the ThreeJSOverlayView like you would when\nusing a bundler.\n\n```html\n\u003cscript type=\"module\"\u003e\n  import * as THREE from \"three\";\n  import { ThreeJSOverlayView } from \"@googlemaps/three\";\n\n  // ...\n\u003c/script\u003e\n```\n\n## Documentation\n\nCheckout the reference [documentation](https://googlemaps.github.io/js-three/index.html).\n\n### Coordinates, Projection and Anchor-Points\n\nThe coordinate system within the three.js scene (so-called 'world\ncoordinates') is a right-handed coordinate system in z-up orientation.\nThe y-axis is pointing true north, and the x-axis is pointing east. The\nunits are meters. So the point `new Vector3(0, 50, 10)` is 10 meters\nabove ground and 50 meters east of the specified anchor point.\n\nThis anchor-point and orientation can be set in the constructor, or by using the\n`setAnchor()` and `setUpAxis()`-methods (be aware that all object-positions in\nyour scene depend on the anchor-point and orientation, so they have to be\nrecomputed when either of them is changed):\n\n```typescript\nimport { ThreeJSOverlayView } from \"@googlemaps/three\";\n\nconst overlay = new ThreeJSOverlayView({\n  anchor: { lat: 37.7793, lng: -122.4192, altitude: 0 },\n  upAxis: \"Y\",\n});\n\noverlay.setAnchor({ lat: 35.680432, lng: 139.769013, altitude: 0 });\noverlay.setUpAxis(\"Z\");\n// can also be specified as Vector3:\noverlay.setUpAxis(new Vector3(0, 0, 1));\n```\n\n\u003e The default up-axis used in this library is the z-axis (+x is east\n\u003e and +y is north), which is different from the y-up orientation normally\n\u003e used in three.\n\nAll computations on the GPU related to the position use float32 numbers,\nwhich limits the possible precision to about 7 decimal digits. Because\nof this, we cannot use a global reference system and still have the\nprecision to show details in the meters to centimeters range.\n\nThis is where the anchor point is important. The anchor specifies the\ngeo-coordinates (lat/lng/altitude) where the origin of the world-space\ncoordinate system is, and you should always define it close to where the\nobjects are placed in the scene - unless of course you are only working with\nlarge-scale (city-sized) objects distributed globally.\n\nAnother reason why setting the anchor close to the objects in the scene\nis generally a good idea: In the mercator map-projection used in Google Maps,\nthe scaling of meters is only accurate in regions close to the equator. This\ncan be compensated for by applying a scale factor that depends on the\nlatitude of the anchor. This scale factor is factored into the coordinate\ncalculations in WebGlOverlayView based on the latitude of the anchor.\n\n#### Converting coordinates\n\nWhen you need more than just a single georeferenced object in your scene,\nyou need to compute the world-space position for those coordinates. The\nThreeJSOverlayView class provides a helper function for this conversion that\ntakes the current `anchor` and `upAxis` into account:\n\n```typescript\nconst coordinates = { lat: 12.34, lng: 56.78 };\nconst position: Vector3 = overlay.latLngAltitudeToVector3(coordinates);\n\n// alternative: pass the Vector3 to write the position\n// to as the second parameter, so to set the position of a mesh:\noverlay.latLngAltitudeToVector3(coordinates, mesh.position);\n```\n\n### Raycasting and Interactions\n\nIf you want to add interactivity to any three.js content, you typically\nhave to implement raycasting. We took care of that for you, and the\nThreeJSOverlayView provides a method `overlay.raycast()` for this. To make\nuse of it, you first have to keep track of mouse movements on the map:\n\n```js\nimport { Vector2 } from \"three\";\n\n// ...\n\nconst mapDiv = map.getDiv();\nconst mousePosition = new Vector2();\n\nmap.addListener(\"mousemove\", (ev) =\u003e {\n  const { domEvent } = ev;\n  const { left, top, width, height } = mapDiv.getBoundingClientRect();\n\n  const x = domEvent.clientX - left;\n  const y = domEvent.clientY - top;\n\n  mousePosition.x = 2 * (x / width) - 1;\n  mousePosition.y = 1 - 2 * (y / height);\n\n  // since the actual raycasting is performed when the next frame is\n  // rendered, we have to make sure that it will be called for the next frame.\n  overlay.requestRedraw();\n});\n```\n\nWith the mouse position being always up to date, you can then use the\n`raycast()` function in the `onBeforeDraw` callback.\nIn this example, we change the color of the object under the cursor:\n\n```js\nconst DEFAULT_COLOR = 0xffffff;\nconst HIGHLIGHT_COLOR = 0xff0000;\n\nlet highlightedObject = null;\n\noverlay.onBeforeDraw = () =\u003e {\n  const intersections = overlay.raycast(mousePosition);\n  if (highlightedObject) {\n    highlightedObject.material.color.setHex(DEFAULT_COLOR);\n  }\n\n  if (intersections.length === 0) return;\n\n  highlightedObject = intersections[0].object;\n  highlightedObject.material.color.setHex(HIGHLIGHT_COLOR);\n};\n```\n\nThe full examples can be found in [`./examples/raycasting.ts`](./examples/raycasting.ts).\n\n## Example\n\nThe following example provides a skeleton for adding objects to the map with this library.\n\n```js\nimport * as THREE from \"three\";\nimport { ThreeJSOverlayView, latLngToVector3 } from \"@googlemaps/three\";\n\n// when loading via UMD, remove the imports and use this instead:\n// const { ThreeJSOverlayView, latLngToVector3 } = google.maps.plugins.three;\n\nconst map = new google.maps.Map(document.getElementById(\"map\"), mapOptions);\nconst overlay = new ThreeJSOverlayView({\n  map,\n  upAxis: \"Y\",\n  anchor: mapOptions.center,\n});\n\n// create a box mesh\nconst box = new THREE.Mesh(\n  new THREE.BoxGeometry(10, 50, 10),\n  new THREE.MeshMatcapMaterial()\n);\n// move the box up so the origin of the box is at the bottom\nbox.geometry.translateY(25);\n\n// set position at center of map\nbox.position.copy(overlay.latLngAltitudeToVector3(mapOptions.center));\n\n// add box mesh to the scene\noverlay.scene.add(box);\n\n// rotate the box using requestAnimationFrame\nconst animate = () =\u003e {\n  box.rotateY(THREE.MathUtils.degToRad(0.1));\n\n  requestAnimationFrame(animate);\n};\n\n// start animation loop\nrequestAnimationFrame(animate);\n```\n\nThis adds a box to the map.\n\n\u003cimg src=\"https://storage.googleapis.com/geo-devrel-public-buckets/box.png\" alt=\"threejs box on map\" width=\"400\"/\u003e\n\n## Demos\n\nView the package in action:\n\n- [Basic Example](https://googlemaps.github.io/js-three/public/basic/)\n- [Anchor Example](https://googlemaps.github.io/js-three/public/anchor/)\n- [Orientation Example](https://googlemaps.github.io/js-three/public/orientation/)\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglemaps%2Fjs-three","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgooglemaps%2Fjs-three","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglemaps%2Fjs-three/lists"}