Unable to catch mouseover/mouseout/click events on PolyCluster polygons

166 views
Skip to first unread message

Niko

unread,
Aug 17, 2010, 10:30:53 AM8/17/10
to Google Maps JavaScript API v3
Hi everybody,

I am currently trying to draw polygons that have an important number
of vertex, that's why I choosed to use the PolyCluster facility that
Berry Rattlif built. I am quite new to js programming and I need help
to be sure not going in the wrong way.
I would like to display very precisely the Marseille's (France) area
with a lot of vertex really near from each other and to be able to
fire events when the mouse is passing in and out polygons or even when
a click is done.
The only way I know is to build a point-in-polygon algorythm and
associate it manually with my polys,and I don't know if there is a
better way to do it.
Using map.polygon object appears to be really slow when polygons are
complex...
Hope someone will advice me.

Thanks for your help.

bratliff

unread,
Aug 18, 2010, 10:05:42 AM8/18/10
to Google Maps JavaScript API v3
It is on my "to do" list but realistically it is a few months away.
The API allows you to click on rendered polys. PolyCluster will allow
you click on a naked map to render the corresponding poly. It
requires a separate structure of intersecting X & Y slices. It will
be much more compact than the full poly definitions. The full poly
definitions can be loaded on demand.

Niko

unread,
Aug 18, 2010, 11:27:15 AM8/18/10
to Google Maps JavaScript API v3
So what should I do in order to get the mouseover behavior according
to you?
What I would like is to make polygons appear and disappear when the
mouse is passing over and out.
Is this a good idea to access the poly array of coordinates, make a
point in polygon algorythm and attach a test to the mousemove map
event (this is the only way I know) without loading any Polygon
object.
What do you call "a separate structure of intersecting X & Y slices"
and how could I get it deal fast with events?
Anyway, thanks for your work and help!

Niko

unread,
Sep 9, 2010, 11:28:02 AM9/9/10
to Google Maps JavaScript API v3
Hello Berry,

I am still trying to get interactions between your clustered polys and
the map's mousemove event...
Did you go further on this subject?
I really need this functionality for my app and I do not know how to
proceed, I am maybe not that far but It's still not there.
It would be great if any help could give me the steps to follow.

Thanks


On 18 août, 17:27, Niko <nicolas.yordam...@gmail.com> wrote:
> So what should I do in order to get the mouseover behavior according
> to you?
> What I would like is to make polygons appear and disappear when the
> mouse is passing over and out.
> Is this a good idea to  access the poly array of coordinates, make a
> point in polygon algorythm and attach a test to the mousemove map
> event (this is the only way I know) without loading any Polygon
> object.
> What do you call "a separate structure of intersecting X & Y slices"
> and how could I get it deal fast withevents?
> Anyway, thanks for your work and help!
>
> On 18 août, 16:05, bratliff <bratl...@umich.edu> wrote:
>
> > On Aug 17, 2:30 pm, Niko <nicolas.yordam...@gmail.com> wrote:
>
> > > Hi everybody,
>
> > > I am currently trying to draw polygons that have an important number
> > > of vertex, that's why I choosed to use thePolyClusterfacility that
> > > Berry Rattlif built. I am quite new to js programming and I need help
> > > to be sure not going in the wrong way.
> > > I would like to display very precisely the Marseille's (France) area
> > > with a lot of vertex really near from each other and to be able to
> > > fireeventswhen the mouse is passing in and out polygons or even when
> > > a click is done.
> > > The only way I know is to build a point-in-polygon algorythm and
> > > associate it manually with my polys,and I don't know if there is a
> > > better way to do it.
> > > Using map.polygon object appears to be really slow when polygons are
> > > complex...
> > > Hope someone will advice me.
>
> > > Thanks for your help.
>
> > It is on my "to do" list but realistically it is a few months away.
> > The API allows you to click on rendered polys.  PolyClusterwill allow

bratliff

unread,
Sep 10, 2010, 9:15:09 AM9/10/10
to Google Maps JavaScript API v3
On Sep 9, 3:28 pm, Niko <nicolas.yordam...@gmail.com> wrote:
> Hello Berry,
>
> I am still trying to get interactions between your clustered polys and
> the map's mousemove event...
> Did you go further on this subject?
> I really need this functionality for my app and I do not know how to
> proceed, I am maybe not that far but It's still not there.
> It would be great if any help could give me the steps to follow.
>
> Thanks

It will require design changes.

Both PolyCluster & the API poly facility use tiles to improve
performance during dragging / panning / zooming. If several polys
have pieces in the same tile, the pieces of the polys are combined
into a single CANVAS / SVG / VML element. If one of the polys changes
color, the entire tile must be rebuilt. A poly may be added to an
existing tile but a poly cannot be destroyed without regenerating
every tile containing its pieces. Fortunately, the remaining poly
paths are already cached which reduces the amount of work over
building a tile from scratch.

CANVAS may offer a solution with "save" / "restore" coupled with a
"globalCompositeOperation" of "COPY". SVG or VML may offer solutions
with the "style.display" or "style.visibility" attributes of the
"path" or "shape" sub-elements. It will require some experimenting
with several browsers. Unfortunately, PolyCluster is just a "hobby"
project.

bratliff

unread,
Sep 10, 2010, 10:00:18 AM9/10/10
to Google Maps JavaScript API v3
I tried implementing my own "mousemove" event handler on the map. It
was a disaster. It did not play nicely with Google's other event
handlers. Every time the DOM hierarchy changed, it was broken. I
have no idea what to do to emulate a "mousemove" on an iPhone or on an
Android device. "touch" equals "click" but "mousemove" has no
equivalent.

Are you interested in "rollover" feedback from a "sidebar" or from the
map canvas itself ? A "sidebar" will not be difficult to implement.
The other will require the use of the API's "mousemove" event
handler. PolyCluster cannot provide a reliable "mousemove" event
handler. You will have to pass lat/lon coordinates to PolyCluster.
PolyCluster will return a list of every visible and/or invisible poly
in which your lat/lon coordinates are contained.

I cannot promise when it might happen. Let me know if it fits your
requirements.

Niko

unread,
Sep 13, 2010, 11:50:02 AM9/13/10
to Google Maps JavaScript API v3
It sounds interesting and user friendly for my app.
The exact behavior I am trying to get is to change the color of the
clustered polys when the mouse is passing on the polygon itself, not
on any "sidebar" entry.
I made an example of what I would like with the google.maps.Polygon
object here: http://evilfenril.free.fr/mapv3/map.php but It's really
slow and can't render a lot of complex polys at the same time, it has
to set and unset polys from the map wich is not as fast as I would
like.
I also tryed to implement a point-in-polygon algorythm with your
clustered polys wich is also really slow (I maybe took the wrong way),
you can see it there :
http://evilfenril.free.fr/mapv3/cluster.php

Thank you for your help

On 10 sep, 16:00, bratliff <bratl...@umich.edu> wrote:
> I tried implementing my own "mousemove" event handler on the map.  It
> was a disaster.  It did not play nicely with Google's other event
> handlers.  Every time the DOM hierarchy changed, it was broken.  I
> have no idea what to do to emulate a "mousemove" on an iPhone or on an
> Android device.  "touch" equals "click" but "mousemove" has no
> equivalent.
>
> Are you interested in "rollover" feedback from a "sidebar" or from the
> map canvas itself ?  A "sidebar" will not be difficult to implement.
> The other will require the use of the API's "mousemove" event
> handler.  PolyClustercannot provide a reliable "mousemove" event
> handler.  You will have to pass lat/lon coordinates toPolyCluster.PolyClusterwill return a list of every visible and/or invisible poly

Niko

unread,
Sep 14, 2010, 4:39:24 AM9/14/10
to Google Maps JavaScript API v3
It seems that your second option fits what I need, the issue I meet is
that I can't get the feedback quickly and it's also slowing down the
map application.
It would be great if you could show me your way to do it.
I am quite stuck at this point, I really appreciate your advices.
Many thanks

On 13 sep, 17:50, Niko <nicolas.yordam...@gmail.com> wrote:
> It sounds interesting and user friendly for my app.
> The exact behavior I am trying to get is to change the color of the
> clustered polys when the mouse is passing on the polygon itself, not
> on any "sidebar" entry.
> I made an example of what I would like with the google.maps.Polygon
> object here:http://evilfenril.free.fr/mapv3/map.phpbut It's really

bratliff

unread,
Sep 14, 2010, 8:44:44 AM9/14/10
to Google Maps JavaScript API v3
On Sep 13, 3:50 pm, Niko <nicolas.yordam...@gmail.com> wrote:
> It sounds interesting and user friendly for my app.
> The exact behavior I am trying to get is to change the color of the
> clustered polys when the mouse is passing on the polygon itself, not
> on any "sidebar" entry.
> I made an example of what I would like with the google.maps.Polygon
> object here:http://evilfenril.free.fr/mapv3/map.phpbut It's really
> slow and can't render a lot of complex polys at the same time, it has
> to set and unset polys from the map wich is not as fast as I would
> like.
> I also tryed to implement a point-in-polygon algorythm with your
> clustered polys wich is also really slow (I maybe took the wrong way),
> you can see it there :http://evilfenril.free.fr/mapv3/cluster.php

I will make some changes to improve the color changing speed but it
may not be fast enough for instantaneous "rollovers".

I believe the API uses "mouseover" / "mouseout" event handlers for
every tile of every poly. It works well for a few polys but does not
scale well if many polys are involved. The number of individual event
handlers can be very large. If an event handler for one poly of one
tile fires, every tile containing a piece of the same poly must be
corrected.

Trying to add an event handler without interfering with Google's event
handlers is futile. Internet Explorer uses a very different event
handler model than the other standards compliant browsers. The way
pixel offsets are determined varies across browsers. Google's DOM
structure is neither documented nor guranteed not to change.

I prefer to use Google's "mousemove" event handler which is consistent
across browsers. PolyCluster will perform a "fast winding" point-in-
poly analysis on a single tile. Each tile contains fewer polys than
the entire set. Each tile contains fewer points than the entire poly.

bratliff

unread,
Sep 14, 2010, 10:04:50 AM9/14/10
to Google Maps JavaScript API v3
On Sep 13, 3:50 pm, Niko <nicolas.yordam...@gmail.com> wrote:
> It sounds interesting and user friendly for my app.
> The exact behavior I am trying to get is to change the color of the
> clustered polys when the mouse is passing on the polygon itself, not
> on any "sidebar" entry.
> I made an example of what I would like with the google.maps.Polygon
> object here:http://evilfenril.free.fr/mapv3/map.phpbut It's really
> slow and can't render a lot of complex polys at the same time, it has
> to set and unset polys from the map wich is not as fast as I would
> like.
> I also tryed to implement a point-in-polygon algorythm with your
> clustered polys wich is also really slow (I maybe took the wrong way),
> you can see it there :http://evilfenril.free.fr/mapv3/cluster.php

I cannot load:

http://evilfenril.free.fr/mapv3/map.php

You can simplify your code if you build your "new
google.maps.LatLng()" objects in a loop from an array of {x:,y:}
objects. The API ought to support such arrays directly. The
requirement of a separate "new google.maps.LatLng()" object for every
point is huge waste of resources.

Niko

unread,
Sep 14, 2010, 10:51:25 AM9/14/10
to Google Maps JavaScript API v3
I will check and modify my code, you seem to be talking about the
map.php file (I can load this page, dont know why you can't, anyway
you saw its code)
Maybe it will increase enough the speed of the app...
Do you think I should give up with polyclustering and focus on using
google.maps.Polygon optimizing my code?
The test you were talkin about using tiles and not the entire set in
order to get the polygon hovered by the mouse seems to be a good
solution, would'nt it be faster?


On 14 sep, 16:04, bratliff <bratl...@umich.edu> wrote:
> On Sep 13, 3:50 pm, Niko <nicolas.yordam...@gmail.com> wrote:
>
> > It sounds interesting and user friendly for my app.
> > The exact behavior I am trying to get is to change the color of the
> > clustered polys when the mouse is passing on the polygon itself, not
> > on any "sidebar" entry.
> > I made an example of what I would like with the google.maps.Polygon
> > object here:http://evilfenril.free.fr/mapv3/map.phpbutIt's really

Ben Appleton

unread,
Sep 14, 2010, 5:58:33 PM9/14/10
to google-map...@googlegroups.com

The API uses 1 mouseover/mouseout listener per tile, not per poly.  We catch events as they bubble up, then dispatch to the correct poly using event.target.

We use SVG or VML where available.  These support fast restyling on rollover, though they are initially slower to render than Canvas.

> --
> 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.
>

bratliff

unread,
Sep 15, 2010, 7:55:51 AM9/15/10
to Google Maps JavaScript API v3
On Sep 14, 9:58 pm, Ben Appleton <apple...@google.com> wrote:
> The API uses 1 mouseover/mouseout listener per tile, not per poly. We catch
> events as they bubble up, then dispatch to the correct poly using
> event.target.

Cool. You must be applying event listeners to the "svg" element for
the tile rather than to the individual "path" elements for every
contained poly.

> We use SVG or VML where available. These support fast restyling on
> rollover, though they are initially slower to render than Canvas.

I believe I will switch from CANVAS to SVG also. The
"globalCompositeOperation" of "COPY" can be used to avoid a complete
rebuild but it changes the "zIndex" order.

Any plans to offer an alternative to a "new google.maps.LatLng" object
for every point ? The old API accepted arrays of {x:,y:} objects
which are constants rather than executable constructors.

Ben Appleton

unread,
Sep 15, 2010, 8:02:34 PM9/15/10
to google-map...@googlegroups.com
This hasn't turned up as a bottleneck in my profiling.  We'd prefer not to complicate the API without clear benefit.  If you find otherwise, can you point me to a demo where these object allocations are more than eg. 10% of processing time?

- Ben

bratliff

unread,
Sep 16, 2010, 12:56:25 AM9/16/10
to Google Maps JavaScript API v3
On Sep 14, 9:58 pm, Ben Appleton <apple...@google.com> wrote:
> The API uses 1 mouseover/mouseout listener per tile, not per poly. We catch
> events as they bubble up, then dispatch to the correct poly using
> event.target.

With just one pair of mouseover / mouseout event listeners for the
entire tile, how are you able to detect the mouse exiting one poly &
entering another poly in the same tile ?

> We use SVG or VML where available. These support fast restyling on
> rollover, though they are initially slower to render than Canvas.

Which browser(s) do support CANVAS but do not support SVG ?

> This hasn't turned up as a bottleneck in my profiling. We'd prefer not to
> complicate the API without clear benefit. If you find otherwise, can you
> point me to a demo where these object allocations are more than eg. 10% of
> processing time?

I cannot profile it because I cannot avoid using the constructors. I
refer you to Niko's comment in his original post. It consumes extra
memory which limits the number points the API is able to support.
Even experienced users specify the same redundant constructors for
every element of large arrays. The old API was able to offer both
without complications.

Ben Appleton

unread,
Sep 16, 2010, 1:12:49 AM9/16/10
to google-map...@googlegroups.com
On Thu, Sep 16, 2010 at 2:56 PM, bratliff <brat...@umich.edu> wrote:
On Sep 14, 9:58 pm, Ben Appleton <apple...@google.com> wrote:
> The API uses 1 mouseover/mouseout listener per tile, not per poly.  We catch
> events as they bubble up, then dispatch to the correct poly using
> event.target.

With just one pair of mouseover / mouseout event listeners for the
entire tile, how are you able to detect the mouse exiting one poly &
entering another poly in the same tile ?

Individual SVG/VML paths emit mouseover/mouseout events, which bubble up to my listener.  So if the mouse exits one poly and enters another in the same tile, I'll see the following sequence of events:
mouseout {target: poly1}
mouseover {target: poly2}

The "hard" part is when the user moves their mouse inside a polygon from 1 tile to a neighboring tile.  So in fact I only listen to mousemove events and keep track globally of the target element.  When the target element changes, I fire mouseout on the old poly and mouseover on the new poly.

I also listen to mouseout on the map container, so I can fire mouseout on a polygon if the user mouses from the polygon to the outside of the map.

> We use SVG or VML where available.  These support fast restyling on
> rollover, though they are initially slower to render than Canvas.

Which browser(s) do support CANVAS but do not support SVG ?

Android's browser, at least on old devices (http://code.google.com/p/android/issues/detail?id=1376).
 
> This hasn't turned up as a bottleneck in my profiling.  We'd prefer not to
> complicate the API without clear benefit.  If you find otherwise, can you
> point me to a demo where these object allocations are more than eg. 10% of
> processing time?

I cannot profile it because I cannot avoid using the constructors.

A profiler can tell you how long the JS engine spends constructing the LatLngs versus rendering.  Indeed you can time this directly in JS, by measuring the time to construct the set of LatLngs versus the subsequent time to render them.
 
 I
refer you to Niko's comment in his original post.  It consumes extra
memory which limits the number points the API is able to support.
Even experienced users specify the same redundant constructors for
every element of large arrays.  The old API was able to offer both
without complications.

bratliff

unread,
Nov 7, 2010, 4:15:19 PM11/7/10
to Google Maps JavaScript API v3
I have added "click" / "cover" capabilities. Instead of individual
event listeners for every poly, you add a single event listener for
the entire PolyCluster.

For "mousedown" / "mouseup", use:

cluster.setClick(YourClickFunction);

It will be called with two arguments:

function YourClickFunction(polyname,flag)

The first argument is the name of the poly. The second argument will
be "true" for "mousedown" or "false" for "mouseup".

For "mouseover" / "mouseout", use:

cluster.setCover(YourCoverFunction);

It will be called with two arguments:

function YourCoverFunction(polyname,flag)

The first argument is the name of the poly. The second argument will
be "true" for "mouseover" or "false" for "mouseout".

http://www.polylib.us contains some demos.
Reply all
Reply to author
Forward
0 new messages