I have multiple markers on google map v3. When map gets loaded it draws all marker and polyline. Initial path of the polyline would be same LatLng of each marker. When you drag marker it should draw the line between original LatLng to new position of the marker. You can move all and/or any markers on the map and each marker should have separate line showing marker's original LatLng to new position. I have done similar thing in below code but the problem is when I move marker it looses previous line of the marker. It always shows only one line of the dragged marker. How to solve this problem. Thanks in advance... Ash
<!DOCTYPE html>
<html>
<head>
<title>Marker with line example two</title>
<style type="text/css">
html {
height: 100%;
}
body {
height: 100%;
margin: 0;
padding: 0;
}
#map_canvas {
height: 100%;
}
</style>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="Scripts/jquery-1.10.2.min.js"></script>
<script>
var line;
var myLatlng = new google.maps.LatLng(41.7833, 5.2167);
var marker;
var lines = [];
function initialize() {
var domain = [new google.maps.LatLng(11.2583, 75.1374)];
var markers = [];
var mapOptions = {
zoom: 2,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
opacity: 0.2,
disableDefaultUI: true,
draggable: false
};
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
var lineCoordinates = [
new google.maps.LatLng(53.215556, 56.949219),
new google.maps.LatLng(75.797201, 125.003906),
new google.maps.LatLng(37.7833, 144.9667),
new google.maps.LatLng(-24.797201, 26.003906),
new google.maps.LatLng(27.797201, -101.003906)
];
for (i = 0; i < lineCoordinates.length; i++) {
var latLng = lineCoordinates[i],
marker = new google.maps.Marker({
position: latLng,
draggable: true,
title: i.toString(),
map: map,
});
markers.push({
key: i.toString(),
latLng: latLng
});
line = new google.maps.Polyline({
path: [latLng, latLng],
strokeOpacity: 0.8,
strokeWeight: 2,
strokeColor: '#f00',
geodesic: true
});
line.setMap(map);
lines.push(line);
google.maps.event.addListener(marker, 'drag', function (event) {
var title = this.title,
result = $.grep(markers, function (e) { return e.key === title }),
oldLatLng = result[0].latLng,
newLatLng = new google.maps.LatLng(this.getPosition().lat(), this.getPosition().lng());
line.setPath([oldLatLng, newLatLng]);
});
} //end of for loop
} //end of initialize function
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width: 1000px; height: 675px; margin-left: 400px; margin-top: 38px;"></div>
</body>
</html>
You were almost there. You have to make closure for variable line for event listener:
(function(line) {
google.maps.event.addListener(marker, 'drag', function (event) {
var title = this.title,
result = $.grep(markers, function (e) { return e.key === title }),
oldLatLng = result[0].latLng,
newLatLng = new google.maps.LatLng(this.getPosition().lat(), this.getPosition().lng());
line.setPath([oldLatLng, newLatLng]);
});
})(line);
Related
I have a 3D model placed in a map using mapbox with javascript (using this tutorial) and I'm trying to change the object's location when a button is clicked. The object isn't moving, though, and I don't really know how to fix it.
This is the function I wrote to make the location change (I can see all those console logs when I hit the button, so I know the part that isn't working is the actual location update itself):
function updateObjectLocation(id,newTransform) {
let objectLayer = map.getLayer(id);
if (typeof objectLayer === 'undefined') {
console.log('layer ' + id + ' does not exist');
} else {
console.log(objectLayer);
console.log(newTransform);
objectLayer.render = function(gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(1,0,0),
newTransform.rotateX
);
var rotationY = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0,1,0),
newTransform.rotateY
);
var rotationZ = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0,0,1),
newTransform.rotateZ
);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4()
.makeTranslation(
newTransform.translateX,
newTransform.translateY,
newTransform.translateZ
)
.scale(
new THREE.Vector3(
newTransform.scale,
- newTransform.scale,
newTransform.scale
)
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
};
}
}
Welcome to Stackoverflow. The solution is much simpler, you only have to modify the transformation, no need to rewrite the render method.
Here you have a fiddle with the solution how to move a 3D model
And here the full code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Add a 3D model</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css" rel="stylesheet" />
<style>
body {
margin: 0;
padding: 0;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#move {
display: block;
position: relative;
margin: 0px auto;
width: 50%;
height: 40px;
padding: 10px;
border: none;
border-radius: 3px;
font-size: 12px;
text-align: center;
color: #fff;
background: #ee8a65;
}
</style>
</head>
<body>
<script src="https://unpkg.com/three#0.106.2/build/three.min.js"></script>
<script src="https://unpkg.com/three#0.106.2/examples/js/loaders/GLTFLoader.js">
</script>
<div id="map"></div>
<button id="move">Move</button>
<script>
mapboxgl.accessToken = 'pk.eyJ1IjoianNjYXN0cm8iLCJhIjoiY2s2YzB6Z25kMDVhejNrbXNpcmtjNGtpbiJ9.28ynPf1Y5Q8EyB_moOHylw';
var map = (window.map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
zoom: 18,
center: [148.9819, -35.3981],
pitch: 60,
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));
// parameters to ensure the model is georeferenced correctly on the map
var modelOrigin = [148.9819, -35.39847];
var modelOrigin2 = [148.9816, -35.39851];
var modelAltitude = 0;
var modelRotate = [Math.PI / 2, 0, 0];
var modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin,
modelAltitude
);
// transformation parameters to position, rotate and scale the 3D model onto the map
var modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
var THREE = window.THREE;
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
id: '3d-model',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, gl) {
this.camera = new THREE.Camera();
this.scene = new THREE.Scene();
// create two three.js lights to illuminate the model
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set(0, -70, 100).normalize();
this.scene.add(directionalLight);
var directionalLight2 = new THREE.DirectionalLight(0xffffff);
directionalLight2.position.set(0, 70, 100).normalize();
this.scene.add(directionalLight2);
// use the three.js GLTF loader to add the 3D model to the three.js scene
var loader = new THREE.GLTFLoader();
loader.load(
'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf',
function (gltf) {
this.scene.add(gltf.scene);
}.bind(this)
);
this.map = map;
// use the Mapbox GL JS map canvas for three.js
this.renderer = new THREE.WebGLRenderer({
canvas: map.getCanvas(),
context: gl,
antialias: true
});
this.renderer.autoClear = false;
},
render: function (gl, matrix) {
var rotationX = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(1, 0, 0),
modelTransform.rotateX
);
var rotationY = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 1, 0),
modelTransform.rotateY
);
var rotationZ = new THREE.Matrix4().makeRotationAxis(
new THREE.Vector3(0, 0, 1),
modelTransform.rotateZ
);
var m = new THREE.Matrix4().fromArray(matrix);
var l = new THREE.Matrix4()
.makeTranslation(
modelTransform.translateX,
modelTransform.translateY,
modelTransform.translateZ
)
.scale(
new THREE.Vector3(
modelTransform.scale,
-modelTransform.scale,
modelTransform.scale
)
)
.multiply(rotationX)
.multiply(rotationY)
.multiply(rotationZ);
this.camera.projectionMatrix = m.multiply(l);
this.renderer.state.reset();
this.renderer.render(this.scene, this.camera);
this.map.triggerRepaint();
}
};
map.on('style.load', function () {
map.addLayer(customLayer, 'waterway-label');
});
document.getElementById('move').addEventListener('click', function () {
// creating an event listener to modify the position to modelOrigin2
modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
modelOrigin2,
modelAltitude
);
// transformation parameters to position, rotate and scale the 3D model onto the map
modelTransform = {
translateX: modelAsMercatorCoordinate.x,
translateY: modelAsMercatorCoordinate.y,
translateZ: modelAsMercatorCoordinate.z,
rotateX: modelRotate[0],
rotateY: modelRotate[1],
rotateZ: modelRotate[2],
/* Since our 3D model is in real world meters, a scale transform needs to be
* applied since the CustomLayerInterface expects units in MercatorCoordinates.
*/
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
};
});
</script>
</body>
</html>
BTW, if you are trying to create a much more interactive experience between Mapbox and Three.js, but I would recommend you to check out the latest version of threebox as it enables you to add as many models and 3D layers as you want but also to do things like these below with only a few lines of code
map.on('style.load', function () {
map.addLayer({
id: 'custom_layer',
type: 'custom',
renderingMode: '3d',
onAdd: function (map, mbxContext) {
window.tb = new Threebox(
map,
mbxContext,
{ defaultLights: true }
);
var options = {
obj: '/3D/soldier/soldier.glb',
type: 'gltf',
scale: 1,
units: 'meters',
rotation: { x: 90, y: 0, z: 0 } //default rotation
}
tb.loadObj(options, function (model) {
soldier = model.setCoords(origin);
tb.add(soldier);
})
},
render: function (gl, matrix) {
tb.update();
}
});
})
- 3D models built-in and custom animations
- Full raycast support MouseOver/Mouseout, Selected, Drag&Drop, Drag&Rotate, Wireframe
- CSS2D Tooltips and Labels that consider altitude
**- Three.js and Mapbox cameras sync with depth adjustment **
- Include geolocated models of monuments
So I have a functioning code (example here) to create a split screen of half google map Hybrid view and then when you click somewhere on that map (left side) then (right side) opens street view for that location.
I want to have a marker on the hybrid map side that when clicked on opens an info window on that side and then the street view for that location on the right side of the screen. But I can't seem to figure out how to code in that marker to open as an info window/bubble on the left side map?
Here's the code currently (including the mistake I've made as it doesn't work):
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script>
var myCenter = new google.maps.LatLng(42.315126 , -72.63455);
var DoYouFeel = new google.maps.LatLng(42.315148 , -72.634429)
var sv = new google.maps.StreetViewService();
var panorama;
function initialize() {
panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'));
// Set up the map
var mapOptions = {
center: myCenter,
zoom: 16,
mapTypeId: google.maps.MapTypeId.HYBRID,
streetViewControl: false
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
//Set up the markers
var marker = new google.maps.Marker({
position: DoYouFeel,
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function() {
bubble = new google.maps.InfoWindow({
content: '<div id="mydiv"><br><embed src="Do You Feel....mov" width="720" height="576" align="center"><br><br></div>'
})
bubble.open(map, marker);
});
// getPanoramaByLocation will return the nearest pano when the
// given radius is 50 meters or less.
google.maps.event.addListener(map, 'click', function(event) {
sv.getPanoramaByLocation(event.latLng, 50, processSVData);
});
}
function processSVData(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
var marker = new google.maps.Marker({
position: data.location.latLng,
map: map,
title: data.location.description
});
panorama.setPano(data.location.pano);
panorama.setPov({
heading: 270,
pitch: 0
});
panorama.setVisible(true);
google.maps.event.addListener(marker, 'click', function() {
var markerPanoID = data.location.pano;
// Set the Pano to use the passed panoID
panorama.setPano(markerPanoID);
panorama.setPov({
heading: 270,
pitch: 0
});
panorama.setVisible(true);
});
} else {
alert('Street View data not found for this location.');
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
My demo is here http://jsfiddle.net/akuma/7NmXw/1/
First, draw something in the blue box.
Then, click the rotate button once.
After the box has been rotated, draw something again.
Finally the draw poisitoin was wrong.
How can I fix that, thanks!
Code:
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer({
width: 400,
height: 400
});
var rect = new Kinetic.Rect({
x: 0,
y: 0,
width: 400,
height: 300,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 5
});
layer.add(rect);
stage.add(layer);
$(document).on('click', '#rotateBtn', function () {
var w = layer.getWidth(),
h = layer.getHeight();
layer.setOffset(w / 2, h / 2);
layer.setPosition(w / 2, h / 2);
layer.rotateDeg(90);
layer.draw();
});
var points = [],
drawing = false;
stage.on('mousedown', function () {
drawing = true;
var pos = stage.getMousePosition();
points.push([pos.x, pos.y]);
var line = new Kinetic.Line({
id: 'line',
points: [
[pos.x, pos.y],
[pos.x + 1, pos.y + 1]
],
stroke: 'white',
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
layer.drawScene();
});
stage.on('mousemove', function () {
if (!drawing) {
return;
}
// Remove previous line
layer.get('#line').remove();
var pos = stage.getMousePosition();
points.push([pos.x, pos.y]);
// Redraw line
var line = new Kinetic.Line({
id: 'line',
points: points,
stroke: 'white',
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
layer.drawScene();
});
stage.on('mouseup', function () {
drawing = false;
points = [];
});
Even after rotating, Kinetic will still give you un-rotated mouse coordinates
That’s because you are asking for stage.getMousePosition and the stage is not rotated.
There is no method like layer.getMousePosition, so you’ll have to create one.
If you rotate your layer 90-degrees, you must also rotate stage's mouse coordinates by 90-degrees.
Here’s how you rotate the stage mouse position to match the layer rotation:
// get the unrotated mouse position from Kinetic
var pos=stage.getMousePosition();
// rotate that point to match the layer rotation
var x1 = rotationX
+ (pos.x-rotationX)*rotationCos
+ (pos.y-rotationY)*rotationSin;
var y1 = rotationY
+ (pos.y-rotationY)*rotationCos
- (pos.x-rotationX)*rotationSin;
Since you will be doing this math with each mousemove, you should pre-calculate the rotation values to maximize performance:
// reset the current rotation information
function setRotation(degrees){
var radians=layer.getRotation();
rotationX=layer.getOffsetX();
rotationY=layer.getOffsetY();
rotationCos=Math.cos(radians);
rotationSin=Math.sin(radians);
}
Also, a bit off-topic to your question, but...
Instead of removing / recreating a new line on every mousemove, you can “recycle” your existing line:
// set the points property of the line to your updated points array
line.setPoints(points);
Here’s code and a Fiddle: http://jsfiddle.net/m1erickson/cQATv/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.5.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:400px;
height:400px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer({width:400,height:400});
stage.add(layer);
// vars to save the current rotation information
var rotationX;
var rotationY;
var rotationCos;
var rotationSin;
setRotation(0);
var rect = new Kinetic.Rect({
x: 0,
y: 0,
width: 400,
height: 300,
fill: '#00D2FF',
stroke: 'black',
strokeWidth: 5
});
layer.add(rect);
stage.add(layer);
$(document).on('click', '#rotateBtn', function () {
var w = layer.getWidth(),
h = layer.getHeight();
layer.setOffset(w / 2, h / 2);
layer.setPosition(w / 2, h / 2);
layer.rotateDeg(90);
layer.draw();
// set the info necessary to un-rotate the mouse position
setRotation(layer.getRotationDeg())
});
var points = [],
drawing = false;
stage.on('mousedown', function () {
drawing = true;
// get the rotated mouse position
pos=getPos();
points.push([pos.x, pos.y]);
var line = new Kinetic.Line({
id: 'line',
points: [
[pos.x, pos.y],
[pos.x + 1, pos.y + 1]
],
stroke: 'white',
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
layer.drawScene();
});
stage.on('mousemove', function () {
if (!drawing) {
return;
}
// Remove previous line
layer.get('#line').remove();
// get the rotated mouse position
var pos = getPos();
points.push([pos.x, pos.y]);
// Redraw line
var line = new Kinetic.Line({
id: 'line',
points: points,
stroke: 'white',
strokeWidth: 5,
lineCap: 'round',
lineJoin: 'round'
});
layer.add(line);
layer.drawScene();
});
stage.on('mouseup', function () {
drawing = false;
points = [];
});
// reset to the current rotation information
function setRotation(degrees){
var radians=layer.getRotation();
rotationX=layer.getOffsetX();
rotationY=layer.getOffsetY();
rotationCos=Math.cos(radians);
rotationSin=Math.sin(radians);
}
// rotate the stage mouse position
// to match the layer rotation
function getPos(x,y){
// normal space, no adjustment necessary
if(rotationCos==0){return;}
var pos=stage.getMousePosition();
var x1 = rotationX
+ (pos.x-rotationX)*rotationCos
+ (pos.y-rotationY)*rotationSin;
var y1 = rotationY
+ (pos.y-rotationY)*rotationCos
- (pos.x-rotationX)*rotationSin;
return({x:x1,y:y1});
}
}); // end $(function(){});
</script>
</head>
<body>
<button id="rotateBtn">rotate</button>
<div id="container"></div>
</body>
</html>
Check out my html5 based clipping constraint on
http://shedlimited.debrucellc.com/test3/canvaskinclip.html
(messing with jsfiddle on http://jsfiddle.net/aqaP7/4/)
So, in html5 I can easily draw a shaped boundary like the following:
context.beginPath();
context.moveTo(5, 5);
context.lineTo(34, 202);
context.lineTo(2, 405);
context.lineTo(212, 385);
context.lineTo(425, 405);
context.lineTo(400, 202);
context.lineTo(415, 10);
context.lineTo(212, 25);
context.clip();
In kinetic.js though, all I see for clipping options is: height, width, and x, y,
I came across the following : Mask/Clip an Image using a Polygon in KineticJS, but the inner/fill image can't be set to draggable
any help please!
In the new kineticJS versions, a lot of the work is done in the background for you.
Take a look at this tutorial:
This fiddle gets you pretty close, here's the code:
<body>
<div id="container"></div>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.0-beta2.js"></script>
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function draw(images) {
var stage = new Kinetic.Stage({
container: 'container',
width: 600,
height: 700
});
var layer = new Kinetic.Layer();
var patternPentagon = new Kinetic.RegularPolygon({
x: 220,
y: stage.getHeight() / 4,
sides: 5,
radius: 70,
fillPatternImage: images.yoda,
fillPatternOffset: [-220, 70],
stroke: 'black',
strokeWidth: 4,
draggable: true
});
patternPentagon.on('dragmove', function() {
//this.setFillPatternImage(images.yoda);
//this.setFillPatternOffset(-100, 70);
var userPos = stage.getUserPosition();
this.setFillPatternOffset(-userPos.x,-userPos.y);
layer.draw();
this.setX(220);
this.setY(stage.getHeight() / 4);
});
layer.add(patternPentagon);
stage.add(layer);
}
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, function(images) {
draw(images);
});
</script>
</body>
There is a more complex/accurate way of doing this without making it a background pattern, like with grouping objects together
i just want to set some markers based on a xml file and additionally create three different marker clusterer with own icons!
the problems are:
no markers are displayed
how i have to implement three marker groups (marker clusterer) with my own icons
index.html
<html>
<head>
<title>Google Maps Integration</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="js/jquery-1.4.1.min.js"></script>
<script type="text/javascript" src="js/data.json"></script>
<script type="text/javascript" src="js/markerclusterer.js"></script>
<script type="text/javascript" src="js/markers.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>
marker.js
$(document).ready(function() {
$("#map").css({
height: 675,
width: 659
});
var myLatLng = new google.maps.LatLng(51.918, 4.47663);
MYMAP.init('#map', myLatLng, 7);
MYMAP.placeMarkers("markers.xml"); // xml data
});
var MYMAP = {
map: null,
}
MYMAP.init = function(selector, latLng, zoom) {
var myOptions = {
zoom:zoom,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map($(selector)[0], myOptions);
}
// set markers
MYMAP.placeMarkers = function(filename) {
var markers = []; // create new array for marker points
$.get(filename, function(xml){
$(xml).find("marker").each(function(){
var name = $(this).find('name').text();
var address = $(this).find('address').text();
// create a new LatLng point for the marker
var lat = $(this).find('lat').text();
var lng = $(this).find('lng').text();
var point = new google.maps.LatLng(parseFloat(lat),parseFloat(lng));
// set marker new
var marker = new google.maps.Marker({position: point});
markers.push(marker);
// set marker info
var infoWindow = new google.maps.InfoWindow();
var html='<b>'+name+'</b><br>'+address;
google.maps.event.addListener(marker, 'click', function() {
infoWindow.setContent(html);
infoWindow.open(MYMAP.map, marker);
});
});
var markerCluster = new MarkerClusterer(map, markers);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
marker.xml
<?xml version="1.0"?>
<markers>
<marker>
<name>Heineken Amsterdam</name>
<address>Joop Geesinkweg 5</address>
<city>Amsterdam</city>
<postcode>1096 AT</postcode>
<lat>52.3354</lat>
<lng>4.92938</lng>
</marker>
</markers>
Check out the newest version of markerclusterPlus here:
http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.6/
There is a good doc and some examples too.