Add the 'drag' and 'zoom' plugins

This commit is contained in:
Brandon Tilley 2013-12-22 13:59:41 -08:00
parent b06c3779dc
commit 823a938a4b
10 changed files with 205 additions and 7 deletions

View File

@ -1,3 +1,5 @@
* Implement the `drag` and `zoom` plugins
v0.2.0 v0.2.0
------ ------

View File

@ -2,7 +2,7 @@
* Copyright (c) 2013 Brandon Tilley * Copyright (c) 2013 Brandon Tilley
* *
* Released under the MIT license * Released under the MIT license
* Date: 2013-12-22T07:35:17.700Z * Date: 2013-12-22T21:59:27.746Z
*/ */
(function (root, factory) { (function (root, factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {

67
dist/planetaryjs.js vendored
View File

@ -2,7 +2,7 @@
* Copyright (c) 2013 Brandon Tilley * Copyright (c) 2013 Brandon Tilley
* *
* Released under the MIT license * Released under the MIT license
* Date: 2013-12-22T07:35:17.783Z * Date: 2013-12-22T21:59:27.872Z
*/ */
(function (root, factory) { (function (root, factory) {
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
@ -306,5 +306,70 @@
}; };
}; };
planetaryjs.plugins.zoom = function (options) {
var options = options || {};
var noop = function() {};
var onZoomStart = options.onZoomStart || noop;
var onZoomEnd = options.onZoomEnd || noop;
var onZoom = options.onZoom || noop;
var startScale = options.initialScale;
var scaleExtent = options.scaleExtent || [50, 2000];
return function(planet) {
planet.onInit(function() {
var zoom = d3.behavior.zoom()
.scaleExtent(scaleExtent);
if (startScale) {
zoom.scale(startScale);
} else {
zoom.scale(planet.projection.scale());
}
zoom
.on('zoomstart', onZoomStart)
.on('zoomend', onZoomEnd)
.on('zoom', function() {
onZoom();
planet.projection.scale(d3.event.scale);
});
d3.select(planet.canvas).call(zoom);
});
};
};
planetaryjs.plugins.drag = function(options) {
var options = options || {};
var noop = function() {};
var onDragStart = options.onDragStart || noop;
var onDragEnd = options.onDragEnd || noop;
var onDrag = options.onDrag || noop;
return function(planet) {
planet.onInit(function() {
var drag = d3.behavior.drag()
.on('dragstart', onDragStart)
.on('dragend', onDragEnd)
.on('drag', function() {
onDrag();
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = planet.projection.rotate();
var radius = planet.projection.scale();
var scale = d3.scale.linear()
.domain([-1 * radius, radius])
.range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
planet.projection.rotate(rotation);
});
d3.select(planet.canvas).call(drag);
});
};
};
return planetaryjs; return planetaryjs;
})); }));

View File

@ -1,2 +1,2 @@
/*! Planetary.js 0.2.0 | (c) 2013 Brandon Tilley | Released under MIT License */ /*! Planetary.js 0.2.0 | (c) 2013 Brandon Tilley | Released under MIT License */
!function(n,t){"function"==typeof define&&define.amd?define(["d3","topojson"],t):"object"==typeof exports?module.exports=t(require("d3"),require("topojson")):n.planetaryjs=t(n.d3,n.topojson,n)}(this,function(n,t,o){"use strict";var i=null;o&&(i=o.planetaryjs);var e=[],r=function(t,o,i){n.timer(function(){t.context.clearRect(0,0,o.width,o.height);for(var n=0;n<i.onDraw.length;n++)i.onDraw[n]()})},l=function(n,t){for(var o=0;o<e.length;o++)t.unshift(e[o]);0==t.length&&(s.plugins.earth&&n.loadPlugin(s.plugins.earth()),s.plugins.pings&&n.loadPlugin(s.plugins.pings()));for(var o=0;o<t.length;o++)t[o](n)},u=function(n,t,o){if(o.onInit.length){var i=0,e=function(n){var t=o.onInit[i];t.length?t(function(){i++,n()}):(t(),i++,setTimeout(n,0))},l=function(){i>=o.onInit.length?r(n,t,o):e(l)};e(l)}else r(n,t,o)},a=function(n,t,o,i){l(n,o),n.canvas=t,n.context=t.getContext("2d"),u(n,t,i)},s={plugins:{},noConflict:function(){return o.planetaryjs=i,s},loadPlugin:function(n){e.push(n)},planet:function(){var t=[],o={onInit:[],onDraw:[]},i={plugins:{},draw:function(n){a(i,n,t,o)},onInit:function(n){o.onInit.push(n)},onDraw:function(n){o.onDraw.push(n)},loadPlugin:function(n){t.push(n)},withSavedContext:function(n){if(!this.context)throw new Error("No canvas to fetch context for");this.context.save(),n(this.context),this.context.restore()}};return i.projection=n.geo.orthographic().clipAngle(90).precision(0),i.path=n.geo.path().projection(i.projection),i}};return s.plugins.topojson=function(t){return function(o){o.plugins.topojson={},o.onInit(function(i){if(t.world)o.plugins.topojson.world=t.world,setTimeout(i,0);else{var e=t.file||"world-110m.json";n.json(e,function(n,t){if(n)throw new Error("Could not load JSON "+e);o.plugins.topojson.world=t,i()})}})}},s.plugins.oceans=function(n){return function(t){t.onDraw(function(){t.withSavedContext(function(o){o.beginPath(),t.path.context(o)({type:"Sphere"}),o.fillStyle=n.fill||"black",o.fill()})})}},s.plugins.land=function(n){return function(o){var i=null;o.onInit(function(){var n=o.plugins.topojson.world;i=t.feature(n,n.objects.land)}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),0!=n.fill&&(t.fillStyle=n.fill||"white",t.fill()),n.stroke&&(n.lineWidth&&(t.lineWidth=n.lineWidth),t.strokeStyle=n.stroke,t.stroke())})})}},s.plugins.borders=function(n){return function(o){var i=null,e={internal:function(n,t){return n.id!==t.id},external:function(n,t){return n.id===t.id},both:function(){return!0}};o.onInit(function(){var r=o.plugins.topojson.world,l=r.objects.countries,u=n.type||"internal";i=t.mesh(r,l,e[u])}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),t.strokeStyle=n.stroke||"gray",n.lineWidth&&(t.lineWidth=n.lineWidth),t.stroke()})})}},s.plugins.earth=function(n){var n=n||{},t=n.topojson||{},o=n.oceans||{},i=n.land||{},e=n.borders||{};return function(n){s.plugins.topojson(t)(n),s.plugins.oceans(o)(n),s.plugins.land(i)(n),s.plugins.borders(e)(n)}},s.plugins.pings=function(t){var o=[],i=function(n,i,e){var e=e||{};e.color=e.color||t.color||"white",e.ttl=e.ttl||t.ttl||2e3,e.angle=e.angle||t.angle||5,o.push({lat:n,lng:i,time:new Date,options:e})},e=function(n,t,i){for(var e=[],l=0;l<o.length;l++){var u=o[l],a=i-u.time;a<u.options.ttl&&(e.push(u),r(n,t,i,a,u))}o=e},r=function(t,o,i,e,r){var l=1-e/r.options.ttl,u=n.rgb(r.options.color);u="rgba("+u.r+","+u.g+","+u.b+","+l+")",o.strokeStyle=u;var a=n.geo.circle().origin([r.lng,r.lat]).angle(e/r.options.ttl*r.options.angle)();o.beginPath(),t.path.context(o)(a),o.stroke()};return function(n){n.plugins.pings={add:i},n.onDraw(function(){var t=new Date;n.withSavedContext(function(o){e(n,o,t)})})}},s}); !function(n,t){"function"==typeof define&&define.amd?define(["d3","topojson"],t):"object"==typeof exports?module.exports=t(require("d3"),require("topojson")):n.planetaryjs=t(n.d3,n.topojson,n)}(this,function(n,t,o){"use strict";var i=null;o&&(i=o.planetaryjs);var e=[],r=function(t,o,i){n.timer(function(){t.context.clearRect(0,0,o.width,o.height);for(var n=0;n<i.onDraw.length;n++)i.onDraw[n]()})},l=function(n,t){for(var o=0;o<e.length;o++)t.unshift(e[o]);0==t.length&&(c.plugins.earth&&n.loadPlugin(c.plugins.earth()),c.plugins.pings&&n.loadPlugin(c.plugins.pings()));for(var o=0;o<t.length;o++)t[o](n)},a=function(n,t,o){if(o.onInit.length){var i=0,e=function(n){var t=o.onInit[i];t.length?t(function(){i++,n()}):(t(),i++,setTimeout(n,0))},l=function(){i>=o.onInit.length?r(n,t,o):e(l)};e(l)}else r(n,t,o)},u=function(n,t,o,i){l(n,o),n.canvas=t,n.context=t.getContext("2d"),a(n,t,i)},c={plugins:{},noConflict:function(){return o.planetaryjs=i,c},loadPlugin:function(n){e.push(n)},planet:function(){var t=[],o={onInit:[],onDraw:[]},i={plugins:{},draw:function(n){u(i,n,t,o)},onInit:function(n){o.onInit.push(n)},onDraw:function(n){o.onDraw.push(n)},loadPlugin:function(n){t.push(n)},withSavedContext:function(n){if(!this.context)throw new Error("No canvas to fetch context for");this.context.save(),n(this.context),this.context.restore()}};return i.projection=n.geo.orthographic().clipAngle(90).precision(0),i.path=n.geo.path().projection(i.projection),i}};return c.plugins.topojson=function(t){return function(o){o.plugins.topojson={},o.onInit(function(i){if(t.world)o.plugins.topojson.world=t.world,setTimeout(i,0);else{var e=t.file||"world-110m.json";n.json(e,function(n,t){if(n)throw new Error("Could not load JSON "+e);o.plugins.topojson.world=t,i()})}})}},c.plugins.oceans=function(n){return function(t){t.onDraw(function(){t.withSavedContext(function(o){o.beginPath(),t.path.context(o)({type:"Sphere"}),o.fillStyle=n.fill||"black",o.fill()})})}},c.plugins.land=function(n){return function(o){var i=null;o.onInit(function(){var n=o.plugins.topojson.world;i=t.feature(n,n.objects.land)}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),0!=n.fill&&(t.fillStyle=n.fill||"white",t.fill()),n.stroke&&(n.lineWidth&&(t.lineWidth=n.lineWidth),t.strokeStyle=n.stroke,t.stroke())})})}},c.plugins.borders=function(n){return function(o){var i=null,e={internal:function(n,t){return n.id!==t.id},external:function(n,t){return n.id===t.id},both:function(){return!0}};o.onInit(function(){var r=o.plugins.topojson.world,l=r.objects.countries,a=n.type||"internal";i=t.mesh(r,l,e[a])}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),t.strokeStyle=n.stroke||"gray",n.lineWidth&&(t.lineWidth=n.lineWidth),t.stroke()})})}},c.plugins.earth=function(n){var n=n||{},t=n.topojson||{},o=n.oceans||{},i=n.land||{},e=n.borders||{};return function(n){c.plugins.topojson(t)(n),c.plugins.oceans(o)(n),c.plugins.land(i)(n),c.plugins.borders(e)(n)}},c.plugins.pings=function(t){var o=[],i=function(n,i,e){var e=e||{};e.color=e.color||t.color||"white",e.ttl=e.ttl||t.ttl||2e3,e.angle=e.angle||t.angle||5,o.push({lat:n,lng:i,time:new Date,options:e})},e=function(n,t,i){for(var e=[],l=0;l<o.length;l++){var a=o[l],u=i-a.time;u<a.options.ttl&&(e.push(a),r(n,t,i,u,a))}o=e},r=function(t,o,i,e,r){var l=1-e/r.options.ttl,a=n.rgb(r.options.color);a="rgba("+a.r+","+a.g+","+a.b+","+l+")",o.strokeStyle=a;var u=n.geo.circle().origin([r.lng,r.lat]).angle(e/r.options.ttl*r.options.angle)();o.beginPath(),t.path.context(o)(u),o.stroke()};return function(n){n.plugins.pings={add:i},n.onDraw(function(){var t=new Date;n.withSavedContext(function(o){e(n,o,t)})})}},c.plugins.zoom=function(t){var t=t||{},o=function(){},i=t.onZoomStart||o,e=t.onZoomEnd||o,r=t.onZoom||o,l=t.initialScale,a=t.scaleExtent||[50,2e3];return function(t){t.onInit(function(){var o=n.behavior.zoom().scaleExtent(a);l?o.scale(l):o.scale(t.projection.scale()),o.on("zoomstart",i).on("zoomend",e).on("zoom",function(){r(),t.projection.scale(n.event.scale)}),n.select(t.canvas).call(o)})}},c.plugins.drag=function(t){var t=t||{},o=function(){},i=t.onDragStart||o,e=t.onDragEnd||o,r=t.onDrag||o;return function(t){t.onInit(function(){var o=n.behavior.drag().on("dragstart",i).on("dragend",e).on("drag",function(){r();var o=n.event.dx,i=n.event.dy,e=t.projection.rotate(),l=t.projection.scale(),a=n.scale.linear().domain([-1*l,l]).range([-90,90]),u=a(o),c=a(i);e[0]+=u,e[1]-=c,e[1]>90&&(e[1]=90),e[1]<-90&&(e[1]=-90),e[0]>=180&&(e[0]-=360),t.projection.rotate(e)});n.select(t.canvas).call(o)})}},c});

View File

@ -67,6 +67,7 @@ a.ui.icon.header {
canvas#homepage-globe-canvas { canvas#homepage-globe-canvas {
width: 350px; width: 350px;
height: 350px; height: 350px;
cursor: move;
} }
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {

View File

@ -1,4 +1,25 @@
Drag Plugin Drag Plugin
=========== ===========
This plugin is not yet impelemented. The `drag` plugin allows for modifying the planet's projection's rotation with the mouse wheel. It supports dragging vertically with hard stops at the north and south poles, and dragging horizontally without restriction.
API
---
**`planetaryjs.plugins.drag([config])`**
Valid keys for `config` are:
* `onDrag`, `onDragStart`, `onDragEnd`: hooks to the `d3.behavior.drag` object's `drag`, `dragstart`, and `dragend` events; each defaults to a no-op
<div class='ui raise segment'>
<div class='ui red ribbon label'>JavaScript</div>
```javascript
planetaryjs.plugins.drag({
onDrag: function() {
console.log("The planet was dragged!", d3.event);
}
});
```
</div>

View File

@ -1,4 +1,28 @@
Zoom Plugin Zoom Plugin
=========== ===========
This plugin is not yet impelemented. The `zoom` plugin allows for modifying the planet's projection's scale with the mouse wheel.
API
---
**`planetaryjs.plugins.zoom([config])`**
Valid keys for `config` are:
* `initialScale`: the value to initialize the [`d3.behavior.zoom`](https://github.com/mbostock/d3/wiki/Zoom-Behavior) object's scale to; defaults to the scale of the planet's projection at the time the planet is initialized
* `scaleExtent`: the value to use for the `d3.behavior.zoom` object's `scaleExtent` property, which defines how far in and out the planet can be zoomed; defaults to `[50, 2000]`
* `onZoom`, `onZoomStart`, `onZoomEnd`: hooks to the `d3.behavior.zoom` object's `zoom`, `zoomstart`, and `zoomend` events; each defaults to a no-op
<div class='ui raise segment'>
<div class='ui red ribbon label'>JavaScript</div>
```javascript
planetaryjs.plugins.zoom({
scaleExtent: [200, 1000],
onZoom: function() {
console.log("The planet was zoomed!", d3.event);
}
});
```
</div>

View File

@ -12,6 +12,21 @@
globe.loadPlugin(planetaryjs.plugins.pings()); globe.loadPlugin(planetaryjs.plugins.pings());
// Load our custom `autorotate` plugin; see below. // Load our custom `autorotate` plugin; see below.
globe.loadPlugin(autorotate(10)); globe.loadPlugin(autorotate(10));
// The `zoom` and `drag` plugins enable
// manipulating the globe with the mouse.
globe.loadPlugin(planetaryjs.plugins.zoom({
scaleExtent: [100, 300]
}));
globe.loadPlugin(planetaryjs.plugins.drag({
// Dragging the globe shoud pause the
// automatic rotation until we release the mouse.
onDragStart: function() {
globe.plugins.autorotate.pause();
},
onDragEnd: function() {
globe.plugins.autorotate.resume();
}
}))
// Set up the globe's initial scale, offset, and rotation. // Set up the globe's initial scale, offset, and rotation.
globe.projection.scale(175).translate([175, 175]).rotate([0, -10, 0]); globe.projection.scale(175).translate([175, 175]).rotate([0, -10, 0]);
@ -43,9 +58,14 @@
// as an argument... // as an argument...
return function(planet) { return function(planet) {
var lastTick = null; var lastTick = null;
var paused = false;
planet.plugins.autorotate = {
pause: function() { paused = true; },
resume: function() { paused = false; }
};
// ...and configure hooks into certain pieces of its lifecycle. // ...and configure hooks into certain pieces of its lifecycle.
planet.onDraw(function() { planet.onDraw(function() {
if (!lastTick) { if (paused || !lastTick) {
lastTick = new Date(); lastTick = new Date();
} else { } else {
var now = new Date(); var now = new Date();

View File

@ -1,2 +1,2 @@
/*! Planetary.js 0.2.0 | (c) 2013 Brandon Tilley | Released under MIT License */ /*! Planetary.js 0.2.0 | (c) 2013 Brandon Tilley | Released under MIT License */
!function(n,t){"function"==typeof define&&define.amd?define(["d3","topojson"],t):"object"==typeof exports?module.exports=t(require("d3"),require("topojson")):n.planetaryjs=t(n.d3,n.topojson,n)}(this,function(n,t,o){"use strict";var i=null;o&&(i=o.planetaryjs);var e=[],r=function(t,o,i){n.timer(function(){t.context.clearRect(0,0,o.width,o.height);for(var n=0;n<i.onDraw.length;n++)i.onDraw[n]()})},l=function(n,t){for(var o=0;o<e.length;o++)t.unshift(e[o]);0==t.length&&(s.plugins.earth&&n.loadPlugin(s.plugins.earth()),s.plugins.pings&&n.loadPlugin(s.plugins.pings()));for(var o=0;o<t.length;o++)t[o](n)},u=function(n,t,o){if(o.onInit.length){var i=0,e=function(n){var t=o.onInit[i];t.length?t(function(){i++,n()}):(t(),i++,setTimeout(n,0))},l=function(){i>=o.onInit.length?r(n,t,o):e(l)};e(l)}else r(n,t,o)},a=function(n,t,o,i){l(n,o),n.canvas=t,n.context=t.getContext("2d"),u(n,t,i)},s={plugins:{},noConflict:function(){return o.planetaryjs=i,s},loadPlugin:function(n){e.push(n)},planet:function(){var t=[],o={onInit:[],onDraw:[]},i={plugins:{},draw:function(n){a(i,n,t,o)},onInit:function(n){o.onInit.push(n)},onDraw:function(n){o.onDraw.push(n)},loadPlugin:function(n){t.push(n)},withSavedContext:function(n){if(!this.context)throw new Error("No canvas to fetch context for");this.context.save(),n(this.context),this.context.restore()}};return i.projection=n.geo.orthographic().clipAngle(90).precision(0),i.path=n.geo.path().projection(i.projection),i}};return s.plugins.topojson=function(t){return function(o){o.plugins.topojson={},o.onInit(function(i){if(t.world)o.plugins.topojson.world=t.world,setTimeout(i,0);else{var e=t.file||"world-110m.json";n.json(e,function(n,t){if(n)throw new Error("Could not load JSON "+e);o.plugins.topojson.world=t,i()})}})}},s.plugins.oceans=function(n){return function(t){t.onDraw(function(){t.withSavedContext(function(o){o.beginPath(),t.path.context(o)({type:"Sphere"}),o.fillStyle=n.fill||"black",o.fill()})})}},s.plugins.land=function(n){return function(o){var i=null;o.onInit(function(){var n=o.plugins.topojson.world;i=t.feature(n,n.objects.land)}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),0!=n.fill&&(t.fillStyle=n.fill||"white",t.fill()),n.stroke&&(n.lineWidth&&(t.lineWidth=n.lineWidth),t.strokeStyle=n.stroke,t.stroke())})})}},s.plugins.borders=function(n){return function(o){var i=null,e={internal:function(n,t){return n.id!==t.id},external:function(n,t){return n.id===t.id},both:function(){return!0}};o.onInit(function(){var r=o.plugins.topojson.world,l=r.objects.countries,u=n.type||"internal";i=t.mesh(r,l,e[u])}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),t.strokeStyle=n.stroke||"gray",n.lineWidth&&(t.lineWidth=n.lineWidth),t.stroke()})})}},s.plugins.earth=function(n){var n=n||{},t=n.topojson||{},o=n.oceans||{},i=n.land||{},e=n.borders||{};return function(n){s.plugins.topojson(t)(n),s.plugins.oceans(o)(n),s.plugins.land(i)(n),s.plugins.borders(e)(n)}},s.plugins.pings=function(t){var o=[],i=function(n,i,e){var e=e||{};e.color=e.color||t.color||"white",e.ttl=e.ttl||t.ttl||2e3,e.angle=e.angle||t.angle||5,o.push({lat:n,lng:i,time:new Date,options:e})},e=function(n,t,i){for(var e=[],l=0;l<o.length;l++){var u=o[l],a=i-u.time;a<u.options.ttl&&(e.push(u),r(n,t,i,a,u))}o=e},r=function(t,o,i,e,r){var l=1-e/r.options.ttl,u=n.rgb(r.options.color);u="rgba("+u.r+","+u.g+","+u.b+","+l+")",o.strokeStyle=u;var a=n.geo.circle().origin([r.lng,r.lat]).angle(e/r.options.ttl*r.options.angle)();o.beginPath(),t.path.context(o)(a),o.stroke()};return function(n){n.plugins.pings={add:i},n.onDraw(function(){var t=new Date;n.withSavedContext(function(o){e(n,o,t)})})}},s}); !function(n,t){"function"==typeof define&&define.amd?define(["d3","topojson"],t):"object"==typeof exports?module.exports=t(require("d3"),require("topojson")):n.planetaryjs=t(n.d3,n.topojson,n)}(this,function(n,t,o){"use strict";var i=null;o&&(i=o.planetaryjs);var e=[],r=function(t,o,i){n.timer(function(){t.context.clearRect(0,0,o.width,o.height);for(var n=0;n<i.onDraw.length;n++)i.onDraw[n]()})},l=function(n,t){for(var o=0;o<e.length;o++)t.unshift(e[o]);0==t.length&&(c.plugins.earth&&n.loadPlugin(c.plugins.earth()),c.plugins.pings&&n.loadPlugin(c.plugins.pings()));for(var o=0;o<t.length;o++)t[o](n)},a=function(n,t,o){if(o.onInit.length){var i=0,e=function(n){var t=o.onInit[i];t.length?t(function(){i++,n()}):(t(),i++,setTimeout(n,0))},l=function(){i>=o.onInit.length?r(n,t,o):e(l)};e(l)}else r(n,t,o)},u=function(n,t,o,i){l(n,o),n.canvas=t,n.context=t.getContext("2d"),a(n,t,i)},c={plugins:{},noConflict:function(){return o.planetaryjs=i,c},loadPlugin:function(n){e.push(n)},planet:function(){var t=[],o={onInit:[],onDraw:[]},i={plugins:{},draw:function(n){u(i,n,t,o)},onInit:function(n){o.onInit.push(n)},onDraw:function(n){o.onDraw.push(n)},loadPlugin:function(n){t.push(n)},withSavedContext:function(n){if(!this.context)throw new Error("No canvas to fetch context for");this.context.save(),n(this.context),this.context.restore()}};return i.projection=n.geo.orthographic().clipAngle(90).precision(0),i.path=n.geo.path().projection(i.projection),i}};return c.plugins.topojson=function(t){return function(o){o.plugins.topojson={},o.onInit(function(i){if(t.world)o.plugins.topojson.world=t.world,setTimeout(i,0);else{var e=t.file||"world-110m.json";n.json(e,function(n,t){if(n)throw new Error("Could not load JSON "+e);o.plugins.topojson.world=t,i()})}})}},c.plugins.oceans=function(n){return function(t){t.onDraw(function(){t.withSavedContext(function(o){o.beginPath(),t.path.context(o)({type:"Sphere"}),o.fillStyle=n.fill||"black",o.fill()})})}},c.plugins.land=function(n){return function(o){var i=null;o.onInit(function(){var n=o.plugins.topojson.world;i=t.feature(n,n.objects.land)}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),0!=n.fill&&(t.fillStyle=n.fill||"white",t.fill()),n.stroke&&(n.lineWidth&&(t.lineWidth=n.lineWidth),t.strokeStyle=n.stroke,t.stroke())})})}},c.plugins.borders=function(n){return function(o){var i=null,e={internal:function(n,t){return n.id!==t.id},external:function(n,t){return n.id===t.id},both:function(){return!0}};o.onInit(function(){var r=o.plugins.topojson.world,l=r.objects.countries,a=n.type||"internal";i=t.mesh(r,l,e[a])}),o.onDraw(function(){o.withSavedContext(function(t){t.beginPath(),o.path.context(t)(i),t.strokeStyle=n.stroke||"gray",n.lineWidth&&(t.lineWidth=n.lineWidth),t.stroke()})})}},c.plugins.earth=function(n){var n=n||{},t=n.topojson||{},o=n.oceans||{},i=n.land||{},e=n.borders||{};return function(n){c.plugins.topojson(t)(n),c.plugins.oceans(o)(n),c.plugins.land(i)(n),c.plugins.borders(e)(n)}},c.plugins.pings=function(t){var o=[],i=function(n,i,e){var e=e||{};e.color=e.color||t.color||"white",e.ttl=e.ttl||t.ttl||2e3,e.angle=e.angle||t.angle||5,o.push({lat:n,lng:i,time:new Date,options:e})},e=function(n,t,i){for(var e=[],l=0;l<o.length;l++){var a=o[l],u=i-a.time;u<a.options.ttl&&(e.push(a),r(n,t,i,u,a))}o=e},r=function(t,o,i,e,r){var l=1-e/r.options.ttl,a=n.rgb(r.options.color);a="rgba("+a.r+","+a.g+","+a.b+","+l+")",o.strokeStyle=a;var u=n.geo.circle().origin([r.lng,r.lat]).angle(e/r.options.ttl*r.options.angle)();o.beginPath(),t.path.context(o)(u),o.stroke()};return function(n){n.plugins.pings={add:i},n.onDraw(function(){var t=new Date;n.withSavedContext(function(o){e(n,o,t)})})}},c.plugins.zoom=function(t){var t=t||{},o=function(){},i=t.onZoomStart||o,e=t.onZoomEnd||o,r=t.onZoom||o,l=t.initialScale,a=t.scaleExtent||[50,2e3];return function(t){t.onInit(function(){var o=n.behavior.zoom().scaleExtent(a);l?o.scale(l):o.scale(t.projection.scale()),o.on("zoomstart",i).on("zoomend",e).on("zoom",function(){r(),t.projection.scale(n.event.scale)}),n.select(t.canvas).call(o)})}},c.plugins.drag=function(t){var t=t||{},o=function(){},i=t.onDragStart||o,e=t.onDragEnd||o,r=t.onDrag||o;return function(t){t.onInit(function(){var o=n.behavior.drag().on("dragstart",i).on("dragend",e).on("drag",function(){r();var o=n.event.dx,i=n.event.dy,e=t.projection.rotate(),l=t.projection.scale(),a=n.scale.linear().domain([-1*l,l]).range([-90,90]),u=a(o),c=a(i);e[0]+=u,e[1]-=c,e[1]>90&&(e[1]=90),e[1]<-90&&(e[1]=-90),e[0]>=180&&(e[0]-=360),t.projection.rotate(e)});n.select(t.canvas).call(o)})}},c});

View File

@ -161,3 +161,68 @@
}); });
}; };
}; };
planetaryjs.plugins.zoom = function (options) {
var options = options || {};
var noop = function() {};
var onZoomStart = options.onZoomStart || noop;
var onZoomEnd = options.onZoomEnd || noop;
var onZoom = options.onZoom || noop;
var startScale = options.initialScale;
var scaleExtent = options.scaleExtent || [50, 2000];
return function(planet) {
planet.onInit(function() {
var zoom = d3.behavior.zoom()
.scaleExtent(scaleExtent);
if (startScale) {
zoom.scale(startScale);
} else {
zoom.scale(planet.projection.scale());
}
zoom
.on('zoomstart', onZoomStart)
.on('zoomend', onZoomEnd)
.on('zoom', function() {
onZoom();
planet.projection.scale(d3.event.scale);
});
d3.select(planet.canvas).call(zoom);
});
};
};
planetaryjs.plugins.drag = function(options) {
var options = options || {};
var noop = function() {};
var onDragStart = options.onDragStart || noop;
var onDragEnd = options.onDragEnd || noop;
var onDrag = options.onDrag || noop;
return function(planet) {
planet.onInit(function() {
var drag = d3.behavior.drag()
.on('dragstart', onDragStart)
.on('dragend', onDragEnd)
.on('drag', function() {
onDrag();
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = planet.projection.rotate();
var radius = planet.projection.scale();
var scale = d3.scale.linear()
.domain([-1 * radius, radius])
.range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
planet.projection.rotate(rotation);
});
d3.select(planet.canvas).call(drag);
});
};
};