{"id":15760456,"url":"https://github.com/d3/versor","last_synced_at":"2025-10-20T04:31:50.842Z","repository":{"id":50785390,"uuid":"109686109","full_name":"d3/versor","owner":"d3","description":"a home for Mike Bostock's versor.js","archived":false,"fork":false,"pushed_at":"2023-07-18T20:28:09.000Z","size":170,"stargazers_count":34,"open_issues_count":7,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-01-30T15:25:27.550Z","etag":null,"topics":["d3","d3-geo","quaternion","rotation","versor"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/d3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","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}},"created_at":"2017-11-06T11:21:42.000Z","updated_at":"2023-11-24T15:08:43.000Z","dependencies_parsed_at":"2024-06-18T17:11:00.826Z","dependency_job_id":null,"html_url":"https://github.com/d3/versor","commit_stats":null,"previous_names":["fil/versor"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d3%2Fversor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d3%2Fversor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d3%2Fversor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d3%2Fversor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d3","download_url":"https://codeload.github.com/d3/versor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237178348,"owners_count":19267519,"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":["d3","d3-geo","quaternion","rotation","versor"],"created_at":"2024-10-04T10:58:05.888Z","updated_at":"2025-10-20T04:31:50.449Z","avatar_url":"https://github.com/d3.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Versor\n\nRotate the globe with the mouse.\n\nThe naïve method uses `mouse.x` and `mouse.y` as proxies for longitude and latitude. It works when the rotation is small, but try to put the globe \"upside-down\" and suddenly moving the mouse to the left rotates the globe to the right, and vice versa.\n\nThe correct solution is to track the spherical coordinates of the point that is under the mouse, and apply a rotation to the globe that will move the initial point to the current mouse position. Computing that rotation involves quaternions.\n\nThis method, introduced by [Jason Davies](https://www.jasondavies.com/maps/rotate/) and Mike Bostock, is called [versor dragging](https://gist.github.com/mbostock/7ea1dde508cec6d2d95306f92642bc42).\n\nThis module contains the quaternion \u0026 versor functions. For a directly usable package, see [d3-inertia](https://github.com/Fil/d3-inertia).\n\n\nIn Node:\n\n```js\nconst versor = require(\"versor\");\n\n// interpolate angles (slerp), see https://observablehq.com/@d3/world-tour\nversor.interpolate(rotation0, rotation1); // function of (t)\n\n// quaternion to rotate between p0 and p1, see d3-inertia\nconst p0 = [0, 0],\n    p1 = [90, 0],\n    c0 = versor.cartesian(p0),\n    c1 = versor.cartesian(p1);\nversor.delta(c0, c1); // [0.7071, 0.7071, 0, 0]\n\n// tweening: quaternion to rotate halfway between p0 and p1\nversor.delta(c0, c1, 0.5); // [0.9239, 0.3827, 0, 0]\n\n\n// utilities\n\n// get cartesian coordinates [x, y, z] given spherical coordinates [λ, φ].\nversor.cartesian = function(e) {\n  var l = e[0] * radians, p = e[1] * radians, cp = cos(p);\n  return [cp * cos(l), cp * sin(l), sin(p)];\n};\n\n// create a quaternion from Euler angles\nconst q0 = versor([90,0,0]); // [0.7071068, 0.7071068, 0, 0]\nconst q1 = versor([0,90,0]); // [0.7071068, 0, 0.7071068, 0]\n\n// the quaternion that represents q0 * q1.\nq01 = versor.multiply(q0, q1); // [0.5, 0.5, 0.5, 0.5]\n\n// Euler rotation angles [λ, φ, γ] for the given quaternion.\nversor.rotation(q01); // [90, 0, 90]\n\n\n\n```\n\nIf you use npm, `npm install versor`. You can also download the [latest release on GitHub](https://github.com/d3/versor/releases/latest). For vanilla HTML in modern browsers, import versor from Skypack:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import versor from \"https://cdn.skypack.dev/versor@0.2\";\n  const t = versor([90,0,0]);\n\u003c/script\u003e\n```\n\nFor legacy environments, you can load versor’s UMD bundle from an npm-based CDN such as jsDelivr; a `versor` global is exported:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/versor@0.2\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  \nversor([90,0,0]);\n\n\u003c/script\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd3%2Fversor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd3%2Fversor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd3%2Fversor/lists"}