I am trying to replicate the behavior seen at:
http://forevermore.net/articles/photo-zoom/
It allows panning and zooming of a photo, but it limits the panning to the bounds of the photo.
The example above using google maps v2 code.
It seems I would have to do the following:
google.maps.event.addListener(map, 'dragend', function()
{
//Get bounds and not allow dragging
});
(As seen here: How do I limit panning in Google maps API V3?)
My problem is:
- Images that will be panned/zoomed are dynamic in size, I want a generic solution (if possible)
If it is not possible to have a generic solution, how do I determine the correct LatLon bounds for an image?
Here is what I have so far:
var customTypeOptions = {
getTileUrl: function(coord, zoom) {
return "img/earth_tiles/tile-" + zoom + "-" + coord.x + "-" + coord.y + ".jpg";
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 6,
minZoom: 0,
name: "Custom Map Type"
};
var customMapType = new google.maps.ImageMapType(customTypeOptions);
jQuery(document).ready(function(){
var myLatlng = new google.maps.LatLng(0, 0);
var myOptions = {
center: myLatlng,
zoom: 3,
disableDefaultUI: true,
zoomControl: true
};
var map = new google.maps.Map(document.getElementById("map"), myOptions);
map.mapTypes.set('custom', customMapType);
map.setMapTypeId('custom');
});
It works fine, it just allows a user to scroll outside of the photo.
I got burned by JSFiddle deleting my demo, so I reworked the solution, and am posting the demo below with SO's built-in preview. But JSFiddle is arguably more convenient to edit, so I added the code over there too. Demo in JSFiddle
The original solution assigns the image's coordinates to +/-50 degrees, but I couldn't reproduce this behavior. This new code uses +/-85 deg. latitude and +/-180 longitude with the default Mercator projection.
I haven't tested the new solution thoroughly, so use it with caution. A particularly nasty bug I found was that using
setCenter()
inside the bounds checking led to a stack overflow. It was solved by replacing it topanTo()
. My main observations are:First, the solution is hacky. As the latitude increases, so does the space it takes up on the screen. What I do is re-compute the pixel midpoint between the limits of the map bounds when the map is moved, rather than using a geometrical conversion. To make this hack work, the acceptable bounds are dictated by the map's div's height.
On the other hand, longitude behaves normally. The trick with longitude is that it repeats, so markers and other items showing up at this limit will be duplicated. I think the way around this problem is to transform the longitude coordinates far from this boundary (as in the original solution transforming longitudes to +/- 50 degrees). Unfortunately I'm unable right now to reproduce this coordinate transformation.
ORIGINAL 2012 SOLUTION:
I combined the forevermore coordinate system and the documentation's ImageMapTypes example for the moon's surface
Initially, the demo starts at zoom 0, to give an idea of the whole image. After zooming in, panning will be restricted to a rectangle with an aspect ratio defined by the (W)idth and (H)eight textboxes. For this demo, only this ratio
W/H
, orH/W
is important.I'm assuming your images will be similar to both of the above, fitting in 256x256 tiles, and having a "black border" around the image. Furthermore, that the image stretches all the way to the tiles' edge on the longer dimension. If not (but at least, the image is centered), the viewable area can be modified in the
latbound
andlngbound
variables, which correspond to the coordinate grid(-50,50) x (-50,50)
defined in forevermore.In the demo, when zoomed in and W > H, the aspect ratio is longer horizontally: the whole width of the lunar surface is visible around the center, and the top/bottom horizontal bars will be blocked. That is, the dark craters on the top and bottom of the full image will not be reachable at zooms above 0. Visualizing an actual image with the black borders, some of the "black region" might still show at zoom 1, whose area decreases as the zoom level increases.
When zoomed in and H > W, the reachable area extends vertically. The dark craters directly above and below the center of the whole surface will be reachable, but the left/right areas, not. In this demo, the aspect ratio is changed by
updateEdge
reading the textboxes; clicking on Set callsupdateEdge
.Most of the effort in the code was to prevent the movement outside the desired display area. Both the forevermore method and the "How do I limit Panning" were jumpy or caused errors when I tested, so I came up with a modified version of Range Limiting that takes into account the current zoom level by measuring the screen width and height:
The projection and tile fetching code are not significantly changed from their sources.
To be honest, I don't think using Google Maps is really the right approach. Yes, you can probably hack it into working, but it's not really what the library is meant to do. (Something about using a hammer to fit a round screw into a triangular hole.)
Additionally, you're subjecting yourself to both Google's restrictive terms (your site must be public) and their new pricing, which means over 25,000 pageviews/day will cost you — and you're not even using the maps.
Instead, why not use a library designed for tiled zooming of very large images? PanoJS3 seems to fit the bill.