bindTo - How do I link a marker position to the position of a polyline node?

2,770 views
Skip to first unread message

Joseph Elfelt

unread,
Jul 20, 2010, 4:40:53 PM7/20/10
to Google Maps JavaScript API v3
I've been playing with the code of this example:
http://code.google.com/apis/maps/documentation/javascript/examples/polyline-complex.html

I've made the markers draggable and now I want the polyline to follow
the markers as they are dragged.
If I understand correctly, I ought to be able to use the bindTo
concept to link the 'position' of the marker to the corresponding
position within the 'path' variable of this example.

None of the bindTo statements I have tried have done the trick.
Any suggestion would be most welcome.

I realize that I could listen for the marker being dragged and then
insert new coords into the path. But my impression is that bindTo
does away with the need for that coding.

William

unread,
Jul 20, 2010, 10:44:14 PM7/20/10
to Google Maps JavaScript API v3
On Jul 21, 6:40 am, Joseph Elfelt <josephelf...@gmail.com> wrote:
>
> If I understand correctly, I ought to be able to use the bindTo
> concept to link the 'position' of the marker to the corresponding
> position within the 'path' variable of this example.
>
I'm not sure about this, but the path is a MVCArray, which extends the
MVCObject with methods like getAt(integer) and setAt(integer,elem), so
for binding there'd need to be a new method on MVCArray like
path.bindAt(integer, marker, 'position') ? Or is there a string key
already available for each element of a MVCArray?

...

Joseph Elfelt

unread,
Jul 20, 2010, 11:53:46 PM7/20/10
to Google Maps JavaScript API v3
William,

Thanks for your thoughts. I've studied the reference doc and did not
find any hint of anything like path.bindAt nor did I see any mention
of a string key that would identify an element of a MVCArray.

Perhaps such things exist but are not in the docs yet.

I'll modify the Google example I cited by listening for a marker
'drag' and updating the position of the corresponding element of
path. That should make the 1 or 2 adjoining polyline segments nicely
stay hitched to a marker that is on the move.

Marx Tseng

unread,
Jul 21, 2010, 4:08:05 AM7/21/10
to Google Maps JavaScript API v3
Try this sample, hope can solve your problem
http://marx-tseng.appspot.com/maps/Polygons.html

Pil

unread,
Jul 21, 2010, 5:01:04 AM7/21/10
to Google Maps JavaScript API v3
Have a look at this illustrative post on how to bind properties of
MVCObjects:

http://blog.mridey.com/2010/03/maps-javascript-api-v3-more-about.html

Joseph Elfelt

unread,
Jul 21, 2010, 8:41:59 AM7/21/10
to Google Maps JavaScript API v3
Yes, I did see that Marc Ridey post along with his followup post.
Alas, those posts do not appear to answer the question of how do we
bind to elements of an MVCArray.

The bindTo statement I want to write is:

marker[i].bindTo(‘position’, what_do_I_put_here, ‘position’);

what_do_I_put_here needs to refer to element i of an MVCArray.

I have searched high and low and not found anything on this point.

Joseph Elfelt

unread,
Jul 21, 2010, 8:49:20 AM7/21/10
to Google Maps JavaScript API v3
Marx,

Thanks, I did see something in that map that is useful.
However that code does not contain any bindTo therefor my original
question remains on the floor.

Joseph Elfelt

unread,
Jul 21, 2010, 10:27:35 AM7/21/10
to Google Maps JavaScript API v3
Here is my solution:
http://www.mappingsupport.com/forum_post/drag_marker_and_line.html

Click a few times to draw a line.
Drag a marker and the line follows the marker.

The polyline is an MVCArray.
I wish it was possible to use the bindTo feature to link the positions
of my markers to the positions of the polyline nodes.

Nianwei Liu

unread,
Jul 21, 2010, 10:39:09 AM7/21/10
to Google Maps JavaScript API v3
This one is a bindTo Solution.

http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/poly_bind.html

I was a little surprised that it worked because the 'draw' method on
Polyline is obfuscated and I thought I have to find a way to trigger
the 'get' method on the MVCArray, so some event can trigger the poly
redraw (MVCArray length change would be an example).

However to my surprise the direction of bindTo is somewhat flexible
and it actually worked when I bind the marker to MVCArray, instead of
the other way back. Do sure if it is by design or just happen to
worked on this version.

The idea is using instance method to overwrite prototype method.

Joseph Elfelt

unread,
Jul 21, 2010, 10:46:49 AM7/21/10
to Google Maps JavaScript API v3
Fantastic!
You get a star.

Hmmmm.....do I dare put this in my app given that it is undocumented?

On Jul 21, 7:39 am, Nianwei Liu <nian...@gmail.com> wrote:
> This one is a bindTo Solution.
>
> http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/poly_bin...

Nianwei Liu

unread,
Jul 21, 2010, 10:55:01 AM7/21/10
to Google Maps JavaScript API v3
After some extra thinking I believe this should always work, it has
nothing to do with undocumented feature.

The fact is that the the drag action triggers Marker set('position')
which is bind to the Polyline path's set('prefix'<i>) method. It then
calls setAt, and that is a legit method to triggers a poly redraw.

Joseph Elfelt

unread,
Jul 21, 2010, 11:13:39 AM7/21/10
to Google Maps JavaScript API v3
Well that's an astute observation.
Perhaps we'll get lucky and one of the Google staff will comment.

Ben Appleton

unread,
Jul 21, 2010, 10:18:04 PM7/21/10
to google-map...@googlegroups.com
I like the MVCArrayBinder adaptor.  This uses only documented features
so it will continue to work.

One caveat: while MVCArrayBinder correctly forwards get/set calls to
its MVCArray, it does not forward events from the MVCArray to its
observers.  This means that if you directly call
polyline.getPath().setAt(0, ...), the 0th Marker does not know it
needs to repaint.

MVCArrayBinder could support this too, like:

function MVCArrayBinder(mvcArray){
var me = this;
me.array_ = mvcArray;

function forwardSetAt(index) {
google.maps.event.trigger(me, index + '_changed');
}
google.maps.event.addListener(mvcArray, 'set_at', forwardSetAt);
}

Note: I haven't checked that this code works, so there might be a bug.
But you get the idea.

Ben

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

William

unread,
Jul 21, 2010, 10:39:36 PM7/21/10
to Google Maps JavaScript API v3
On Jul 22, 12:27 am, Joseph Elfelt <josephelf...@gmail.com> wrote:
>
> I wish it was possible to use the bindTo feature to link the positions
> of my markers to the positions of the polyline nodes.
>

If you are going to build a polyline editing tool, another thing to
consider is whether your application will allow the user to insert
vertices in between the ones they've already drawn, or to delete
vertices. In this case the binding cannot be between the markers and
fixed indices in the array.

...

Joseph Elfelt

unread,
Jul 22, 2010, 12:51:14 AM7/22/10
to Google Maps JavaScript API v3
Ben & William,

Thanks for your thoughts.
This part of my project involves route planning and rightclicking a
marker will show a context menu that will include choices to:
delete the current marker
insert a marker after the current marker

On the map below you click to draw a line. The markers can be dragged
and the line follows.
Rightclick a marker for the skeleton of a context menu. Or rightclick
the map for coords.
Both types of rightclicks use the same infowindow.
http://www.mappingsupport.com/forum_post/drag_marker_and_line_beta1.html

(There's a bug I'll fix tomorrow. If you click an item in the context
menu that will also drop a new marker and extend the line.)

In the back of my mind I've been pondering the need to keep my marker
array in synch with my polyline MVCArray.
When I squarely address that issue I may decide not to pursue the
bindTo approach since the markers can come and go.

Ben - I'm not real clear on your reference to MVCArrayBinder. I
searched and did not find any hits on this critter.
I realize that more/better docs on MVCArrays and bindTo will appear
Real Soon Now.
In the meantime, can you shed a bit more light on MVCArrayBinder?
Should I be thinking of putting my markers into an MVCArray?








Ben Appleton

unread,
Jul 22, 2010, 12:58:15 AM7/22/10
to google-map...@googlegroups.com

William

unread,
Jul 22, 2010, 1:35:16 AM7/22/10
to Google Maps JavaScript API v3
On Jul 22, 12:39 am, Nianwei Liu <nian...@gmail.com> wrote:
> This one is a bindTo Solution.
>
> http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/poly_bin...
>

one small clarification, I guess you don't need to set the position of
the marker on construction because position is bound to the MVCArray:

var marker = new google.maps.Marker({
// position: event.latLng, <--- can we remove this line??
title: '#' + len,
map: map,
draggable : true
});
marker.bindTo('position', poly.binder, (len-1).toString());

...

Ben Appleton

unread,
Jul 22, 2010, 2:08:30 AM7/22/10
to google-map...@googlegroups.com
On Thu, Jul 22, 2010 at 3:35 PM, William <willia...@gmail.com> wrote:
> On Jul 22, 12:39 am, Nianwei Liu <nian...@gmail.com> wrote:
>> This one is a bindTo Solution.
>>
>> http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/poly_bin...
>>
>
> one small clarification, I guess you don't need to set the position of
> the marker on construction because position is bound to the MVCArray:
>
> var marker = new google.maps.Marker({
> //  position: event.latLng,  <--- can we remove this line??

Yes, that line has no effect. The subsequent marker.bindTo(...) clobbers it.

>  title: '#' + len,
>  map: map,
>  draggable : true
> });
> marker.bindTo('position', poly.binder, (len-1).toString());
>
> ...
>

Joseph Elfelt

unread,
Jul 22, 2010, 8:32:29 AM7/22/10
to Google Maps JavaScript API v3
Thanks Ben.

Nianwei - I apologize that I did not realize Ben was referring to your
intriguing code.


On Jul 21, 9:58 pm, Ben Appleton <apple...@google.com> wrote:
> I refer to Nianwei's MVCArrayBinder:http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/poly_bin...
p/google-maps-js-api-v3?hl=en.

Nianwei Liu

unread,
Jul 22, 2010, 10:23:09 AM7/22/10
to Google Maps JavaScript API v3
@Ben,
Thanks for pointing that out. Tested your code and worked fine. The
issue is that 'set_at' is not a documented event for MVCArray, so I am
expecting some new docs. I remember the older version of MVC was all
"get_/set_" for properties but eventually exposed "get/set" based on
feed back.
I also used the instance-prototype technique to override getter/
setter to retain events from the array. See
http://gmaps-utility-gis.googlecode.com/svn/trunk/v3test/mvc/instance_setter.html

Click map to draw a few points, then click on the 'moveFirst' button
on top middle of map to trigger a call to setAt and move the first
point of the line to the map center. The first marker will follow.
This solution can do without listening to the currently undocumented
'set_at' event. There maybe a slight risk depending on the API code
was written if it is compiled with Closure Compiler with advanced
optimization because the get/set maybe called as a difference name
internally.

@William:
That's a good point. Add/remove points in the middle of the array
will cause some problem, maybe the property needs a rebind or
something at the length change event. I noticed there is an issue
submitted with an internal tracking id for enable poly edit, so I'll
wait a little bit before trying to build one. I did noticed some other
folks have done some work to mimic the v2 editor, but the code does
not seem to be rewritten with reuse abstraction in mind.

> One caveat: while MVCArrayBinder correctly forwards get/set calls to
> its MVCArray, it does not forward events from the MVCArray to its
> observers.  This means that if you directly call
> polyline.getPath().setAt(0, ...), the 0th Marker does not know it
> needs to repaint.
>
> MVCArrayBinder could support this too, like:
>
> function MVCArrayBinder(mvcArray){
>   var me = this;
>   me.array_ = mvcArray;
>
>   function forwardSetAt(index) {
>     google.maps.event.trigger(me, index + '_changed');
>   }
>   google.maps.event.addListener(mvcArray, 'set_at', forwardSetAt);
>
> }
>
> Note: I haven't checked that this code works, so there might be a bug.
>  But you get the idea.
>
> Ben
>

William

unread,
Jul 23, 2010, 2:13:41 AM7/23/10
to Google Maps JavaScript API v3
On Jul 23, 12:23 am, Nianwei Liu <nian...@gmail.com> wrote:
> @William:
>   That's a good point. Add/remove points in the middle of the array
> will cause some problem, maybe the property needs a rebind or
> something at the length change event. I noticed there is an issue
> submitted with an internal tracking id for enable poly edit, so I'll
> wait a little bit before trying to build one. I did noticed some other
> folks have done some work to mimic the v2 editor, but the code does
> not seem to be rewritten with reuse abstraction in mind.
>
I had a go at it, by making a linked list interface to the MVCArray.
This class extends your MVCArrayBinder. I agree that the aim of this
exercise is to make something reusable. Here it is used to implement
the polyline editor. Clicking on the map adds a new vertex at the end
of the polyline. Vertices are moved by dragging the markers. Clicking
a marker inserts a vertex at the midpoint of the following segment.
Right clicking a marker deletes a vertex. Clicking the final marker
toggles the drawing mode, so a new vertex gets added before the start
of the polyline.

http://www.william-map.com/20100723/1/polyline.htm

...

Ben Appleton

unread,
Jul 23, 2010, 2:31:33 AM7/23/10
to google-map...@googlegroups.com
On Fri, Jul 23, 2010 at 12:23 AM, Nianwei Liu <nia...@gmail.com> wrote:
> @Ben,
>  Thanks for pointing that out. Tested your code and worked fine. The
> issue is that 'set_at' is not a documented event for MVCArray, so I am
> expecting some new docs.

Oops, I've updated the reference. The reference change should go live
in the next week or so. Thanks!

Nianwei Liu

unread,
Jul 23, 2010, 5:43:26 AM7/23/10
to Google Maps JavaScript API v3
Looks great! I can see a nice util lib emerged from this if a few more
things can be added/changed:
--- click on the line instead of adjacent node to add a new point.
That's the most intuitive way but more work is involved. To decide
the index of the new point, transverse nodes maybe needed or even
break the poly into segments and assign from/to nodes. Alternatively
middle "ghost" points like v2 should work too, but it may involve a
"ghost" line or at least a separate collection of markers.
--- double click to finish line. That's most drawing programs do, so
did v2.
--- I like right click to remove nodes, but most user may be
familiar with v2 with single click. I think both can be implemented
because marker's drag event does not interfere with click.
--- Use Google chart API for point icons, so it looks more like a
node than a push pin.
--- dispatch events such as "linefinished" etc as in v2. Can also
consider attach methods to Polyline's prototype if not defined for
forward compatibility.

William

unread,
Jul 23, 2010, 9:39:12 AM7/23/10
to Google Maps JavaScript API v3
yeah that can all be done, but in the first instance I'm interested in
finding the best design to enhance the MVCArray, in these kind of
situations where V3 concepts aren't fully implemented compared to V2,
for example another one is this thread which talks about problems with
overlay management:
http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/b7d796cfa05a40de

Reply all
Reply to author
Forward
0 new messages