Giter VIP home page Giter VIP logo

d3-inertia's Introduction

Inertia

An extension to d3-drag that continues the mouse movement with some inertia (by default, 5 seconds).

The inertia object exposes a position and a velocity, that correspond to the mouse coordinates relative to the target of the d3.drag method. During the drag gesture, the position just follows the mouse, and the velocity accumulates the movement. When the drag gesture ends, the render() method is called repeatedly with a tweening argument t that goes from 0 to 1. It is up to you to know what to do with these vectors.

The most simple case is: currentPosition = last position + t * velocity.

This example demonstrates a more creative use of the parameters. As you can see, d3.inertia can be used on its own, but you will need to manage quite a few parameters.

(TODO: a helping function for common use cases).

Dragging the globe

Versor Dragging with Inertia
Canvas example + code

The naïve method to rotate a globe 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.

The 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.

This method, introduced by Jason Davies and Mike Bostock, is called versor dragging.

d3-inertia packages this method.

Include the scripts in your page with

<script src="https://unpkg.com/versor"></script>
<script src="https://unpkg.com/d3-inertia"></script>

Then, define a render() function that redraws the globe, and call:

var inertia = d3.geoInertiaDrag(canvas, function() { render(); }, [projection], [opt]);

Versor Dragging with Inertia
SVG example + code

canvas is the target container (it can also be svg)

projection is an object with two methods:

  • projection.rotate([r]) gets and sets the rotation.

  • projection.invert([x,y]) transforms screen coordinates into spherical coordinates lambda, phi; most projections have an exact invert, but for the few which do not, this doesn't have to be very accurate to give an “almost correct” movement.

If a projection is defined globally, and not specified in the function call, the plugin will use it.

opt is an array of options, which can include:

  • start, move, end: callback functions on the corresponding events (end is invoked only if conditions for inertia are met)

  • stop, finish: extra callback functions invoked if the conditions for inertia are not met and after it finishes respectively

  • time: reference time for the inertia (in ms, default 5000)

  • hold: threshold time beteen the final move and end events after which inertia will be cancelled (in ms, default 100)

Credits

Thanks to Jason Davies, Mike Bostock and Widi Harsojo.

The quaternion & versor functions are taken from the versor package.

d3-inertia's People

Contributors

datawis avatar dependabot[bot] avatar fil avatar mbolli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

d3-inertia's Issues

add a "north is up" option

@vasturiano

Btw, I've noticed one of the disorienting things about the versors globe rotation is that it can easily get turned sideways and upside down. I think maintaining a north-up orientation could improve the interaction. This example https://www.jasondavies.com/maps/zoom/ has a "north up" mode, but that's only for the programmatic jumps, not the rotation drag interaction. Do you think it's even possible to enforce a north-up view, or is it a conflicting restriction with the pan interaction?

work with d3.zoom

The planets example sort of works, but it's not the end of the story:

  • check all mobile gestures (see also #3)
  • allow panning when outside the sphere (??)

Versor dependency prevents some toolchains (vite)

d3-inertia currently depends on versor ^0.1, which results in a download of versor 0.1.2. However, that version of versor incorrectly specifies its package.json file, by specifying module and jsnext:main as src/versor.js. No such file exists for that version; they should be pointing instead towards src/index.js (or instead src/index.js should have been src/versor.js).

This actually does not matter for many cases, since d3-inertia's usage of versor under the hood uses the bundled versions in the dist folder. However, some toolchains like Vite need this field to be correctly specified to avoid unnecessary bundling. Vite gives the following error when trying to run yarn start:

node_modules/vite/dist/node/chunks/dep-63d4bd14.js:43786:10: error: [plugin: vite:dep-pre-bundle] Failed to resolve entry for package "versor". The package may have incorrect main/module/exports specified in its package.json:

I thought it would be as simple as requiring d3-inertia to use versor 0.2.0, but this did not work when I tried it out because versor 0.2.0 has type: module in its package.json and thus the require statement in d3-inertia's minified file fails. So I'm not sure what the best solution is.

If this issue occurs for anyone else, a temp fix for d3-inertia users is to use patch-package after just renaming versor 0.1.2's src/index.js to src/versor.js.

Brief block when releasing drag

When letting go of the drag, there seems to be a momentary pause in the motion before initiating the inertia decay. Here's an example with the globe rotation:

d3-inertia-block

mobile breaks on pinch/zoom

two fingers gestures can send the script to infinity (or huge or NaN) velocities, which is definitely not good™

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.