UNPKG

earthjs

Version:

D3 Earth JS using SVG, Canvas & THREE js, build with some plugins.

227 lines (209 loc) 6.75 kB
// Mike Bostock’s Block https://bl.ocks.org/mbostock/7ea1dde508cec6d2d95306f92642bc42 export default ({zoomScale,intervalDrag}={zoomScale:[0,50000]}) => { /*eslint no-console: 0 */ const _ = { svg:null, wait: null, zoom: null, mouse: null, q: null, sync: [], onDrag: {}, onDragVals: [], onDragStart: {}, onDragStartVals: [], onDragEnd: {}, onDragEndVals: [], onClick: {}, onClickVals: [], onDblClick: {}, onDblClickVals: [] }; window._mouse = _; if (zoomScale===undefined) { zoomScale = [0,50000]; } function onclick() { _.onClickVals.forEach(v => { v.call(_._this, _.event, _.mouse); }); } function ondblclick() { _.onDblClickVals.forEach(v => { v.call(_._this, _.event, _.mouse); }); } let v0, // Mouse position in Cartesian coordinates at start of drag gesture. r0, // Projection rotation as Euler angles at start. q0; // Projection rotation as versor at start. function r(__) { const versor = __.versor; const v1 = versor.cartesian(__.proj.rotate(r0).invert(_.mouse)), q1 = versor.multiply(q0, versor.delta(v0, v1)); _.r = versor.rotation(q1); } function drag(__) { r(__); __.rotate(_.r); _.onDragVals.forEach(v => { v.call(this, _.event, _.mouse); }); } function init() { const __ = this._; const versor = __.versor; const s0 = __.proj.scale(); const wh = [__.options.width, __.options.height]; _.scale = d3.scaleLinear().domain([30,__.proj.scale()]).range([0.1,1]); _.svg.call(d3.drag() .on('start',onStartDrag) .on('drag', onDragging) .on('end', onEndDrag)); _.zoom = d3.zoom() .on('zoom', zoom) .scaleExtent([0.1,160]) .translateExtent([[0,0], wh]) .filter(function() { const {touches, type} = d3.event; return (type==='wheel' || touches); }) _.svg.call(_.zoom); // todo: add zoom lifecycle to optimize plugins zoom-able // ex: barTooltipSvg, at the end of zoom, need to recreate function zoom() { const z = zoomScale; const r1 = s0 * d3.event.transform.k; if (r1>=z[0] && r1<=z[1]) { __.scale(r1); _.sync.forEach(g=>g._.scale(r1)); } } function rotate(r) { const d = r[0] - r0[0]; r[0] = d + this._.proj.rotate()[0]; if (r[0] >= 180) r[0] -= 360; this._.rotate(r); } function onStartDrag() { const mouse = d3.mouse(this); v0 = versor.cartesian(__.proj.invert(mouse)); r0 = __.proj.rotate(); q0 = versor(r0); __.drag = null; _.onDragStartVals.forEach(v => v.call(this, _.event, mouse)); _.onDragVals.forEach( v => v.call(this, _.event, mouse)); __.refresh(); _.mouse = mouse; _._this = this; _.t1 = 0; _.t2 = 0; } function onDragging() { // DOM update must be onInterval! __.drag = true; _._this = this; _.mouse = d3.mouse(this); !intervalDrag && drag(__); // _.t1+=1; // twice call compare to onInterval } function onEndDrag() { let drag = __.drag; __.drag = false; if (drag===null) { _.event = d3.event; if (__.options.spin) { onclick(); } else if (_.wait) { _.wait = null; ondblclick(); } else if (_.wait===null) { _.wait = setTimeout(function() { if (_.wait) { _.wait = false; } }, 250); } } else if (drag) { r(__); __.rotate(_.r); _.onDragVals.forEach(v => v.call(_._this, _.event, _.mouse)); _.sync.forEach(g=>rotate.call(g, _.r)); } _.onDragEndVals.forEach(v => v.call(this, _.event, _.mouse)); __.refresh(); // console.log('ttl:',_.t1,_.t2); } } function interval() { const __ = this._; if (__.drag && intervalDrag) { if (_.oMouse[0]!==_.mouse[0] && _.oMouse[1]!==_.mouse[1]) { _.oMouse = _.mouse; drag(__); // _.t2+=1; } } else if (_.wait===false) { _.wait = null; onclick(); } } return { name: 'mousePlugin', onInit(me) { _.me = me; _.oMouse = []; _.svg = this._.svg; init.call(this); }, onInterval() { interval.call(this); }, selectAll(q) { if (q) { _.q = q; _.svg.call(d3.drag() .on('start',null) .on('drag', null) .on('end', null)); _.svg.call(d3.zoom() .on('zoom', null)); _.svg = d3.selectAll(q); init.call(this); if (this.hoverCanvas) { this.hoverCanvas.selectAll(q); } } return _.svg; }, sync(arr) { _.sync = arr; }, zoom(k) { _.zoom.scaleTo(_.svg, (k ? _.scale(k) : 1)); }, mouse() { return _.mouse; }, onDrag(obj) { Object.assign(_.onDrag, obj); _.onDragVals = Object.keys(_.onDrag).map(k => _.onDrag[k]); }, onDragStart(obj) { Object.assign(_.onDragStart, obj); _.onDragStartVals = Object.keys(_.onDragStart).map(k => _.onDragStart[k]); }, onDragEnd(obj) { Object.assign(_.onDragEnd, obj); _.onDragEndVals = Object.keys(_.onDragEnd).map(k => _.onDragEnd[k]); }, onClick(obj) { Object.assign(_.onClick, obj); _.onClickVals = Object.keys(_.onClick).map(k => _.onClick[k]); }, onDblClick(obj) { Object.assign(_.onDblClick, obj); _.onDblClickVals = Object.keys(_.onDblClick).map(k => _.onDblClick[k]); } } }