Hello,
I'm currently working on a mapping/logging application using Route-Me
and I'm having an issue with panning and zooming when displaying one
map overlaid onto another.
Problem:
I have a semi-transparent RMMapView that I have layered above another
RMMapView. Both need to move and zoom in sync with each other.
However, certain types of panning and zooming cause the two layers to
become out of sync.
Current Solution:
I have a custom subclass of RMMapView for the semi-transparent upper
layer. The top layer has a baseLayer property which holds the lower
unmodified RMMapView. This subclass simply overrides the movement and
zooming methods and for each one calls the super implementation and
also the base layer's implementation.
For example:
> -(void)moveBy:(CGSize)delta{
> [super moveBy:delta];
> [baseLayer moveBy:delta];
> }
>
> -(void)moveToProjectedPoint:(RMProjectedPoint)aPoint{
> [super moveToProjectedPoint:aPoint];
> [baseLayer moveToProjectedPoint:aPoint];
> }
This works fine when moving programmatically, panning by dragging, or
when zooming to fixed zoom levels (either programmatically or by
double-tapping). However this doesn't work when performing a pinch to
zoom motion. When this occurs, the two layers zoom at different rates.
Unable to work out what was causing this disparity, I instead overrode
the methods to handle touch gestures and passed the touches through to
the base layer when they involve two fingers (supposedly making them a
pinch or stretch) instead of overriding zoomByFactor:near: and
zoomByFactor:near:animated (the other movement and zooming methods
remained unchanged).
For example:
> - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
>
> [super touchesBegan:touches withEvent:event];
>
> // Only pass down pinch & stretch gestures (for zooming)
> if(lastGesture.numTouches > 1){
> [baseLayer touchesBegan:touches withEvent:event];
> }
> }
I do the same for touchesMoved:withEvent:, touchesEnded:touches
withEvent: and touchesCancelled:touches withEvent:
This appeared to solve the problem (maps now stay in sync when
pinching to zoom). However I recently realised that this meant that
two-fingered dragging (but not pinching or stretching) now causes the
previous issue to reoccur, as my method for determining whether a
gesture is a pinch (lastGesture.numTouches > 1) is too naive.
To see an example of this (which might help explain what I mean):
http://f.cl.ly/items/1p3E2B2e0g1x3U1l3b00/BadScrollAnimation.gif
The OpenStreetMap layer is the baseLayer. The stars and other icons
are from the top layer (OpenSeaMap). Watch, for instance, how the star
below Goat Island moves from the bottom to the top of the island
during the drag.
The possible solutions I can think of include:
* Modifying the touches{Began, Moved, Ended, Cancelled} methods to
correctly determine when a gesture is a pinch, which I'm not sure how
to do. This feels a little kludgey, but should solve the issue.
* Making the two maps zoom at the same rate during the pinch to zoom
gestures (this is the preferred solution, as I can use one style for
all interaction types). Unfortunately, I've been unable to work out
what determines the map's zooming speed. I assumed it was a function
of minimum zoom, maximum zoom and current zoom, but making these
values the same for both maps doesn't seem to have an effect.
I'd be grateful for any advice or suggestions on how to resolve this
issue.
Thanks,
-Mark