From 86a1b8a3814ab843f84a12cf49911ac441fa84f1 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 25 Aug 2010 17:52:39 -0700 Subject: [PATCH] Better browser workarounds. Rollback commit 73168a7, which didn't entirely solve the problem for Firefox and introduced new artifacts in WebKit browsers. The root problem is that Firefox positions the SVG image with subpixel accuracy (as evinced by getScreenCTM() returning subpixel values for the `e` and `f` attributes), and so even if the SVG internally positions images at even pixel boundaries, Firefox still has anti-aliasing artifacts. A proper solution to this problem is trickier than I thought, and since it's only a minor aesthetic problem I'm going to ignore it for now. The `wheel` control now triggers the wheel speed dampening if a single large wheelDelta is seen, rather than trying to compute a moving average of the wheel speed. This means that false positives are more annoying, but false negatives are significantly less likely, so this should be a significant improvement for Safari and Chrome. Lastly, there's a workaround for the broken getScreenCTM in WebKit browsers when the window is scrolled! Hooray. --- polymaps.js | 41 ++++++++++++++------- polymaps.min.js | 97 +++++++++++++++++++++++++------------------------ src/Layer.js | 8 ++-- src/Map.js | 20 +++++++++- src/Wheel.js | 11 +++--- src/start.js | 2 +- 6 files changed, 105 insertions(+), 74 deletions(-) diff --git a/polymaps.js b/polymaps.js index 8ae67b6..7dae5f3 100644 --- a/polymaps.js +++ b/polymaps.js @@ -2,7 +2,7 @@ if (!org) var org = {}; if (!org.polymaps) org.polymaps = {}; (function(po){ - po.version = "2.0.2"; // semver.org + po.version = "2.0.2+1"; // This fork not semver! var zero = {x: 0, y: 0}; po.id = (function() { @@ -451,8 +451,21 @@ po.map = function() { map.mouse = function(e) { var point = (container.ownerSVGElement || container).createSVGPoint(); - point.x = e.clientX; - point.y = e.clientY; + if ((bug44083 < 0) && (window.scrollX || window.scrollY)) { + var svg = document.body.appendChild(po.svg("svg")); + svg.style.position = "absolute"; + svg.style.top = svg.style.left = "0px"; + var ctm = svg.getScreenCTM(); + bug44083 = !(ctm.f || ctm.e); + document.body.removeChild(svg); + } + if (bug44083) { + point.x = e.pageX; + point.y = e.pageY; + } else { + point.x = e.clientX; + point.y = e.clientY; + } return point.matrixTransform(container.getScreenCTM().inverse()); }; @@ -640,6 +653,9 @@ po.map.coordinateLocation = function(c) { lat: y2lat(180 - k * c.row) }; }; + +// https://bugs.webkit.org/show_bug.cgi?id=44083 +var bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; po.layer = function(load, unload) { var layer = {}, cache = layer.cache = po.cache(load, unload).size(512), @@ -673,7 +689,7 @@ po.layer = function(load, unload) { // set the layer transform container.setAttribute("transform", - "translate(" + (mapSize.x >> 1) + "," + (mapSize.y >> 1) + ")" + "translate(" + (mapSize.x / 2) + "," + (mapSize.y / 2) + ")" + (mapAngle ? "rotate(" + mapAngle / Math.PI * 180 + ")" : "") + (mapZoomFraction ? "scale(" + Math.pow(2, mapZoomFraction) + ")" : "") + (transform ? transform.zoomFraction(mapZoomFraction) : "")); @@ -685,9 +701,9 @@ po.layer = function(load, unload) { c3 = map.pointCoordinate(tileCenter, {x: 0, y: mapSize.y}); // round to pixel boundary to avoid anti-aliasing artifacts - if (!transform && !mapAngle && !mapZoomFraction) { - tileCenter.column = Math.round(tileSize.x * tileCenter.column) / tileSize.x; - tileCenter.row = Math.round(tileSize.y * tileCenter.row) / tileSize.y; + if (!mapZoomFraction && !mapAngle && !transform) { + tileCenter.column = (Math.round(tileSize.x * tileCenter.column) + (mapSize.x & 1) / 2) / tileSize.x; + tileCenter.row = (Math.round(tileSize.y * tileCenter.row) + (mapSize.y & 1) / 2) / tileSize.y; } // layer-specific zoom transform @@ -1253,8 +1269,6 @@ po.wheel = function() { timePrev = 0, smooth = true, location, - speedBug = /WebKit\/533/.test(navigator.userAgent), - speedAvg = .3, map; function move(e) { @@ -1264,10 +1278,8 @@ po.wheel = function() { function mousewheel(e) { var delta = Math.max(-1, Math.min(1, (e.wheelDelta / 120 || -e.detail) * .1)), point = map.mouse(e); - if (speedBug) { - speedAvg = speedAvg * .95 + Math.abs(delta) * .05; - if (speedAvg > .5) delta *= .4; - } + if ((bug40441 < 0) && (Math.abs(e.wheelDelta) >= 4800)) bug40441 = 1; + if (bug40441 == 1) delta *= .1; if (!location) location = map.pointLocation(point); map.off("move", move); if (smooth) { @@ -1304,6 +1316,9 @@ po.wheel = function() { return wheel; }; + +// https://bugs.webkit.org/show_bug.cgi?id=40441 +var bug40441 = /WebKit\/533/.test(navigator.userAgent) ? -1 : 0; po.arrow = function() { var arrow = {}, key = {left: 0, right: 0, up: 0, down: 0, plus: 0, minus: 0}, diff --git a/polymaps.min.js b/polymaps.min.js index 2630aa6..300b5d6 100644 --- a/polymaps.min.js +++ b/polymaps.min.js @@ -1,49 +1,50 @@ if(!org)var org={};if(!org.polymaps)org.polymaps={}; -(function(r){function J(){for(var h=0;ha.row){var e=h;h=a;a=e}return{x0:h.column,y0:h.row,x1:a.column,y1:a.row,dx:a.column-h.column,dy:a.row-h.row}}function X(h,a,e,d,c){e=Math.max(e,Math.floor(a.y0));d=Math.min(d,Math.ceil(a.y1));if(h.x00,o=a.dx<0;for(e=e;ea.dy){e=i;i=a;a=e}if(i.dy>h.dy){e=i;i=h;h=e}if(a.dy>h.dy){e=a;a=h;h=e}i.dy&&X(h,i,d,c,g);a.dy&&X(h,a,d,c,g)}r.version="2.0.2";var R={x:0,y:0};r.id=function(){var h=0;return function(){return++h}}();r.svg=function(h){return document.createElementNS(r.ns.svg,h)};r.ns={svg:"http://www.w3.org/2000/svg", -xlink:"http://www.w3.org/1999/xlink"};r.transform=function(h,a,e,d,c,g){var i={},n,o,t;if(!arguments.length){h=1;a=c=e=0;d=1;g=0}i.zoomFraction=function(j){if(!arguments.length)return o;o=j;n=Math.floor(o+Math.log(Math.sqrt(h*h+a*a+e*e+d*d))/Math.log(2));t=Math.pow(2,-n);return i};i.apply=function(j){var k=Math.pow(2,-j.zoom),f=Math.pow(2,j.zoom-n);return{column:(h*j.column*k+e*j.row*k+c)*f,row:(a*j.column*k+d*j.row*k+g)*f,zoom:j.zoom-n}};i.unapply=function(j){var k=Math.pow(2,-j.zoom),f=Math.pow(2, -j.zoom+n);return{column:(j.column*k*d-j.row*k*e-c*d+g*e)/(h*d-a*e)*f,row:(j.column*k*a-j.row*k*h-c*a+g*h)/(e*a-d*h)*f,zoom:j.zoom+n}};i.toString=function(){return"matrix("+[h*t,a*t,e*t,d*t].join(" ")+" 0 0)"};return i.zoomFraction(0)};r.cache=function(h,a){function e(k){j--;a&&a(k);delete i[k.key];if(k.next)k.next.prev=k.prev;else if(o=k.prev)o.next=null;if(k.prev)k.prev.next=k.next;else if(n=k.next)n.prev=null}function d(){for(var k=o;j>t;k=k.prev){if(!k)break;k.lock||e(k)}}var c={},g={},i={},n= -null,o=null,t=64,j=0;c.peek=function(k){return i[[k.zoom,k.column,k.row].join("/")]};c.load=function(k,f){var q=[k.zoom,k.column,k.row].join("/"),s=i[q];if(s){if(s.prev){if(s.prev.next=s.next)s.next.prev=s.prev;else o=s.prev;s.prev=null;s.next=n;n=n.prev=s}s.lock=1;return g[q]=s}s={key:q,column:k.column,row:k.row,zoom:k.zoom,next:n,prev:null,lock:1};h.call(null,s,f);g[q]=i[q]=s;if(n)n.prev=s;else o=s;n=s;j++;d();return s};c.unload=function(k){if(!(k in g))return false;var f=g[k];f.lock=0;delete g[k]; -f.request&&f.request.abort(false)?e(f):d();return f};c.locks=function(){return g};c.size=function(k){if(!arguments.length)return t;t=k;d();return c};return c};r.url=function(h){function a(d){var c=1<=g||!d.length)){c++;d.pop()()}}function a(i){for(var n=0;n=0)return l;return window};a.mouse=function(l){var u=(e.ownerSVGElement||e).createSVGPoint();u.x=l.clientX;u.y=l.clientY;return u.matrixTransform(e.getScreenCTM().inverse())}; -a.size=function(l){if(!arguments.length)return c;d=l;return a.resize()};a.resize=function(){if(d){c=d;J.remove(a)}else{var l=e.ownerSVGElement||e;if(l.offsetWidth==null){C.setAttribute("width","100%");C.setAttribute("height","100%");l=C}b=l.getBoundingClientRect();c={x:b.width,y:b.height};J.add(a)}C.setAttribute("width",c.x);C.setAttribute("height",c.y);g={x:c.x/2,y:c.y/2};h();a.dispatch({type:"resize"});return a};a.tileSize=function(l){if(!arguments.length)return i;i=l;a.dispatch({type:"move"}); -return a};a.center=function(l){if(!arguments.length)return n;n=l;h();a.dispatch({type:"move"});return a};a.panBy=function(l){var u=45/Math.pow(2,o+t-3),y=l.x*u;l=l.y*u;return a.center({lon:n.lon+(w*l-m*y)/i.x,lat:P(Q(n.lat)+(w*y+m*l)/i.y)})};a.centerRange=function(l){if(!arguments.length)return G;if(G=l){B=G[0].lat>-90?Q(G[0].lat):-Infinity;I=G[0].lat<90?Q(G[1].lat):Infinity}else{B=-Infinity;I=Infinity}h();a.dispatch({type:"move"});return a};a.zoom=function(l){if(!arguments.length)return o+t;o=Math.max(k[0], -Math.min(k[1],l));t=o-(o=Math.round(o));j=Math.pow(2,t);return a.center(n)};a.zoomBy=function(l,u,y){if(arguments.length<2)return a.zoom(o+t+l);if(arguments.length<3)y=a.pointLocation(u);o=Math.max(k[0],Math.min(k[1],o+t+l));t=o-(o=Math.round(o));j=Math.pow(2,t);var D=a.locationPoint(y);return a.panBy({x:u.x-D.x,y:u.y-D.y})};a.zoomRange=function(l){if(!arguments.length)return k;k=l;return a.zoom(o+t)};a.angle=function(l){if(!arguments.length)return f;f=l;q=Math.cos(f);s=Math.sin(f);m=Math.cos(-f); -w=Math.sin(-f);h();a.dispatch({type:"move"});return a};a.add=function(l){l.map(a);return a};a.remove=function(l){l.map(null);return a};a.dispatch=r.dispatch(a);return a};J.maps=[];J.add=function(h){for(var a=0;a>L,row:F>>L,zoom:H-L}))&&K.ready){x[K.key]=c.load(S);K.proxyCount++;O.proxyRefs[K.key]=K;break}}x[O.key]=O}}var m=d.map(),w=m.zoom(),B=w-(w=Math.round(w)),I=m.size(),G=m.angle(),C=m.tileSize(),l=m.locationCoordinate(m.center()); -i?j.removeAttribute("visibility"):j.setAttribute("visibility","hidden");for(var u=-4;u<=2;u++)f[u].setAttribute("class","zoom"+(u<0?"":"+")+u+" zoom"+(w+u));j.setAttribute("transform","translate("+(I.x>>1)+","+(I.y>>1)+")"+(G?"rotate("+G/Math.PI*180+")":"")+(B?"scale("+Math.pow(2,B)+")":"")+(k?k.zoomFraction(B):""));var y=m.pointCoordinate(l,R);u=m.pointCoordinate(l,{x:I.x,y:0});var D=m.pointCoordinate(l,I);m=m.pointCoordinate(l,{x:0,y:I.y});if(!k&&!G&&!B){l.column=Math.round(C.x*l.column)/C.x;l.row= -Math.round(C.y*l.row)/C.y}var E=n?n(w)-w:0;if(E){B=Math.pow(2,E);y.column*=B;y.row*=B;u.column*=B;u.row*=B;D.column*=B;D.row*=B;m.column*=B;m.row*=B;y.zoom=u.zoom=D.zoom=m.zoom+=E}if(k){y=k.unapply(y);u=k.unapply(u);D=k.unapply(D);m=k.unapply(m);l=k.unapply(l)}w=c.locks();var x={};for(var v in w)w[v].proxyCount=0;if(i&&E>-5&&E<3){B=1<> -u<>u<=1;s--)(f[s]=j.appendChild(r.svg("g"))).setAttribute("transform","scale("+Math.pow(2,-s)+")");f[0]=j.appendChild(r.svg("g"));d.init&&d.init(j);t.on("move", -e).on("resize",e);e()}return d};d.container=function(){return j};d.id=function(q){if(!arguments.length)return o;o=q;return d};d.visible=function(q){if(!arguments.length)return i;i=q;t&&e();return d};d.transform=function(q){if(!arguments.length)return k;k=q;t&&e();return d};d.zoom=function(q){if(!arguments.length)return n;n=typeof q=="function"||q==null?q:function(){return q};return d};d.tile=function(q){if(!arguments.length)return g;g=q;return d};d.dispatch=r.dispatch(d);d.on("load",function(q){if(q.tile.proxyRefs){for(var s in q.tile.proxyRefs){var m= -q.tile.proxyRefs[s];--m.proxyCount<=0&&c.unload(s)&&m.element.parentNode.removeChild(m.element)}delete q.tile.proxyRefs}});return d};r.image=function(){var h=r.layer(function(e){var d=e.element=r.svg("image"),c=h.map().tileSize();d.setAttribute("preserveAspectRatio","none");d.setAttribute("width",c.x);d.setAttribute("height",c.y);d.setAttribute("opacity",0);if(typeof a=="function")e.request=r.queue.image(d,a(e),function(){delete e.request;e.ready=true;d.removeAttribute("opacity");h.dispatch({type:"load", -tile:e})});else{e.ready=true;d.setAttributeNS(r.ns.xlink,"href",a);h.dispatch({type:"load",tile:e})}},function(e){e.request&&e.request.abort(true)}),a="about:blank";h.url=function(e){if(!arguments.length)return a;a=typeof e=="string"&&/{.}/.test(e)?r.url(e):e;return h};return h};r.geoJson=function(h){function a(f,q){var s=q({lat:f[1],lon:f[0]}),m=r.svg("circle");m.setAttribute("r",4.5);m.setAttribute("cx",s.x);m.setAttribute("cy",s.y);return m}function e(f,q,s,m){m.push("M");for(var w=0;w0.5)j*=0.4}g||(g=o.pointLocation(k));o.off("move",h);if(c)o.zoomBy(j,k,g);else if(j){var f=Date.now();if(f-d>200){o.zoomBy(j>0?+1:-1,k,g);d=f}}o.on("move",h);t.preventDefault();return false}var e={},d=0,c=true,g,i=/WebKit\/533/.test(navigator.userAgent),n=0.3,o;e.smooth=function(t){if(!arguments.length)return c;c=t;return e};e.map= -function(t){if(!arguments.length)return o;(o=t).on("move",h);var j=o.container();j.addEventListener("mousemove",h,false);j.addEventListener("mousewheel",a,false);j.addEventListener("DOMMouseScroll",a,false);return e};return e};r.arrow=function(){function h(k){if(!(k.ctrlKey||k.altKey||k.metaKey)){var f=Date.now(),q=0,s=0,m=0;switch(k.keyCode){case 37:if(!c.left){g=f;c.left=1;c.right||(q=t)}break;case 39:if(!c.right){g=f;c.right=1;c.left||(q=-t)}break;case 38:if(!c.up){g=f;c.up=1;c.down||(s=t)}break; -case 40:if(!c.down){g=f;c.down=1;c.up||(s=-t)}break;case 109:case 189:if(!c.plus){g=f;c.plus=1;c.minus||(m=-1)}break;case 61:case 187:if(!c.minus){g=f;c.minus=1;c.plus||(m=1)}break;default:return}if(m){f=j.zoom();j.zoom(m<0?Math.ceil(f)-1:Math.floor(f)+1)}else if(q||s)j.panBy({x:q,y:s});if(!i&&c.left|c.right|c.up|c.down)i=setInterval(e,o);k.preventDefault()}}function a(k){g=Date.now();switch(k.keyCode){case 37:c.left=0;break;case 39:c.right=0;break;case 38:c.up=0;break;case 40:c.down=0;break;case 109:case 189:c.plus= -0;break;case 61:case 187:c.minus=0;break;default:return}if(i&&!(c.left|c.right|c.up|c.down))i=clearInterval(i);k.preventDefault()}function e(){if(j)if(!(Date.now()B+I&&E.panBy(D)},G));D&&E.panBy(D);B=Date.now();n(x)}function a(){q.setAttribute("class","compass");if(y){clearInterval(y); -y=0}}function e(x){return function(){x?this.setAttribute("class","active"):this.removeAttribute("class");D=x}}function d(x){return function(v){q.setAttribute("class","compass active");var z=E.zoom();E.zoom(x<0?Math.ceil(z)-1:Math.floor(z)+1);n(v)}}function c(x){return function(v){E.zoom(x);n(v)}}function g(){this.setAttribute("class","active")}function i(){this.removeAttribute("class")}function n(x){x.stopPropagation();x.preventDefault()}function o(x){var v=Math.SQRT1_2*m,z=m*0.7,A=m*0.2,F=r.svg("g"), -H=F.appendChild(r.svg("path")),N=F.appendChild(r.svg("path"));H.setAttribute("class","direction");H.setAttribute("pointer-events","all");H.setAttribute("d","M0,0L"+v+","+v+"A"+m+","+m+" 0 0,1 "+-v+","+v+"Z");N.setAttribute("class","chevron");N.setAttribute("d","M"+A+","+(z-A)+"L0,"+z+" "+-A+","+(z-A));N.setAttribute("pointer-events","none");F.addEventListener("mousedown",h,false);F.addEventListener("mouseover",e(x),false);F.addEventListener("mouseout",e(null),false);F.addEventListener("dblclick", -n,false);return F}function t(x){var v=m*0.4,z=v/2,A=r.svg("g"),F=A.appendChild(r.svg("path")),H=A.appendChild(r.svg("path")),N=A.appendChild(r.svg("path")),M=A.appendChild(r.svg("path"));F.setAttribute("class","back");F.setAttribute("d","M"+-v+",0V"+-v+"A"+v+","+v+" 0 1,1 "+v+","+-v+"V0Z");H.setAttribute("class","direction");H.setAttribute("d",F.getAttribute("d"));N.setAttribute("class","chevron");N.setAttribute("d","M"+-z+","+-v+"H"+z+(x>0?"M0,"+(-v-z)+"V"+-z:""));M.setAttribute("class","fore"); -M.setAttribute("fill","none");M.setAttribute("d",F.getAttribute("d"));A.addEventListener("mousedown",d(x),false);A.addEventListener("mouseover",g,false);A.addEventListener("mouseout",i,false);A.addEventListener("dblclick",n,false);return A}function j(x){var v=m*0.2,z=m*0.4,A=r.svg("g"),F=A.appendChild(r.svg("rect")),H=A.appendChild(r.svg("path"));F.setAttribute("pointer-events","all");F.setAttribute("fill","none");F.setAttribute("x",-z);F.setAttribute("y",-0.75*z);F.setAttribute("width",2*z);F.setAttribute("height", -1.5*z);H.setAttribute("class","chevron");H.setAttribute("d","M"+-v+",0H"+v);A.addEventListener("mousedown",c(x),false);A.addEventListener("dblclick",n,false);return A}function k(){if(q){var x=m+6,v=x,z=E.size();switch(C){case "top-left":break;case "top-right":x=z.x-x;break;case "bottom-left":v=z.y-v;break;case "bottom-right":x=z.x-x;v=z.y-v;break}q.setAttribute("transform","translate("+x+","+v+")");for(var A in s)A==E.zoom()?s[A].setAttribute("class","active"):s[A].removeAttribute("class")}}var f= -{},q,s={},m=30,w=16,B=0,I=250,G=50,C="top-left",l="small",u="small",y,D,E;f.radius=function(x){if(!arguments.length)return m;m=x;return f};f.speed=function(x){if(!arguments.length)return m;w=x;return f};f.position=function(x){if(!arguments.length)return C;C=x;return f};f.pan=function(x){if(!arguments.length)return u;u=x;return f};f.zoom=function(x){if(!arguments.length)return l;l=x;return f};f.map=function(x){if(!arguments.length)return E;E=x;E.on("move",k);E.on("resize",k);q=E.container().appendChild(r.svg("g")); -q.setAttribute("class","compass");if(u!="none"){var v=q.appendChild(r.svg("g"));v.setAttribute("class","pan");var z=v.appendChild(r.svg("circle"));z.setAttribute("class","back");z.setAttribute("r",m);v.appendChild(o({x:0,y:-w})).setAttribute("transform","rotate(0)");v.appendChild(o({x:w,y:0})).setAttribute("transform","rotate(90)");v.appendChild(o({x:0,y:w})).setAttribute("transform","rotate(180)");v.appendChild(o({x:-w,y:0})).setAttribute("transform","rotate(270)");v=v.appendChild(r.svg("circle")); -v.setAttribute("fill","none");v.setAttribute("class","fore");v.setAttribute("r",m);window.addEventListener("mouseup",a,false)}if(l!="none"){v=q.appendChild(r.svg("g"));v.setAttribute("class","zoom");z=-0.5;if(l=="big"){s={};var A=E.zoomRange()[0];for(z=0;A<=E.zoomRange()[1];A++,z++)(s[A]=v.appendChild(j(A))).setAttribute("transform","translate(0,"+-(z+0.75)*m*0.4+")")}A=u=="none"?0.4:2;v.setAttribute("transform","translate(0,"+m*(/^top-/.test(C)?A+(z+0.5)*0.4:-A)+")");v.appendChild(t(+1)).setAttribute("transform", -"translate(0,"+-(z+0.5)*m*0.4+")");v.appendChild(t(-1)).setAttribute("transform","scale(-1)")}k();return f};return f};r.grid=function(){function h(){var c=d.firstChild,g=e.size(),i=e.pointLocation(R);e.pointLocation(g);var n=Math.pow(2,4-Math.round(e.zoom()));i.lat=Math.floor(i.lat/n)*n;i.lon=Math.ceil(i.lon/n)*n;for(var o;(o=e.locationPoint(i).x)<=g.x;i.lon+=n){c||(c=d.appendChild(r.svg("line")));c.setAttribute("x1",o);c.setAttribute("x2",o);c.setAttribute("y1",0);c.setAttribute("y2",g.y);c=c.nextSibling}for(;(o= -e.locationPoint(i).y)<=g.y;i.lat-=n){c||(c=d.appendChild(r.svg("line")));c.setAttribute("y1",o);c.setAttribute("y2",o);c.setAttribute("x1",0);c.setAttribute("x2",g.x);c=c.nextSibling}for(;c;){g=c.nextSibling;d.removeChild(c);c=g}}var a={},e,d;a.map=function(c){if(!arguments.length)return e;e=c;e.on("move",h);e.on("resize",h);if(!d){d=r.svg("g");d.setAttribute("class","grid")}e.container().appendChild(d);h();return a};return a}})(org.polymaps); +(function(r){function J(){for(var g=0;ga.row){var e=g;g=a;a=e}return{x0:g.column,y0:g.row,x1:a.column,y1:a.row,dx:a.column-g.column,dy:a.row-g.row}}function Z(g,a,e,d,c){e=Math.max(e,Math.floor(a.y0));d=Math.min(d,Math.ceil(a.y1));if(g.x00,o=a.dx<0;for(e=e;ea.dy){e=i;i=a;a=e}if(i.dy>g.dy){e=i;i=g;g=e}if(a.dy>g.dy){e=a;a=g;g=e}i.dy&&Z(g,i,d,c,f);a.dy&&Z(g,a,d,c,f)}r.version="2.0.2+1";var R={x:0,y:0};r.id=function(){var g=0;return function(){return++g}}();r.svg=function(g){return document.createElementNS(r.ns.svg,g)};r.ns={svg:"http://www.w3.org/2000/svg", +xlink:"http://www.w3.org/1999/xlink"};r.transform=function(g,a,e,d,c,f){var i={},l,o,u;if(!arguments.length){g=1;a=c=e=0;d=1;f=0}i.zoomFraction=function(n){if(!arguments.length)return o;o=n;l=Math.floor(o+Math.log(Math.sqrt(g*g+a*a+e*e+d*d))/Math.log(2));u=Math.pow(2,-l);return i};i.apply=function(n){var m=Math.pow(2,-n.zoom),h=Math.pow(2,n.zoom-l);return{column:(g*n.column*m+e*n.row*m+c)*h,row:(a*n.column*m+d*n.row*m+f)*h,zoom:n.zoom-l}};i.unapply=function(n){var m=Math.pow(2,-n.zoom),h=Math.pow(2, +n.zoom+l);return{column:(n.column*m*d-n.row*m*e-c*d+f*e)/(g*d-a*e)*h,row:(n.column*m*a-n.row*m*g-c*a+f*g)/(e*a-d*g)*h,zoom:n.zoom+l}};i.toString=function(){return"matrix("+[g*u,a*u,e*u,d*u].join(" ")+" 0 0)"};return i.zoomFraction(0)};r.cache=function(g,a){function e(m){n--;a&&a(m);delete i[m.key];if(m.next)m.next.prev=m.prev;else if(o=m.prev)o.next=null;if(m.prev)m.prev.next=m.next;else if(l=m.next)l.prev=null}function d(){for(var m=o;n>u;m=m.prev){if(!m)break;m.lock||e(m)}}var c={},f={},i={},l= +null,o=null,u=64,n=0;c.peek=function(m){return i[[m.zoom,m.column,m.row].join("/")]};c.load=function(m,h){var q=[m.zoom,m.column,m.row].join("/"),s=i[q];if(s){if(s.prev){if(s.prev.next=s.next)s.next.prev=s.prev;else o=s.prev;s.prev=null;s.next=l;l=l.prev=s}s.lock=1;return f[q]=s}s={key:q,column:m.column,row:m.row,zoom:m.zoom,next:l,prev:null,lock:1};g.call(null,s,h);f[q]=i[q]=s;if(l)l.prev=s;else o=s;l=s;n++;d();return s};c.unload=function(m){if(!(m in f))return false;var h=f[m];h.lock=0;delete f[m]; +h.request&&h.request.abort(false)?e(h):d();return h};c.locks=function(){return f};c.size=function(m){if(!arguments.length)return u;u=m;d();return c};return c};r.url=function(g){function a(d){var c=1<=f||!d.length)){c++;d.pop()()}}function a(i){for(var l=0;l=0)return j;return window};a.mouse=function(j){var t=(e.ownerSVGElement||e).createSVGPoint();if(V<0&&(window.scrollX||window.scrollY)){var w=document.body.appendChild(r.svg("svg")); +w.style.position="absolute";w.style.top=w.style.left="0px";var C=w.getScreenCTM();V=!(C.f||C.e);document.body.removeChild(w)}if(V){t.x=j.pageX;t.y=j.pageY}else{t.x=j.clientX;t.y=j.clientY}return t.matrixTransform(e.getScreenCTM().inverse())};a.size=function(j){if(!arguments.length)return c;d=j;return a.resize()};a.resize=function(){if(d){c=d;J.remove(a)}else{var j=e.ownerSVGElement||e;if(j.offsetWidth==null){D.setAttribute("width","100%");D.setAttribute("height","100%");j=D}b=j.getBoundingClientRect(); +c={x:b.width,y:b.height};J.add(a)}D.setAttribute("width",c.x);D.setAttribute("height",c.y);f={x:c.x/2,y:c.y/2};g();a.dispatch({type:"resize"});return a};a.tileSize=function(j){if(!arguments.length)return i;i=j;a.dispatch({type:"move"});return a};a.center=function(j){if(!arguments.length)return l;l=j;g();a.dispatch({type:"move"});return a};a.panBy=function(j){var t=45/Math.pow(2,o+u-3),w=j.x*t;j=j.y*t;return a.center({lon:l.lon+(x*j-k*w)/i.x,lat:P(Q(l.lat)+(x*w+k*j)/i.y)})};a.centerRange=function(j){if(!arguments.length)return G; +if(G=j){B=G[0].lat>-90?Q(G[0].lat):-Infinity;H=G[0].lat<90?Q(G[1].lat):Infinity}else{B=-Infinity;H=Infinity}g();a.dispatch({type:"move"});return a};a.zoom=function(j){if(!arguments.length)return o+u;o=Math.max(m[0],Math.min(m[1],j));u=o-(o=Math.round(o));n=Math.pow(2,u);return a.center(l)};a.zoomBy=function(j,t,w){if(arguments.length<2)return a.zoom(o+u+j);if(arguments.length<3)w=a.pointLocation(t);o=Math.max(m[0],Math.min(m[1],o+u+j));u=o-(o=Math.round(o));n=Math.pow(2,u);var C=a.locationPoint(w); +return a.panBy({x:t.x-C.x,y:t.y-C.y})};a.zoomRange=function(j){if(!arguments.length)return m;m=j;return a.zoom(o+u)};a.angle=function(j){if(!arguments.length)return h;h=j;q=Math.cos(h);s=Math.sin(h);k=Math.cos(-h);x=Math.sin(-h);g();a.dispatch({type:"move"});return a};a.add=function(j){j.map(a);return a};a.remove=function(j){j.map(null);return a};a.dispatch=r.dispatch(a);return a};J.maps=[];J.add=function(g){for(var a=0;a>L,row:F>>L,zoom:I-L}))&&K.ready){y[K.key]=c.load(S);K.proxyCount++;O.proxyRefs[K.key]=K;break}}y[O.key]=O}}var k=d.map(),x=k.zoom(),B=x-(x=Math.round(x)),H=k.size(),G=k.angle(),D=k.tileSize(),j=k.locationCoordinate(k.center());i?n.removeAttribute("visibility"):n.setAttribute("visibility","hidden");for(var t=-4;t<=2;t++)h[t].setAttribute("class","zoom"+(t<0?"":"+")+t+" zoom"+(x+t));n.setAttribute("transform","translate("+H.x/2+","+H.y/2+")"+(G?"rotate("+G/Math.PI*180+")":"")+(B? +"scale("+Math.pow(2,B)+")":"")+(m?m.zoomFraction(B):""));var w=k.pointCoordinate(j,R);t=k.pointCoordinate(j,{x:H.x,y:0});var C=k.pointCoordinate(j,H);k=k.pointCoordinate(j,{x:0,y:H.y});if(!B&&!G&&!m){j.column=(Math.round(D.x*j.column)+(H.x&1)/2)/D.x;j.row=(Math.round(D.y*j.row)+(H.y&1)/2)/D.y}var E=l?l(x)-x:0;if(E){B=Math.pow(2,E);w.column*=B;w.row*=B;t.column*=B;t.row*=B;C.column*=B;C.row*=B;k.column*=B;k.row*=B;w.zoom=t.zoom=C.zoom=k.zoom+=E}if(m){w=m.unapply(w);t=m.unapply(t);C=m.unapply(C);k= +m.unapply(k);j=m.unapply(j)}x=c.locks();var y={};for(var v in x)x[v].proxyCount=0;if(i&&E>-5&&E<3){B=1<>t<>t<=1;s--)(h[s]=n.appendChild(r.svg("g"))).setAttribute("transform","scale("+Math.pow(2,-s)+")");h[0]=n.appendChild(r.svg("g"));d.init&&d.init(n);u.on("move",e).on("resize",e);e()}return d};d.container=function(){return n};d.id=function(q){if(!arguments.length)return o;o=q;return d};d.visible=function(q){if(!arguments.length)return i;i=q;u&&e();return d};d.transform=function(q){if(!arguments.length)return m; +m=q;u&&e();return d};d.zoom=function(q){if(!arguments.length)return l;l=typeof q=="function"||q==null?q:function(){return q};return d};d.tile=function(q){if(!arguments.length)return f;f=q;return d};d.dispatch=r.dispatch(d);d.on("load",function(q){if(q.tile.proxyRefs){for(var s in q.tile.proxyRefs){var k=q.tile.proxyRefs[s];--k.proxyCount<=0&&c.unload(s)&&k.element.parentNode.removeChild(k.element)}delete q.tile.proxyRefs}});return d};r.image=function(){var g=r.layer(function(e){var d=e.element=r.svg("image"), +c=g.map().tileSize();d.setAttribute("preserveAspectRatio","none");d.setAttribute("width",c.x);d.setAttribute("height",c.y);d.setAttribute("opacity",0);if(typeof a=="function")e.request=r.queue.image(d,a(e),function(){delete e.request;e.ready=true;d.removeAttribute("opacity");g.dispatch({type:"load",tile:e})});else{e.ready=true;d.setAttributeNS(r.ns.xlink,"href",a);g.dispatch({type:"load",tile:e})}},function(e){e.request&&e.request.abort(true)}),a="about:blank";g.url=function(e){if(!arguments.length)return a; +a=typeof e=="string"&&/{.}/.test(e)?r.url(e):e;return g};return g};r.geoJson=function(g){function a(h,q){var s=q({lat:h[1],lon:h[0]}),k=r.svg("circle");k.setAttribute("r",4.5);k.setAttribute("cx",s.x);k.setAttribute("cy",s.y);return k}function e(h,q,s,k){k.push("M");for(var x=0;x=4800)Y=1;if(Y==1)o*=0.1;f||(f=i.pointLocation(u)); +i.off("move",g);if(c)i.zoomBy(o,u,f);else if(o){var n=Date.now();if(n-d>200){i.zoomBy(o>0?+1:-1,u,f);d=n}}i.on("move",g);l.preventDefault();return false}var e={},d=0,c=true,f,i;e.smooth=function(l){if(!arguments.length)return c;c=l;return e};e.map=function(l){if(!arguments.length)return i;(i=l).on("move",g);var o=i.container();o.addEventListener("mousemove",g,false);o.addEventListener("mousewheel",a,false);o.addEventListener("DOMMouseScroll",a,false);return e};return e};var Y=/WebKit\/533/.test(navigator.userAgent)? +-1:0;r.arrow=function(){function g(m){if(!(m.ctrlKey||m.altKey||m.metaKey)){var h=Date.now(),q=0,s=0,k=0;switch(m.keyCode){case 37:if(!c.left){f=h;c.left=1;c.right||(q=u)}break;case 39:if(!c.right){f=h;c.right=1;c.left||(q=-u)}break;case 38:if(!c.up){f=h;c.up=1;c.down||(s=u)}break;case 40:if(!c.down){f=h;c.down=1;c.up||(s=-u)}break;case 109:case 189:if(!c.plus){f=h;c.plus=1;c.minus||(k=-1)}break;case 61:case 187:if(!c.minus){f=h;c.minus=1;c.plus||(k=1)}break;default:return}if(k){h=n.zoom();n.zoom(k< +0?Math.ceil(h)-1:Math.floor(h)+1)}else if(q||s)n.panBy({x:q,y:s});if(!i&&c.left|c.right|c.up|c.down)i=setInterval(e,o);m.preventDefault()}}function a(m){f=Date.now();switch(m.keyCode){case 37:c.left=0;break;case 39:c.right=0;break;case 38:c.up=0;break;case 40:c.down=0;break;case 109:case 189:c.plus=0;break;case 61:case 187:c.minus=0;break;default:return}if(i&&!(c.left|c.right|c.up|c.down))i=clearInterval(i);m.preventDefault()}function e(){if(n)if(!(Date.now()B+H&&E.panBy(C)},G));C&&E.panBy(C);B=Date.now();l(y)}function a(){q.setAttribute("class","compass");if(w){clearInterval(w);w=0}}function e(y){return function(){y?this.setAttribute("class","active"):this.removeAttribute("class");C=y}}function d(y){return function(v){q.setAttribute("class", +"compass active");var z=E.zoom();E.zoom(y<0?Math.ceil(z)-1:Math.floor(z)+1);l(v)}}function c(y){return function(v){E.zoom(y);l(v)}}function f(){this.setAttribute("class","active")}function i(){this.removeAttribute("class")}function l(y){y.stopPropagation();y.preventDefault()}function o(y){var v=Math.SQRT1_2*k,z=k*0.7,A=k*0.2,F=r.svg("g"),I=F.appendChild(r.svg("path")),N=F.appendChild(r.svg("path"));I.setAttribute("class","direction");I.setAttribute("pointer-events","all");I.setAttribute("d","M0,0L"+ +v+","+v+"A"+k+","+k+" 0 0,1 "+-v+","+v+"Z");N.setAttribute("class","chevron");N.setAttribute("d","M"+A+","+(z-A)+"L0,"+z+" "+-A+","+(z-A));N.setAttribute("pointer-events","none");F.addEventListener("mousedown",g,false);F.addEventListener("mouseover",e(y),false);F.addEventListener("mouseout",e(null),false);F.addEventListener("dblclick",l,false);return F}function u(y){var v=k*0.4,z=v/2,A=r.svg("g"),F=A.appendChild(r.svg("path")),I=A.appendChild(r.svg("path")),N=A.appendChild(r.svg("path")),M=A.appendChild(r.svg("path")); +F.setAttribute("class","back");F.setAttribute("d","M"+-v+",0V"+-v+"A"+v+","+v+" 0 1,1 "+v+","+-v+"V0Z");I.setAttribute("class","direction");I.setAttribute("d",F.getAttribute("d"));N.setAttribute("class","chevron");N.setAttribute("d","M"+-z+","+-v+"H"+z+(y>0?"M0,"+(-v-z)+"V"+-z:""));M.setAttribute("class","fore");M.setAttribute("fill","none");M.setAttribute("d",F.getAttribute("d"));A.addEventListener("mousedown",d(y),false);A.addEventListener("mouseover",f,false);A.addEventListener("mouseout",i,false); +A.addEventListener("dblclick",l,false);return A}function n(y){var v=k*0.2,z=k*0.4,A=r.svg("g"),F=A.appendChild(r.svg("rect")),I=A.appendChild(r.svg("path"));F.setAttribute("pointer-events","all");F.setAttribute("fill","none");F.setAttribute("x",-z);F.setAttribute("y",-0.75*z);F.setAttribute("width",2*z);F.setAttribute("height",1.5*z);I.setAttribute("class","chevron");I.setAttribute("d","M"+-v+",0H"+v);A.addEventListener("mousedown",c(y),false);A.addEventListener("dblclick",l,false);return A}function m(){if(q){var y= +k+6,v=y,z=E.size();switch(D){case "top-left":break;case "top-right":y=z.x-y;break;case "bottom-left":v=z.y-v;break;case "bottom-right":y=z.x-y;v=z.y-v;break}q.setAttribute("transform","translate("+y+","+v+")");for(var A in s)A==E.zoom()?s[A].setAttribute("class","active"):s[A].removeAttribute("class")}}var h={},q,s={},k=30,x=16,B=0,H=250,G=50,D="top-left",j="small",t="small",w,C,E;h.radius=function(y){if(!arguments.length)return k;k=y;return h};h.speed=function(y){if(!arguments.length)return k;x= +y;return h};h.position=function(y){if(!arguments.length)return D;D=y;return h};h.pan=function(y){if(!arguments.length)return t;t=y;return h};h.zoom=function(y){if(!arguments.length)return j;j=y;return h};h.map=function(y){if(!arguments.length)return E;E=y;E.on("move",m);E.on("resize",m);q=E.container().appendChild(r.svg("g"));q.setAttribute("class","compass");if(t!="none"){var v=q.appendChild(r.svg("g"));v.setAttribute("class","pan");var z=v.appendChild(r.svg("circle"));z.setAttribute("class","back"); +z.setAttribute("r",k);v.appendChild(o({x:0,y:-x})).setAttribute("transform","rotate(0)");v.appendChild(o({x:x,y:0})).setAttribute("transform","rotate(90)");v.appendChild(o({x:0,y:x})).setAttribute("transform","rotate(180)");v.appendChild(o({x:-x,y:0})).setAttribute("transform","rotate(270)");v=v.appendChild(r.svg("circle"));v.setAttribute("fill","none");v.setAttribute("class","fore");v.setAttribute("r",k);window.addEventListener("mouseup",a,false)}if(j!="none"){v=q.appendChild(r.svg("g"));v.setAttribute("class", +"zoom");z=-0.5;if(j=="big"){s={};var A=E.zoomRange()[0];for(z=0;A<=E.zoomRange()[1];A++,z++)(s[A]=v.appendChild(n(A))).setAttribute("transform","translate(0,"+-(z+0.75)*k*0.4+")")}A=t=="none"?0.4:2;v.setAttribute("transform","translate(0,"+k*(/^top-/.test(D)?A+(z+0.5)*0.4:-A)+")");v.appendChild(u(+1)).setAttribute("transform","translate(0,"+-(z+0.5)*k*0.4+")");v.appendChild(u(-1)).setAttribute("transform","scale(-1)")}m();return h};return h};r.grid=function(){function g(){var c=d.firstChild,f=e.size(), +i=e.pointLocation(R);e.pointLocation(f);var l=Math.pow(2,4-Math.round(e.zoom()));i.lat=Math.floor(i.lat/l)*l;i.lon=Math.ceil(i.lon/l)*l;for(var o;(o=e.locationPoint(i).x)<=f.x;i.lon+=l){c||(c=d.appendChild(r.svg("line")));c.setAttribute("x1",o);c.setAttribute("x2",o);c.setAttribute("y1",0);c.setAttribute("y2",f.y);c=c.nextSibling}for(;(o=e.locationPoint(i).y)<=f.y;i.lat-=l){c||(c=d.appendChild(r.svg("line")));c.setAttribute("y1",o);c.setAttribute("y2",o);c.setAttribute("x1",0);c.setAttribute("x2", +f.x);c=c.nextSibling}for(;c;){f=c.nextSibling;d.removeChild(c);c=f}}var a={},e,d;a.map=function(c){if(!arguments.length)return e;e=c;e.on("move",g);e.on("resize",g);if(!d){d=r.svg("g");d.setAttribute("class","grid")}e.container().appendChild(d);g();return a};return a}})(org.polymaps); diff --git a/src/Layer.js b/src/Layer.js index 475c6e2..4b2e262 100644 --- a/src/Layer.js +++ b/src/Layer.js @@ -31,7 +31,7 @@ po.layer = function(load, unload) { // set the layer transform container.setAttribute("transform", - "translate(" + (mapSize.x >> 1) + "," + (mapSize.y >> 1) + ")" + "translate(" + (mapSize.x / 2) + "," + (mapSize.y / 2) + ")" + (mapAngle ? "rotate(" + mapAngle / Math.PI * 180 + ")" : "") + (mapZoomFraction ? "scale(" + Math.pow(2, mapZoomFraction) + ")" : "") + (transform ? transform.zoomFraction(mapZoomFraction) : "")); @@ -43,9 +43,9 @@ po.layer = function(load, unload) { c3 = map.pointCoordinate(tileCenter, {x: 0, y: mapSize.y}); // round to pixel boundary to avoid anti-aliasing artifacts - if (!transform && !mapAngle && !mapZoomFraction) { - tileCenter.column = Math.round(tileSize.x * tileCenter.column) / tileSize.x; - tileCenter.row = Math.round(tileSize.y * tileCenter.row) / tileSize.y; + if (!mapZoomFraction && !mapAngle && !transform) { + tileCenter.column = (Math.round(tileSize.x * tileCenter.column) + (mapSize.x & 1) / 2) / tileSize.x; + tileCenter.row = (Math.round(tileSize.y * tileCenter.row) + (mapSize.y & 1) / 2) / tileSize.y; } // layer-specific zoom transform diff --git a/src/Map.js b/src/Map.js index 90015b8..78717fa 100644 --- a/src/Map.js +++ b/src/Map.js @@ -117,8 +117,21 @@ po.map = function() { map.mouse = function(e) { var point = (container.ownerSVGElement || container).createSVGPoint(); - point.x = e.clientX; - point.y = e.clientY; + if ((bug44083 < 0) && (window.scrollX || window.scrollY)) { + var svg = document.body.appendChild(po.svg("svg")); + svg.style.position = "absolute"; + svg.style.top = svg.style.left = "0px"; + var ctm = svg.getScreenCTM(); + bug44083 = !(ctm.f || ctm.e); + document.body.removeChild(svg); + } + if (bug44083) { + point.x = e.pageX; + point.y = e.pageY; + } else { + point.x = e.clientX; + point.y = e.clientY; + } return point.matrixTransform(container.getScreenCTM().inverse()); }; @@ -306,3 +319,6 @@ po.map.coordinateLocation = function(c) { lat: y2lat(180 - k * c.row) }; }; + +// https://bugs.webkit.org/show_bug.cgi?id=44083 +var bug44083 = /WebKit/.test(navigator.userAgent) ? -1 : 0; diff --git a/src/Wheel.js b/src/Wheel.js index 2d54251..df29d86 100644 --- a/src/Wheel.js +++ b/src/Wheel.js @@ -3,8 +3,6 @@ po.wheel = function() { timePrev = 0, smooth = true, location, - speedBug = /WebKit\/533/.test(navigator.userAgent), - speedAvg = .3, map; function move(e) { @@ -14,10 +12,8 @@ po.wheel = function() { function mousewheel(e) { var delta = Math.max(-1, Math.min(1, (e.wheelDelta / 120 || -e.detail) * .1)), point = map.mouse(e); - if (speedBug) { - speedAvg = speedAvg * .95 + Math.abs(delta) * .05; - if (speedAvg > .5) delta *= .4; - } + if ((bug40441 < 0) && (Math.abs(e.wheelDelta) >= 4800)) bug40441 = 1; + if (bug40441 == 1) delta *= .1; if (!location) location = map.pointLocation(point); map.off("move", move); if (smooth) { @@ -54,3 +50,6 @@ po.wheel = function() { return wheel; }; + +// https://bugs.webkit.org/show_bug.cgi?id=40441 +var bug40441 = /WebKit\/533/.test(navigator.userAgent) ? -1 : 0; diff --git a/src/start.js b/src/start.js index 9ac7098..9c92cae 100644 --- a/src/start.js +++ b/src/start.js @@ -2,6 +2,6 @@ if (!org) var org = {}; if (!org.polymaps) org.polymaps = {}; (function(po){ - po.version = "2.0.2"; // semver.org + po.version = "2.0.2+1"; // This fork not semver! var zero = {x: 0, y: 0};