d3-geo-zoom
Version:
Zoom and Pan D3 Geo projections
70 lines (67 loc) • 2.16 kB
JavaScript
import { select, pointers } from 'd3-selection';
import { zoom } from 'd3-zoom';
import versor from 'versor/src/index';
import Kapsule from 'kapsule';
var geoZoom = Kapsule({
props: {
projection: {
onChange: function onChange(projection, state) {
state.unityScale = projection ? projection.scale() : 1;
}
},
scaleExtent: {
"default": [0.1, 1e3],
onChange: function onChange(extent, state) {
state.zoom && state.zoom.scaleExtent(extent);
}
},
northUp: {
"default": false
},
onMove: {
defaultVal: function defaultVal() {}
}
},
init: function init(nodeEl, state) {
select(nodeEl).call(state.zoom = zoom().scaleExtent(state.scaleExtent).on('start', zoomStarted).on('zoom', zoomed));
var v0, r0, q0;
function zoomStarted(ev) {
if (!state.projection) return;
v0 = versor.cartesian(state.projection.invert(getPointerCoords(ev)));
r0 = state.projection.rotate();
q0 = versor(r0);
}
function zoomed(ev) {
if (!state.projection) return;
var scale = ev.transform.k * state.unityScale;
state.projection.scale(scale);
var v1 = versor.cartesian(state.projection.rotate(r0).invert(getPointerCoords(ev))),
q1 = versor.multiply(q0, versor.delta(v0, v1)),
rotation = versor.rotation(q1);
if (state.northUp) {
rotation[2] = 0; // Don't rotate on Z axis
}
state.projection.rotate(rotation);
state.onMove({
scale: scale,
rotation: rotation
});
}
function getPointerCoords(zoomEv) {
var avg = function avg(vals) {
return vals.reduce(function (agg, v) {
return agg + v;
}, 0) / vals.length;
};
var pointers$1 = pointers(zoomEv, nodeEl);
return pointers$1 && pointers$1.length > 1 ? [0, 1].map(function (idx) {
return avg(pointers$1.map(function (t) {
return t[idx];
}));
}) // calc centroid of all points if multi-touch
: pointers$1.length ? pointers$1[0] // single point click
: [undefined, undefined];
}
}
});
export { geoZoom as default };