Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active February 9, 2016 00:26
Show Gist options
  • Save mbostock/1177880 to your computer and use it in GitHub Desktop.
Save mbostock/1177880 to your computer and use it in GitHub Desktop.
Pixymaps (Scrolling)
license: gpl-3.0
<!DOCTYPE html>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="pixymaps.min.js"></script>
<style>
body {
font: 10px sans-serif;
}
#container {
width: 960px;
height: 500px;
overflow: hidden;
}
</style>
<div id="container">
<canvas id="map"></canvas>
</div>
<script>
var canvas = d3.select("#map"),
context = canvas.node().getContext("2d");
var w = 960,
h = 500,
lon = -122.41948,
lat = 37.76487;
var project = d3.geo.mercator()
.scale(1 / (2 * Math.PI))
.translate([.5, .5]);
var view = pixymaps.view()
.size([w, h])
.center(project([lon, lat]))
.zoom(12);
var image = pixymaps.image()
.view(view)
.url(pixymaps.url("http://{S}tile.cloudmade.com"
+ "/1a1b06b230af4efdbb989ea99e9841af" // http://cloudmade.com/register
+ "/999/256/{Z}/{X}/{Y}.png")
.hosts(["a.", "b.", "c.", ""]))
.render(canvas.node());
var speed = 0,
acceleration = -.05;
d3.timer(function() {
speed = Math.max(-5, speed + acceleration);
view.panBy([speed, 0]);
image.render(canvas.node());
});
</script>
(function(){function p(a){a.active>=m||!a.queued.length||(a.active++,a.queued.pop()())}function o(a,b){function g(a){d.active--,++e.attempt<n?d.queued.push(e):b(null),p(d)}function f(){d.active--,b(this),p(d)}function e(){var b=new Image;b.onload=f,b.onerror=g,b.src=a}var c=(l.lastIndex=0,l).exec(a)[2]||"",d=k[c]||(k[c]={active:0,queued:[]});e.attempt=0,d.queued.push(e),p(d)}function j(a,b,c,d){var e=h(a,b),f=h(b,c),g=h(c,a);if(e.dy>f.dy){var j=e;e=f,f=j}if(e.dy>g.dy){var j=e;e=g,g=j}if(f.dy>g.dy){var j=f;f=g,g=j}e.dy&&i(g,e,d),f.dy&&i(g,f,d)}function i(a,b,c){var d=Math.floor(b.y0),e=Math.ceil(b.y1);if(a.x0==b.x0&&a.y0==b.y0?a.x0+b.dy/a.dy*a.dx<b.x1:a.x1-b.dy/a.dy*a.dx<b.x0){var f=a;a=b,b=f}var g=a.dx/a.dy,h=b.dx/b.dy,i=a.dx>0,j=b.dx<0;for(var k=d;k<e;k++){var l=Math.ceil(g*Math.max(0,Math.min(a.dy,k+i-a.y0))+a.x0),m=Math.floor(h*Math.max(0,Math.min(b.dy,k+j-b.y0))+b.x0);for(var n=m;n<l;n++)c(n,k)}}function h(a,b){if(a[1]>b[1]){var c=a;a=b,b=c}return{x0:a[0],y0:a[1],x1:b[0],y1:b[1],dx:b[0]-a[0],dy:b[1]-a[1]}}function g(){for(var f=c;d>e&&f;f=f.previous){d--,delete a[f.key];if(f.next)f.next.previous=f.previous;else if(c=f.previous)c.next=null;if(f.previous)f.previous.next=f.next;else if(b=f.next)b.previous=null}}function f(e,f){var h=a[e];if(h){h.previous&&(h.previous.next=h.next,h.next?h.next.previous=h.previous:c=h.previous,h.previous=null,h.next=b,b.previous=h,b=h);return h.callbacks?h.callbacks.push(f):f(h.value)}h=a[e]={key:e,next:b,previous:null,callbacks:[f]},b?b.previous=h:c=h,b=h,d++,g(),o(e,function(a){var b=h.callbacks;delete h.callbacks,h.value=a,b.forEach(function(b){b(a)})})}pixymaps={version:"0.0.1"};var a={},b=null,c=null,d=0,e=512;pixymaps.image=function(){var a={},b,c,d=Math.round;a.view=function(c){if(!arguments.length)return b;b=c;return a},a.url=function(b){if(!arguments.length)return c;c=typeof b=="string"&&/{.}/.test(b)?_url(b):b;return a},a.zoom=function(b){if(!arguments.length)return d;d=typeof b=="function"?b:function(){return b};return a},a.render=function(e,g){function D(a,b){C=A.push([a,b,B])}var h=e.getContext("2d"),i=b.size(),k=b.angle(),l=b.center(),m=l[2],n=b.coordinateSize(),o=m-(m=d(m)),p=Math.pow(2,-o),q=b.coordinate([0,0]),r=b.coordinate([i[0],0]),s=b.coordinate(i),t=b.coordinate([0,i[1]]);q[0]*=p,r[0]*=p,s[0]*=p,t[0]*=p,q[1]*=p,r[1]*=p,s[1]*=p,t[1]*=p,q[2]=r[2]=s[2]=t[2]-=o;var u=Math.floor(Math.min(q[0],r[0],s[0],t[0])),v=Math.ceil(Math.max(q[0],r[0],s[0],t[0])),w=Math.floor(Math.min(q[1],r[1],s[1],t[1])),x=Math.ceil(Math.max(q[1],r[1],s[1],t[1])),y=n[0],z=n[1],A=[],B=q[2],C=0;j(q,r,s,D),j(s,t,q,D);var E=i[0]/2+y*(u-l[0]*p)|0,F=i[1]/2+z*(w-l[1]*p)|0;e.style.webkitTransform="matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,"+E+","+F+",0,1)",e.width=(v-u)*y,e.height=(x-w)*z,A.forEach(function(a){function d(){!--C&&g&&g()}var b=c(a);return b==null?d():f(b,function(b){h.drawImage(b,y*(a[0]-u),z*(a[1]-w)),d()})});return a};return a};var k={},l=/^(?:([^:\/?\#]+):)?(?:\/\/([^\/?\#]*))?([^?\#]*)(?:\?([^\#]*))?(?:\#(.*))?/,m=4,n=4;pixymaps.url=function(a){function d(d){var e=d[0],f=d[1],g=d[2],h=1<<g;/^repeat(-x)?$/.test(c)&&(e=e%h)<0&&(e+=h),/^repeat(-y)?$/.test(c)&&(f=f%h)<0&&(f+=h);if(g<0||e<0||e>=h||f<0||f>=h)return null;return a.replace(/{(.)}/g,function(a,c){switch(c){case"X":return e;case"Y":return f;case"Z":return g;case"S":return b[Math.abs(e+f+g)%b.length]}return c})}var b=[],c="repeat-x";d.template=function(b){if(!arguments.length)return a;a=b;return d},d.hosts=function(a){if(!arguments.length)return b;b=a;return d},d.repeat=function(a){if(!arguments.length)return c;c=a;return d};return d},pixymaps.view=function(){function j(b){var c=Math.pow(2,b);return a.center([d[0]*c,d[1]*c,d[2]+b])}var a={},b=[0,0],c=[256,256],d=[.5,.5,0],e=0,f=1,g=0,h=1,i=0;a.point=function(a){var e=Math.pow(2,d[2]-(a.length<3?0:a[2])),h=(a[0]*e-d[0])*c[0],i=(a[1]*e-d[1])*c[1];return[b[0]/2+f*h-g*i,b[1]/2+g*h+f*i]},a.coordinate=function(a){var e=a[0]-b[0]/2;dy=a[1]-b[1]/2;return[d[0]+(h*e-i*dy)/c[0],d[1]+(i*e+h*dy)/c[1],d[2]]},a.coordinateSize=function(b){if(!arguments.length)return c;c=b;return a},a.size=function(c){if(!arguments.length)return b;b=c;return a},a.center=function(b){if(!arguments.length)return d;d=b,d.length<3&&(d[2]=0);return a},a.zoom=function(a){if(!arguments.length)return d[2];return j(a-d[2])},a.angle=function(b){if(!arguments.length)return e;e=b,f=Math.cos(e),g=Math.sin(e),h=Math.cos(-e),i=Math.sin(-e);return a},a.panBy=function(b){return a.center([d[0]-(i*b[1]+h*b[0])/c[0],d[1]-(h*b[1]-i*b[0])/c[1],d[2]])},a.zoomBy=function(b,c,d){if(arguments.length<2)return j(b);arguments.length<3&&(d=a.coordinate(c));var e=j(b).point(d);return a.panBy([c[0]-e[0],c[1]-e[1]])},a.rotateBy=function(b){return a.angle(e+b)};return a}})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment