Sencha (ExtJS) Map Control

En esta semana se me metió la idea a la cabeza de hacer un control de ExtJS para manejar mapas. Por ejemplo, supongamos que tienes que hacer una aplicación donde te dan una imagen de un fraccionamiento y tienes que identificar todas las propiedades en dicha imagen y luego mostrar el mapa con una imagencilla que indica el estatus (si ya esta vendida, en renta, o lo que sea).

Google maps nos saca del apuro muchas veces, pero a veces necesitamos usar nuestras propias imagenes (mapas), es por eso que comenzé a desarrollar este controlillo.

El control en acción:



Antes de comenzar es necesario hacer pruebas de CSS para ver que atributos necesitamos para que el mapa aparezc adentro de un cuadrito (DIV), para esto es necesario poner un div (al que llamaré wrapper) y es necesario que tenga posición "relative" y overflow: hidden. Esto es para que la imagen no se aplaste dentro del wrapper. Despues, a la imagen le ponemos posición "absolute" y listo, ya tenemos una imagen encerrada dentro de un div igual que google maps. Lo que sigue es agregarle la funcionalidad drag a la imagen interna para poder moverla dentro del div. Lo que todos sabemos es que si ponemos un elemento del DOM en posicion absoluta, este ignorará la jerarquia del DOM y "flotará" por encima de los demás, sin embargo, si su padre tiene posición relativa (como el wrapper), entonces este quedará atrapado dentro de su padre.

Esta algo confuso, pero asi funciona y eso no lo sabia jojo.

Apenas llevo la primera etapa, ya funciona el "Drag" del mapa para moverlo y cuando das click pone una marker, el siguiente paso es guardar toda la info de las markers y serializarlas para poder enviarlas al server, tambien falta el setValues, para que puedas regresar las markers desde el server y mostrarlas en el mapa, pero bueno, esto me lo eche en una noche, espero terminarlo pronto y subirlo completo.

Pero bueno, el codigo del control es el siguiente:


Ext.ns('Ext.ux.ImageMap');

Ext.ux.ImageMap = Ext.extend(Ext.form.Field, {
initComponent : function(){
/*Apply modified Properties, Listeners dont work here*/
Ext.apply(this,{
autoCreate : {tag:'div', style:'position:relative; overflow:hidden; border:1px solid black;'}
});
this.markers = [];
/*Change Normal Events*/
Ext.ux.ImageMap.superclass.initComponent.apply(this, arguments);
}
,onRender : function (){
Ext.ux.ImageMap.superclass.onRender.apply(this, arguments);
var me = this;
/*Main Overflown wrapper*/
this.wrapper = this.el;
/*Create inner wrapper with image inside */
this.innerwrapper = this.wrapper.createChild({
tag : 'div'
,style : 'position:absolute;'
,children : [{
id : this.mapId = Ext.id() + 'map'
,tag : 'img'
,src : this.bgimage
}]
});


/*Add click event*/
this.innerwrapper.on({
click: function(evt){
if(!me.endDrag){

me.addMarker(evt.xy);
}else{
//Reste drag flag
me.endDrag = false;
}
}
})
/*Set Draggable Actions*/
this.dd = new Ext.dd.DD(this.innerwrapper, 'group');
Ext.apply(this.dd,{
endDrag : function(e){
/*Flag to avoid firing the click event when its a drag*/
me.endDrag = e.getTarget().id == me.mapId ? true : false;
}
});

}
,addMarker : function(p){
var m = this.innerwrapper.createChild({
tag : 'div'
,html :' '
,cls : this.markerImgClass
});
this.markers.push(m);
var ctXY = this.wrapper.getXY();
var imgXY = this.innerwrapper.getXY(); //absolute to frame

//Calculate position
var pos = [];
pos[0] = ctXY[0] - imgXY[0];
pos[1] = ctXY[1] - imgXY[1];
p[0] = pos[0] + (p[0] - ctXY[0])-8;
p[1] = pos[1] + (p[1] - ctXY[1])-8;
m.setLeftTop(p[0], p[1]);

console.log(this.markers);
}
});



Ext.onReady(function(){

/*To use the control just add it to a form or render it to a div*/
var form = new Ext.form.FormPanel({
renderTo :'container'
,title : 'Image Control'
,items : [

new Ext.ux.ImageMap({
height :200
,width :300
,hideLabel : true
,bgimage : '../assets/images/map.jpg' //map image you want to use
,markerImgClass : 'markerImgClass' //marker image
})
]

});
});



Jerry ;)

3 Comments:

Lorenzo said...

He probado tu control y me funciona genial, pero no consigo que se vean los marcadores. ¿Podrías poner la clase de estilos que usas para mostrarlos?

gracias,

Jerry Sosa said...

Hola lorenzo, ya no tengo el código fuente porque me cambié de trabajo y se quedó en la otra laptop. Pero la clase "markerImgClass" debe de ser algo asi:

.markerImgClass{background: transparent url('tuPath/tuImagen.jpg') no-repeat;}

Saludos!

Anonymous said...
This comment has been removed by a blog administrator.

Post a Comment