Raphael Overlay

1,423 views
Skip to first unread message

CTAPbIu_MABP

unread,
Nov 30, 2010, 4:07:40 AM11/30/10
to Google Maps JavaScript API v3
I'd like to share my script with community. May be you find it usefull
or help me to improve it :) This is adaptor for RaphaelJS and
gRaphaelJS (plugin for charts). With it helps, you can simply draw
different shapes over your map as well as complex polygons. But it
looks like PATH doesnt work in Opera.

Here is a project page
http://mabp.kiev.ua/2010/09/10/raphael-overlay/
http://mabp.kiev.ua/2010/10/29/graphael-overlay/

Sorry but comments only in russian. If the community would be
interested, I'll translate comments.
The download link in the bottom of the page.

Chris Broadfoot

unread,
Nov 30, 2010, 7:56:09 AM11/30/10
to google-map...@googlegroups.com
Thanks for sharing!

It doesn't look like the Overlay resizes properly when changing between zoom levels, though. Known issue?

Chris


--
You received this message because you are subscribed to the Google Groups "Google Maps JavaScript API v3" group.
To post to this group, send email to google-map...@googlegroups.com.
To unsubscribe from this group, send email to google-maps-js-a...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-maps-js-api-v3?hl=en.


CTAPbIu_MABP

unread,
Nov 30, 2010, 8:29:23 AM11/30/10
to Google Maps JavaScript API v3
overlay resize formula is [width * (1 << map.getZoom())]
but on 16+ zoom level, shapes disappears becouse 2^16 = 65536
and i think svg node cant be so wide

if you noticed another bug please tell me

Anton

unread,
Dec 3, 2010, 1:30:02 PM12/3/10
to Google Maps JavaScript API v3
>but on 16+ zoom level, shapes disappears becouse 2^16 = 65536

This can be avoided by limiting canvas width with 60000 (or less). The
code with workaround below, 2 main points in it:
- raphael canvas width is less or equals to 60000 pixels - with >2^16
zoom canvas area would be less than actual world width in pixels, but
the user will hardly be able to achieve canvas border by dragging the
map with mouse, and if he zooms out/zooms in - the canvas borders
would be recalculated.
- take as world center not 0,0, but visible map center
(map.getCenter())

+ 2 convenient methods to convert map coordinates to canvas
coordinates and back.

This works for me with any zoom on the map.


/**
* Draw with raphael library over google map.
*/
function RaphaelOverlay() {
}

RaphaelOverlay.prototype = new google.maps.OverlayView();

/**
* Convert lan/lng map coordinates to the canvas point coordinates.
*/
RaphaelOverlay.prototype.fromLatLngToCanvasPixel = function(latLng) {
var divPixel = this.getProjection().fromLatLngToDivPixel(latLng);

var left = this.canvasCenter.x - this.canvasWidth / 2;
var top = this.canvasCenter.y - this.canvasHeight / 2;

var x = divPixel.x - left;
var y = divPixel.y - top;

var canvasPixel = new google.maps.Point(x, y);

return canvasPixel;
}

/**
* Convert canvas point coordinates to the lan/lng map coordinates.
*/
RaphaelOverlay.prototype.fromCanvasPixelToLatLng =
function(canvasPixel) {

// borders of the map
var left = this.canvasCenter.x - this.canvasWidth / 2;
var top = this.canvasCenter.y - this.canvasHeight / 2;

// point coondinates on the canvas layer
var x = canvasPixel.x + left;
var y = canvasPixel.y + top;

var divPixel = new google.maps.Point(x, y);
var latLng = this.getProjection().fromDivPixelToLatLng(divPixel);

return latLng;
}

RaphaelOverlay.prototype.onAdd = function() {
// painting for the layer
this.div = document.createElement('div');
this.div.style.border = 'none';
this.div.style.position = 'absolute';
this.div.style.overflow = 'visible';

this.getPanes().overlayImage.appendChild(this.div);
this.canvas = Raphael(this.div);
};

RaphaelOverlay.prototype.draw = function() {
this.canvasCenter =
this.getProjection().fromLatLngToDivPixel(this.getMap().getCenter());
this.canvasWidth = Math.min(this.getProjection().getWorldWidth(),
60000);
this.canvasHeight = Math.min(this.getProjection().getWorldWidth(),
60000);

this.div.style.left = this.canvasCenter.x - this.canvasWidth / 2 +
'px';
this.div.style.top = this.canvasCenter.y - this.canvasHeight / 2 +
'px';
this.div.style.width = this.canvasWidth + 'px';
this.div.style.height = this.canvasHeight + 'px';

this.canvas.setSize(this.canvasWidth, this.canvasHeight);

rebuildPath(this, this.canvas);
};

RaphaelOverlay.prototype.onRemove = function() {
this.div.parentNode.removeChild(this.div);
};

Anton

unread,
Dec 3, 2010, 1:37:11 PM12/3/10
to Google Maps JavaScript API v3
//f@kin sh^t, lost my message 3 times trying to reply the post with
web interface, post as separate thread

http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/b3039231c0e76956/ebfe9a387fd88571?lnk=raot&pli=1
>but on 16+ zoom level, shapes disappears becouse 2^16 = 65536

This can be avoided by limiting canvas width with 60000 pixels (or
less). The code with workaround below, 2 main points in it:
- raphael canvas width is less or equals to 60000 pixels - with >2^16
zoom canvas area would be less than actual world width in pixels, but
the user will hardly be able to achieve canvas border by dragging the
map with mouse, and if he zooms out/zooms in - the canvas borders
would be recalculated and canvas edge would be moved away.

Anton

unread,
Dec 3, 2010, 10:37:38 AM12/3/10
to Google Maps JavaScript API v3
Agrr.. google groups has eaten my message..

>shapes disappears becouse 2^16 = 65536

below is my code to avoid this + 2 convenient methods to convert
canvas coordinates to map lat/lon and back.

Key points:
- limit canvas size by 60000 pixel - this is far enough for the user
being able to drag the map though all that pixels to reach canvas
drawing bound without changing zoom, and if he changes zoom, the
canvas bounds are recalculated
- world center is map's visible center, not 0,0

Anton

unread,
Dec 3, 2010, 9:38:55 AM12/3/10
to Google Maps JavaScript API v3
Thank's a lot, very nice.

>but on 16+ zoom level, shapes disappears becouse 2^16 = 65536

Also met this issue - on firefox2 the problem start at
worldWidth=65536 as you say, on newer firefox and chrome this number
is more than million, but still can be seen on the map with close
zoom.

I have solved this just by limiting the raphael canvas width/height by
60000 pixels (and currently it is taken as map's worldWidth).
Actually, the user will be hardly able to notice this - if he zooms
16+ (so the canvas width will be less than actual world width), he
will have to drag the map through 60000 pixels right/left/top/bottom
in order to reach the paintable canvas edge - this is really long way.
And if he zooms out/zooms in to reach this border, overlay draw()
method would be called, so the canvas location would be recalculated
and the canvas border would be moved to another location.

Below is my code with this workaround and 2 additional helpful methods
to convert lat/lon coordinates values to the raphael canvas
coordinates and back - this works fine with any zoom level.

Also note, that world center is not (0,0), but current visible map
center - without this detail 60000 pixels limitation workaround will
not work right.

CTAPbIu_MABP

unread,
Dec 4, 2010, 5:52:40 AM12/4/10
to Google Maps JavaScript API v3
Hi, Anton.

Thanks a lot for your message (all four ;) )

It's a good idea to limit canvas to 60k*60k pixels.
It's possiable to do this and recalculete new rectangel (60*60) every
time bounds_changed event fires (every time draw metod called)
There will be no problem to draw a rectangel in this maner but there
will be problem with circles (ellipses)
I should cut them to fit 60*60 rectangel. It's little bit difficult
because i should to convert them to PATH and then draw.
Even if i did this it would take too much time to (re)calculate all
figures on map.

As you can see i have a method fillAllMap. it fills all visiable part
of map (viewport) with color when all four corners of viewport belongs
to certain shape. The only thing i really can do is to use rectangel
larger then viewport when calculating their intersection

PS sorry for my bad english

tom

unread,
Aug 19, 2013, 11:43:49 AM8/19/13
to google-map...@googlegroups.com
Hi,

I know this post is a little outdated now but has anyone got a simple example of this working or more info in English?

cheers!

Tom
Reply all
Reply to author
Forward
0 new messages