Mapsforge [1] es un API de visualización de mapas de OpenStreetMap en Android que permite visualizar mapas off line, esto es, que han sido grabados previamente en el dispositivo y no requieren conexión a internet.
Los mapas tienen que estar en formato ‘.map’.
Los archivos ‘.map’ se generan a partir de los archivos ‘.osm’ de OpenStreetMap. Para crearlos nos hace falta utilizar la herramienta ‘Osmosis’ [2], a la que hay que instalarle un plugin de Mapsforge.
La documentación a la fecha es poco clara, por lo que voy a explicar aquí los pasos que he seguido yo para generar los mapas y que me han funcionado muy bien:

  • Descargar Osmosis y descomprimir en un directorio
  • Darle path al directorio bin de la instalación de Osmosis, para que podamos ejecutar la herramienta ‘osmosis’
  • Descargar las librerías Mapsforge. Son dos, la de visualizar y la de crear mapas. La de visualizar se la añadiremos a los proyectos Android. La de crear mapas es la que añadiremos a Osmosis para poder crear nuestros mapas
    • mapsforge-map-0.3.0-jar-with-dependencies.jar Esta es la de visualización en Android
    • mapsforge-map-writer-0.3.0-jar-with-dependencies.jar Esta es la que nos permite crear el plugin en Osmosis
  • Copiar la librería del map-writer en el directorio ‘lib/default’ de la instalación de Osmosis
  • Crear un fichero llamado ‘osmosis-plugins.conf’ dentro del directorio ‘config’ de la instalación de Osmosis
  • Añadirle la siguiente línea: org.mapsforge.map.writer.osmosis.MapFileWriterPluginLoader

Con esto tendremos configurado el plugin de Mapsforge para Osmosis. Ahora podemos coger un archivo ‘.osm’ y convertirlo a ‘.map’ con un comando como el siguiente:

osmosis
    --read-xml file=mimapa.osm
    --mapfile-writer file=mimapa.map
    bbox=40.0,-3.0,42.0,-1.0
    map-start-position=41.0,-2.0
    map-start-zoom=16

Una vez generado el fichero ‘.map’ podremos incorporarle al dispositivo Android y utilizar el API de Mapsforge para visualizar mapas.
Dejo en [3] un enlace a un pequeño ejemplo. La primera vez que se ejecuta tarda un poco más porque copia el mapa a la tarjeta de memoria.


[1] Mapsforge http://code.google.com/p/mapsforge/
[2] Osmosis http://wiki.openstreetmap.org/wiki/Osmosis
[3] TestMF.apk


Santiago Higuera (7 Mayo 2012)

En OpenLayers tenemos dos proyecciones definidas por defecto que son la EPSG:4326 (Coordenadas geográficas Datum WGS-84) y la EPSG::900913 (Spherical Mercator, habitualmente utilizada en los mapas de OpenStreetMap, Google y otros).

Podemos incorporar otras proyecciones. Para ello tenemos que incluir en nuestro código la librería PROJ4JS que nos permitirá definir proyecciones y realizar las correspondientes transformaciones entre ellas. La librería Proj4JS la podemos descargar desde:

http://trac.osgeo.org/proj4js/wiki/Download

Situaremos el fichero proj4js-combined.js en un directorio accesible desde nuestra página web a la que añadiremos una sentencia del tipo:

<script src="lib/proj4js-combined.js"></script>

Ahora ya podemos utilizar en nustro código Javascript la definición de proyecciones. Por ejemplo, para definir la proyección UTM zona 30 Norte, (EPSG:23030), debemos incluir en el código Javascript la siguiente sentencia:

Proj4js.defs["EPSG:23030"] = "+proj=utm +zone=30 +ellps=intl"+
    " +towgs84=-131,-100.3,-163.4,-1.244,-0.020,-1.144,9.39 "+
    " +units=m +no_defs";

También podemos incluir una proyección concreta en nuestro código mediante la siguiente construcción:

<script
    src="http://spatialreference.org/ref/epsg/23030/proj4js/">
</script>

Ahora solamente nos queda utilizar las proyecciones definidas. Por ejemplo podríamos pasar de WGS84 a UTM-30N mediante la siguiente sentencia:

var wgs84Projection = new OpenLayers.Projection("EPSG:4326");
var utmProjection = new OpenLayers.Projection("EPSG:23030");
var defaultMapCenter = new OpenLayers.LonLat(-3.7, 40.985165)
	.transform(wgs84Projection, utmProjection);

Las definiciones de las distintas proyecciones las podemos obtener en :

http://spatialreference.org/

Hemos preparado un ejemplo completo en el que cargamos la capa del Mapa Topográfico Nacional Español Raster Escala 1:25.000 y la capa de las fotografías del Plan Nacional deOrtofotografía Aérea, PNOA. El resultado lo puedes ver en :

olutm.html

Santiago Higuera (30 Marzo 2012)

Programando en Javascript es posible adoptar un enfoque orientado a objetos. De esta forma, mediante el mecanismo de ir extendiendo las clases según una jerarquía determinada, vamos obteniendo objetos adaptados a nuestras necesidades partículares que reducirán el tiempo de los desarrollos futuros.

OpenLayers es una librería Javascript que utiliza esta aproximación, mediante una jerarquía de clases que dan servicio a las diferentes funcionalidades para las que se ha pensado el programa.

Podemos utilizar la arquitectura de clases de OpenLayers para crearnos una librería de clases propia que tenga objetos tales como ‘miMapa‘, que incluye ya los controles y capas que suelo utilizar, o ‘miFeature‘ que incorpora determinadas features utilizadas por mi programa con sus propias características de visualización, por ejemplo.
Vamos a explicar en este artículo como crear una jerarquía propia de clases basada en la arquitectura proporcionada por OpenLayers.

Para ello utilizaremos primero una jerarquia simple de objetos comunes como la indicada en el siguiente esquema:




En ella definimos las clases ‘Punto‘ y ‘P3d‘. La clase Punto tiene como atributos las coordenadas x e y correspondientes a la representación de un punto en dos dimensiones. De ella deriva la clase ‘P3d‘ que añade una tercera coordenada z. La clase ‘P3d‘ hereda las propiedades y métodos de la clase ‘Punto‘, algunos de los cuales los sobreescribe.
Para implementar este esquema en nuestro programa Javascript+OpenLayers utilizaremos dos archivos:

  • Libreria js : La hemos llamado ‘clases1.js‘ y contiene las definiciones correspondientes a nuestra colección de clases.
  • Fichero html : Lo hemos llamado ‘clases1.html‘ y deberá incluir el link a la librería de OpenLayers y a nuestra librería de clases ‘clases1.js‘. Además, el fichero ‘clases1.html‘, incorpora un pequeño script donde probamos la librería.

Vamos a analizar en primer lugar la librería ‘clases1.js‘. Es conveniente en primer lugar definir nuestro propio espacio de nombres, de forma que todas nuestras clases queden ‘aisladas’ del resto de librerías que utilize el programa. Hemos elegido llamar ‘MisGeos‘ a nuestro espacio de nombres. Para definirlo se utiliza la siguiente construcción:

MisGeos = {};

A continuación definimos la clase ‘MisGeos.Punto‘. Para ello utilizaremos el objeto-función ‘OpenLayers.Class‘ definido en la librería OpenLayers. Esta es la función encargada de crear nuevas clases y de gestionar el mecanismo de herencia. Para crear una nueva clase es necesario pasarle dos paramétros: La clase de la cual deriva nuestra nueva clase y, como segundo parámetro, un array asociativo con la definición de las nuevas propiedades y métodos que incorpora el nuevo objeto:

nuevaClase = OpenLayers.Class(
    ClasePadre,
    ArrayNuevasDefiniciones
);

El array del segundo parámetro tendrá la siguiente estructura:

ArrayNuevasDefiniciones= {
    prop1: valor1,
    prop2: valor2,
    metodo1: function() {...},
    metodo2: function(..) {....}
};

Vemos que cada elemento del Array es una definición de una propiedad o método y consta del nombre, los ‘dos puntos’ y la definición correspondiente. Lo veremos más claramente con el caso concreto de nuestra clase MisGeos.Punto:

MisGeos.Punto = OpenLayers.Class(MisGeos, {
    initialize: function(xx, yy) {
        this.x = xx;
        this.y = yy;
    },
    x : null,
    y : null,
    toString : function() {
        return "("+this.x+","+this.y+")";
    }
});

Vemos que el constructor de la clase es una función especial que se debe de llamar ‘initialize‘. También hay que destacar cómo definimos las propiedades ‘x‘ e ‘y‘, a las que inicialmente asignamos un valor nulo, y cómo se procede a la asignación de sus valores. El constructor ‘initialize‘ recibe dos números ‘xx‘ e ‘yy‘ como parámetros y los asigna a las propiedades del objeto utilizando el ‘this‘. Este detalle es importante. Si no utilizamos ‘this‘, los valores serían asignados a ciertas variables ‘x‘ e ‘y‘ locales del propio método ‘initialize‘.

El método ‘toString()‘ muestra el contenido de las propiedades ‘x‘ e ‘y‘ de la instancia, encerrados entre paréntesis y separados por una coma.

Para crear una instancia de objeto de la clase MisGeos.Punto habrá que hacerlo de la siguiente manera:

var p1 = new MisGeos.Punto(-3.0,42.3);

Una vez creada la clase MisGeos.Punto, vamos a crear una clase ‘MisGeos.P3d‘ que derive de la anterior y añada una tercera coordenada. La forma de hacerlo es la siguiente:

MisGeos.P3d = OpenLayers.Class(MisGeos.Punto, {
    initialize : function(xx, yy, zz) {
        MisGeos.Punto.prototype.initialize.apply(
            this, [xx, yy]);
	this.z = zz;
    },
    z : null,
    toString : function() {
        return "("+this.x+", "+this.y+", "+this.z+")";
    }
});

Aquí es importante darse cuenta de la manera de llamar al constructor de la clase base, MisGeos.Punto, desde el constructor de la clase ‘MisGeos.P3d‘:

clasebase.prototype.initialize.apply (
    this,
    [parametros pasados al constructor]
);

Además podemos ver que se sobreescribe el método ‘toString()‘ de la clase base para adaptarlo a la nueva clase.

Con esto queda creada la librería con nuestros dos tipos de objetos ‘Punto‘ y ‘P3d‘. Para probar la librería utilizaremos un sencillo script, que se ha añadido en la página html, y que tiene la siguiente forma:

P1 = new MisGeos.Punto(-3.09, 45.78);
document.write ( "Punto P1: " + P1.toString());
P2 = new MisGeos.P3d(10,20,30);
document.write ("P3d P2: " + P2.toString());

El código completo de los dos ficheros lo puedes ver en:

En un próximo artículo aplicaremos esta metodología a la creación de clases de mapas y features personalizados.

Santiago Higuera (11 Abril 2011)

A veces necesitamos pasar algún valor contenido en una variable PHP a una variable Javascript. Podemos hacerlo de la siguiente manera:
PHP a Javascript:

<?php $mivarPhp = "Asignado en PHP"; ?>
<script type="text/javascript>
   var mivarJS ="Asignado en JS";
   alert (miVarJS);
   mivarJS=<?php echo $mivarPHP ?>;
   alert (mivarJS);
</script>

Javascript a PHP:

En el caso contrario, esto es, para pasar un valor desde Javascript a PHP podemos hacerlo de la siguiente manera:

<?php $mivarPHP=
    '<script type="text/javascript">;
    var mivarJS="Asignado en JS";
    document.writeln (mivarJS);
</script>'; ?>

Espero que os resuelva.


Angel Higuera (15 Febrero 2011)

Una feature consta de una geometria y un estilo. La geometría será una clase derivada de OpenLayers.Geometry. Estas clases tienen dos metodos ‘move’ y ‘rotate’ que permiten ajustar dinámicamente la posición de las features sobre el mapa. Las features tienen que haber sido creadas y añadidas a la capa vectorial previamente.
Una vez llamadas las funciones ‘move’ y/o ‘rotate’ hay que llamar al método ‘drawFeature()‘ de la capa para que se redibuje.

Al método ‘rotate hay que pasarle dos argumentos : un ángulo de rotación en grados (antihorario positivo) y un objeto OpenLayers.Geometry.Point que hará de centro de la rotación.

rotate: function( angle: Float, center: OpenLayers.Geometry.Point)

El método ‘move acepta como parametros el valor de los desplazamientos deseados en la dirección x e y:

move: function( x: Float, y: Float)

El ejemplo de la documentación de OpenLayers ha servido para documentar el artículo y aplica los métodos aquí expuestos a geometrías Point, LineString y LinearRing.

El método rotate no gira la feature sobre si misma, sino que realiza un giro de la feature respecto del centro de giro indicado. Si el centro de giro coincide con el centro de la feature, la feature no rota sobre si misma. Esto sucede cuando se utiliza una imagen en el estilo de una feature con geometría Point y se quiere girar sobre si misma, esto es, con centro de rotación en el centro de la feature, para orientar el icono en una determinada dirección. En este caso para girar la imagen habrá que actuar sobre la propiedad ‘style.rotation‘ de la feature, asignándole el ángulo deseado.



Santiago Higuera (14 Febrero 2011)

Para mostrar etiquetas en mapas creados con OpenLayers podemos utilizar la clase OpenLayers.Feature.Vector.
El constructor de Feature.Vector nos pide dos parámetros: una geometría y un estilo:

var feat = new OpenLayers.Feature.Vector( geometry, null, style);

(El segundo parámetro es un objeto con atributos opcionales para incorporar a la feature. En nuestro caso no lo vamos a utilizar)
Para la geometría utilizaremos una instancia de la clase OpenLayers.Geometry.Point. Al constructor deberemos pasarle las coordenadas x,y del punto donde queramos situar la etiqueta:

var point = new OpenLayers.Geometry.Point(x,y);

Si las coordenadas provienen de objetos LonLat habrá que crearla de la siguiente manera:

var lonlat = new OpenLayers.LonLat( -3.74, 42.37);
var point = new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);

Las features vectoriales tienen una propiedad denominada ‘style’ que es un objeto con las propiedades de visualización. Según la geometría que tenga la feature las propiedades se referirán a las características del grueso de linea, del radio del punto o, en nuestro caso, el estilo del texto. Las propiedades de estilo que puede tener una feature vectorial se detallan en la documentacion de los symbolizer.
La forma práctica de obtener un objeto estilo es utilizar el método ‘extend’ con un estilo por defecto y modificar el valor de las propiedades que queramos personalizar.

var pstyle = OpenLayers.Util.extend({},
    OpenLayers.Feature.Vector.style['default']
);
pstyle.graphic = false;
pstyle.label = "Hola Mundo";
pstyle.fontColor = "#000000";
pstyle.fontOpacity = 1;
pstyle.fontFamily="Arial";
pstyle.fontSize = "23";
pstyle.fontWeight = "bold";

La propiedad ‘graphic’ es un Boolean que indica si queremos representar el ‘simbolizer’ del punto. Poniendo el valor en ‘false’ sólo se visualizará la etiqueta. Si lo activamos con ‘true’ se verán la etiqueta y el punto(por defecto un circulo). En este caso disponemos de las propiedades ‘labelXOffset’ y ‘labelYOffset’ para situar el texto de la etiqueta respecto del símbolo del punto.
Una vez creada la feature vectorial a partir de la geometría y el estilo habrá que añadirsela a una capa vectorial que habremos creado previamente:

var layerVector = new OpenLayers.Layer.Vector("Vectorial");
var feat = new OpenLayers.Feature.Vector(
    point, null, labelst);
layerVector.addFeatures([feat]);

Hemos preparado un pequeño ejemplo en el que se utiliza un mapa cuya única capa es la capa vectorial que contiene la etiqueta. Esto se consigue pasando al mapa la propiedad ‘allOverlays’ con el valor ‘true’ y fijando una extensión para el mapa.
Ejemplo de Etiqueta en OpenLayers

Voy a publicar aquí una librería javascript que ando utilizando en mis páginas para acceder a MySQL, con muy buenos resultados. Consta de dos ficheros:

  • mysqlws.php: Contiene la parte del servidor.
  • mysqlwslib.js: Contiene la librería javascript propiamente dicha.

Siento desilusionar a los que esperasen javascript puro, sin php, pero ahí no llego.

Instalación:Descargar el paquete y descomprimirlo para obtener los fuentes del fichero mysqlws.php y mysqlwslib.js. Copiar ambos ficheros en el mismo servidor que tengamos mysql instalado. Por defecto el paquete supone que el directorio donde instalemos ‘mysqlws.php’ tiene un subdirectorio ‘js’ donde reside la librería ‘mysqlwslib.js’.

Configuración:Seguir las instrucciones que se encuentran en las cabeceras de los ficheros y que se resumen en dar los valores de nuestra instalación a la variables $host, $user, $pw, $db en el fichero ‘php’. Además habrá que indicar al fichero ‘js’ donde está el fichero ‘php’ fijando el valor de la variable ‘urlMysqlwsphp’.

Con esto termina la instalación. Para poder utilizar la librería desde nuestras páginas web habrá que poner un enlace en el fichero ‘html’:

<script src="miruta/mysqlwslib.js"></script>

A partir de ese momento disponemos de las siguientes funciones:

  • mysql_use(“nombre_basedatos”) : Selecciona la base de datos sobre la que se realizaran las siguientes consultas.
  • mysql_select_query(query) : Realiza una consulta tipo SELECT y devuelve un Array con el resultado. Hay que tener en cuenta que devuelve un Array de dos dimensiones, por lo que si el resultado es una sola fila estará en el indice [0] del resultado. Veamos un ejemplo:
    var arrayResult = mysql_select_query ("SELECT * FROM mitabla");
    for (i=0; i< arrayResult.length i++) {
        var fila = arrayResult[i];
        var columna = arrayResult[i][0];
    }
    
  • mysql_update_query(query) : Realiza una consulta del tipo UPDATE, INSERT, DELETE u otras. Devuelve un número entero correspondiente al número de filas afectadas por la última operación. Si el número es -1 se ha producido un error. Un cero en una operación INSERT o UPDATE normalmente indicará un error. Ejemplo de inserción de un registro:
    var n = mysql_update_query("INSERT INTO mitabla VALUES (null, 'Pepito', 'Ruiz')");
    if (n[0] != 1) {
       alert("Error");
    }
    
  • mysql_col_names( tablename): Devuelve un array con los nombres de las columnas de la tabla indicada.

Además de estas funciones que son las dedicadas al acceso a mysql, he dejado en la librería otras funciones que también utilizo en casi todos mis programas:

  • $(elementId) : Devuelve el elemento DOM correspondiente al id pasado.
  • setElementContent(element, content): Sustituye a la pareja de sentencias :
    element = document.getElementById(element);
    element.innerHTML = content;
    

    En el caso de la función se puede pasar el id del elemento buscado o una referencia al elemento propiamente dicho.

  • getDocHeight(): Devuelve la altura del documento.
  • setElementHeight(element, height): Ajusta la altura del elemneto indicado. El elemento se puede especificar por su id o por una referencia al elemento
  • getElementHeight(element): Devuelve la altura del elemento DOM indicado
  • getWindowHeight(): Devuelve la altura de pantalla disponible
  • getWindowWidth(): Devuelve la anchura de pantalla.
  • getTamanoVentana(): Devuelve un Array [ancho, alto] de la ventana.
  • createTableFromArray( arrayDatos, arrayCabeceras): Devuelve una cadena <table>...</table> con los datos de un array organizados en filas y columnas para añadir al elemento <div> que queramos y que nos muestre una tabla con los datso del array. El array con las cabeceras es opcional y se puede conseguir con la función 'mysql_col_names()'.
  • parseFechaUTC(cadFecha, cadHora): Devuelve un objeto javascript Date a partir de unas cadenas fecha y hora en formato mysql. La fecha y hora se supone que son UTC. Ejemplo:
    var dt = parseFechaUTC("2010-12-22", "12:30:00");
    
  • getCadFechaUTCFromJSDate( date): Devuelve una cadena en la forma "aaaa-mm-dd" con la fecha UTC correspondiente al objeto Date 'date'
  • getCadHoraUTCFromJSDate( date): Devuelve una cadena en la forma "hh-mm-ss" con la hora UTC correspondiente al objeto Date 'date'
  • intToString(numero, digitos): Devuelve una cadena con un entero ajustado al numero de digitos indicado, rellenando ceros por delante. Por ejemplo "01"

Espero que os sea de utilidad. Agradezco comentarios y bugs encontrados.

mysqlws.tar

mysqlws.zip



Santiago Higuera (27 Diciembre 2010)

La clase OpenLayer.Control.Panel sirve para agrupar varios controles tipo botón o pulsador.

Si no creamos un elemento ‘div’ en la página html para alojar el Panel, el programa le asignará uno y lo situará en la esquina superior izquierda del mapa. Para poder controlar la posición y el aspecto de nuestro Panel hay que crear un elemento ‘div’ en la página html. En el elemento ‘div’ hay que definir un ‘id‘ y una clase ‘class‘:

[sourcecode language="js"]

[/sourcecode]

Podemos situar el Panel dentro o fuera del mapa. La posición y aspecto del Panel la controlamos mediante clausulas de estilo CSS. En nuestro ejemplo hemos decidido situar el Panel en la parte superior y fuera del mapa. La definición de estilo para el Panel:

[sourcecode language="css"]
.miPanel {
position: relative;
left: 103px;
height: 38px;
width: 78px;
margin: 6px;
border: solid 2px blue;
background-color: #00d0ff;
}
[/sourcecode]

Para completar el proceso de creación del Panel habrá que llamar al constructor de la clase en el código Javascript. El constructor de la clase Panel admite un único parámetro que es un Object con las propiedades que queramos especificar al control. En nuestro caso debemos indicarle cual es el elemento ‘div’ asignado al Panel. Lo hacemos en dos pasos. Primero recuperamos el elemento ‘div’ con el método ‘OpenLayers.Util.getElement‘ y luego se lo pasamos al constructor del Panel:

[sourcecode language="js"]
// Cogemos una referencia al ‘div’ del panel
var el = OpenLayers.Util.getElement(‘panel0′);

// Creamos el panel0 pasandole la referencia del ‘div’
var panel = new OpenLayers.Control.Panel({ ‘div’ : el });
[/sourcecode]

Con esto queda completado el proceso de crear nuestro Panel para alojar otros controles.

A los paneles se les pueden añadir cualquiera de los controles predefinidos para hacer zoom, pan, dibujar features, etc. En este caso vamos a añadir dos botones de la clase genérica OpenLayers.Control.Button.

La clase OpenLayers.Control.Button ofrece funcionalidad para un botón alojado en un Panel.

Para crear un botón no es necesario crear ningún elemento ‘div’ dentro del código html de la página. El programa se encargará de hacerlo por nosotros. Nosotros lo que tenemos que hacer es indicarle el nombre de la clase ‘class‘ que define nuestros botones. A la cadena que le pasemos al constructor, por ejemplo ‘btn1‘, el programa le añade el sufijo ‘ItemActive‘, de modo que el nombre de la clase del botón queda ‘btn1ItemActive‘. Este será el nombre de clase que habrá que utilizar en la hoja de estilo para definir el aspecto de nuestro botón. En nuestro ejemplo hemos definido dos botones: ‘btn1‘ y ‘btn2‘. Los nombres de clase serán ‘btn1ItemActive‘ y ‘btn2ItemActive‘.

La clase Button tiene una propiedad llamada ‘trigger‘ (disparador) que apunta a una función que será llamada cada vez que se pulse el botón. Este es el segundo parámetro que es necesario pasarle al constructor y deberá ser el nombre de la función que queramos que se ejecute cuando pulsemos el botón.

Con estas consideraciones los constructores de nuestros dos botones quedarán:

[sourcecode language="js"]
btn1 = new OpenLayers.Control.Button({
displayClass:”btn1″,
trigger: btn1Click
});
btn2 = new OpenLayers.Control.Button({
displayClass:”btn2″,
trigger: btn2Click
});
[/sourcecode]

El primer parámetro es ‘displayClass‘, que como hemos indicado es el prefijo del nombre de clase del botón. El segundo parámetro es el método que se llamará al pulsar el botón.

[sourcecode language="js"]
// Función ‘trigger’ del boton 1
function btn1Click() {
var el = document.getElementById(‘mapa’);
el.innerHTML = “Botón 1″;
}
// Función ‘trigger’ del boton 2
function btn2Click() {
var el = document.getElementById(‘mapa’);
el.innerHTML = “Botón 2″;
}
[/sourcecode]

En cuanto a la definición del estilo de los botones hemos elegido la siguiente:

[sourcecode language="css"]
.btn1ItemInactive {
float: left; width: 32px; height:32px; margin: 2px;
border: solid 1px #333333;
border-bottom: solid 2px #333333;
border-right: solid 2px #333333;
background-color: #0069b4;
background-image: url(‘image1.gif’);
background-repeat: no-repeat;
background-position: center
}
.btn2ItemInactive {
float: left; width: 32px; height:32px; margin: 2px;
border: solid 1px #333333;
border-bottom: solid 2px #333333;
border-right: solid 2px #333333;
background-color: #0069b4;
background-image: url(‘movie.gif’);
background-repeat: no-repeat;
background-position: center
}
[/sourcecode]

Observese que se han utilizado los nombres de clase mencionados anteriormente para cada botón, usando la pseudo clase ‘hover’ para variar el color del fondo cuando el ratón sobrevuela el botón. Se ha definido para cada botón ‘float: left’ para que se vayan adosando de izquierda a derecha en lugar de apilarse de arriba a abajo. Además se ha especificado el tamaño y un borde más grueso abajo y a la derecha para dar sensación de volumen. Se ha situado una imagen de fondo del botón, centrada y sin repetición.

Creados los botones solo falta añadirlos al Panel y añadir el Panel al Map:

[sourcecode language="js"]
// Añadimos los botones al panel
panel.addControls([btn1, btn2]);

// Añadimos el panel al mapa
map.addControl(panel);
[/sourcecode]

Poniendo juntas todas las piezas, el resultado lo puedes ver en:

ejemploControlButton.html



Santiago Higuera (9 Octubre 2010)

Los controles se utilizan para interactuar con el mapa. Permiten hacer zoom, mover el mapa, conocer las coordenadas del cursor, dibujar features, etc

En OpenLayers V2.10 hay 40 clases de controles para utilizar con los mapas. De ellos, dos está desaconsejado su uso pues se van a suprimir en la próxima versión de OpenLayers, la versión 3.0. Los controles descatalogados son ‘MouseDefaults‘ y ‘MouseToolBar‘. De los 38 controles restantes, dos son nuevos de esta versión, ‘SLDSelect‘ y ‘WMTSGetFeatureInfo‘. El resto vienen de versiones anteriores, si bien el control ‘OpenLayers.Control.Panel‘ ha sufrido modificaciones en su funcionamiento respecto de anteriores versiones.

Todos los controles derivan de la clase ‘OpenLayers.Control‘, y todos los controles se añaden al objeto ‘OpenLayers.Map‘, directa o indirectamente. La clase ‘OpenLayers.Map‘ tiene una propiedad ‘controls‘ que guarda la lista de controles del mapa. Para añadir un control al mapa se puede hacer mediante el método ‘OpenLayers.Map.addControl()‘ o bien directamente en el constructor de ‘OpenLayers.Map‘.

El constructor de la clase OpenLayers.Map permite añadir controles en el momento de la creación del mapa. Si no se indica nada, el mapa añade los siguientes controles por defecto:

Esto es, si creamos el mapa con el siguiente constructor:

var map = new OpenLayers.Map("divMapa");

Automáticamente quedan añadidos al mapa los controles por defecto indicados.

Podemos crear un mapa sin ningún control de la siguiente manera:

var map = new OpenLayers.Map("divMapa", {controls: [] } );

Si lo que queremos es añadir una serie de controles elegidos por nosotros habría que invocar el constructor del mapa de la siguiente manera:

var map = new OpenLayers.Map("divMapa", {
    controls: [
        new OpenLayers.Control.PanZoom(),
        new OpenLayers.Control.Attribution()
    ] }
);

También podemos crear un mapa sin controles y añadirselos después:

var map = new OpenLayers.Map("divMapa", { controls: []});
var ctrlPanZoom = new OpenLayers.Control.PanZoom();
map.addControl(ctrlPanZoom);
var ctrlAttribution = new OpenLayers.Control.Attribution();
map.addControl(ctrlAttribution);

En ambos casos hemos creado un mapa con los controles ‘PanZoom‘ y ‘Attribution‘. Debemos cuidar siempre de añadir el control ‘Attribution‘ para mostrar correctamente los Attribution de los mapas que utilicemos.

En OpenLayers las definiciones de estilo por defecto de controles y otros elementos se declaran y definen en la hoja de estilo http://www.openlayers.org/api/theme/default/style.css. Podemos añadir un enlace a dicha hoja de estilo en nuestro código:

<link type="text/css" rel="stylesheet"
    href="http://www.openlayers.org/api/theme/default/style.css"/>

Si echamos un vistazo al fichero vemos que se definen propiedades de estilo para todo tipo de elementos que son faciles de identificar por su nombre de clase. También podemos personalizar la posición o el aspecto de los controles como se verá en capítulos posteriores

La lista de controles que podemos utilizar es la siguiente:

  • Controles generales
    • ArgParser
    • Attribution
    • Button
    • Graticule
    • KeyboardDefaults
    • LayerSwitcher
    • OverviewMap
    • Panel
    • PanPanel
    • PermaLink
    • SLDSelect (nuevo versión 2.10)
    • Snapping
    • Split
  • Zoom, Panning, Position
    • DragPan
    • MousePosition
    • Navigation
    • NavigationHistory
    • NavToolBar
    • Pan
    • PanZoom
    • PanZoomBar
    • ZoomBox
    • ZoomIn
    • ZoomPanel
    • ZoomOut
    • ZoomToMaxExtent
  • Features
    • EditingToolbar
    • DragFeature
    • DrawFeature
    • GetFeature
    • ModifyFeature
    • SelectFeature
    • TransformFeature
  • Medir
    • Measure
    • Scale
    • ScaleLine
  • Servicios de Mapas
    • WMSGetFeatureInfo
    • WMTSGetFeatureInfo (nuevo versión 2.10)

En próximos capítulos iremos explicando la utilización detallada de cada uno de estos controles.

WordPress guarda toda su información, incluido el contenido de los artículos, en una base de datos. En mi caso tengo instalado WordPress 3.0.1 utilizando la base de datos MySql proporcionada por el alojamiento.

Si queremos interactuar directamente con la base de datos debemos conocer el valor de ‘host‘, ‘user‘, ‘password‘, ‘database‘. (Estos datos son los mismos que hay que rellenar en el fichero ‘wp-config.php‘ durante el proceso de instalación de WordPress).

Conociendo estos valores se puede echar un vistazo con MySqlAdmin para ver como hace WordPress para guardar los artículos y todos los datos de mantenimiento del Blog.

Si así lo hacemos, veremos que en la versión 3.0.1 hay una tabla llamada ‘wp-posts‘ que es la que contiene el grueso de los datos relativos a los artículos (posts). En particular nos vamos a fijar en las columnas ‘ID’ y ‘post-content’. El ‘ID’ coincide con el número del artículo que aparece en los enlaces al mismo. Así si el enlace a un artículo es ‘http://www.ingemoral.es/index.php?p=1044‘, el ‘ID’ del artículo será 1044. La columna ‘post-content‘ almacena todo el contenido del artículo en formato html.

Hemos desarrollado un programa que lee de forma dinámica los artículos de la base de datos de WordPress a medida que se van solicitando.

El programa consta de cuatro ficheros:

  • manualOpenLayers.html : La página html
  • manualOpenLayers.js : Las funciones en javascript y AJAX
  • manualOpenLayers.css : La hoja de estilo del programa
  • testWordpressDb.php : La parte del servidor en php

La página ‘manualOpenLayers.html‘ organiza los paneles de la pantalla y muestra una lista de enlaces.

Hemos dividido la pantalla en ‘panelIzdo’ y ‘panelDcho’. Dentro del panel izquierdo tenemos un elemento ‘attribution’ y una lista de enlaces. En el panel derecho tenemos un elemento ‘titPanelDcho’, destinado a mostrar el título del artículo, y otro elemento ‘contentPanelDcho’ que es donde se muestra el contenido del artículo.

Cada uno de los enlaces guarda el ‘ID’ de un artículo. Cuando se activa el enlace, éste llama a la rutina javascript ‘doRequest( idpost)‘, pasándole como argumento el ‘ID’ del artículo solicitado. La rutina entonces realiza una llamada AJAX al programa ‘testWordpressDb.php‘ pasándole como argumento el ‘ID’ del post solicitado:

http://..../testWordpressDb.php?p=1024

El archivo php contiene las rutinas de acceso a mysql. Busca el articulo ‘ID’ y devuelve una página html con el contenido de la columna ‘post-content’, todo ello en formato texto.

La rutina javascript utiliza el texto recibido para rellenar el contenido html del elemento ‘contentPanelDcho‘.

Los listados de los tres ficheros son los siguientes:

manualOpenLayers.html

manualOpenLayers.css

manualOpenLayers.js

El listado de ‘testWordpressDb.php’ es el siguiente:


<?php
$host="midominio.miservidor.net"; // La url de acceso a mySql
$user="miUsuario"; // El usuario para conectarse a MySql
$pw="miPassword"; // Contraseña de acceso
$db="miBaseDeDatos"; // La base de datos sobre la que se hará el USE
$htmlpage= "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>testWordpressDb</title></head><body>";
$htfin="</body></html>";

// Extraer el parámetro con el id del post
if(isset($_GET['p'])) {
	$idpost = $_GET['p'];
	getPost($idpost);

} else {
	$htmlpage.="Artículo inexistente";
	$htmlpage.=$htfin;
	echo $htmlpage;
}
return;

function getPost($idpost) {
	GLOBAL $host, $user, $pw, $db, $htmlpage, $htfin;
	// Abrir la conexión con mysql
	$conn = opendb($host, $user, $pw, $db);
	if(!$conn) {
		$htmlpage = $htmlpage."Error de Conexión".$htfin;
		echo $htmlpage;
		return;
	} 

	// Realizar la consulta a la B.D.
	$query = "SELECT post_content FROM wp_posts WHERE ID=$idpost;";
	$result=mysql_query($query, $conn);

	if(!$result) {
		$htmlpage.="Resultado de la consulta nulo";
		$htmlpage.=$htfin;
		echo $htmlpage;
		closedb($conn);
		return;
	}
	$cad="";
	while($row=mysql_fetch_array($result, MYSQL_NUM)) {
		$cad=$cad.utf8_encode($row[0]);
	}

	mysql_free_result($result);
	$htmlpage = $htmlpage.$cad;
	$htmlpage.=$htfin;
	echo $htmlpage;

	// Cerrar la conexión
	closedb($conn);
}

function opendb($host, $user, $pw, $db) {
// opendb
// Establece conexión con el servidor $host y hace un USE de la base de datos $db
// Parametros:
//    $host
//    $user
//    $pw : password
//    $db : Base de datos sobre la que se hará el USE
// Devuelve:
//    Referencia a la conexión abierta o null si hay errores
//
	$conn = mysql_connect($host, $user, $pw);
	if(!$conn) {
		return null;
	}
	//echo "connected<br/>";
	$resp = mysql_select_db($db, $conn);
	if($resp != true) {
		return null;
	}
	//echo "used<br/>";
	return $conn;
}
function closedb($conn) {
// closedb()
// Cierra la conexión con la base de datos
// Parámetros:
//	   $conn Referencia al recurso de la conexión con la B.D.
// Devuelve
//	   void
	if(!$conn) {
		return;
	}
	mysql_close($conn);
}

?>

El ejemplo funcionando lo puedes ver en el siguiente enlace:

manualOpenLayers.html

Ten en cuenta que hay que reemplazar el valor de las variables globales $host, $user, $pw y $db con los valores correspondientes de tu instalación WordPress.

El ‘ID’ identifica un artículo, aunque el artículo no esté publicado y exista solo como borrador, lo que nos permite utilizar Wrodpress como editor y almacenador de unos artículos que luego publicamos via página Web



Santiago Higuera (26 Septiembre 2010)

© 2012 Descartes Suffusion theme by Sayontan Sinha