Para prescindir de plugins externos innecesarios, aquí verás cómo hacer tus propios widgets para insertar en tu página de WordPress o dentro de cualquier post.
Sólo tienes que saber algo de HTML y de javascript. Vamos a ello!
Contenido
Custom HTML
Si has visto algún otro post de este blog ya habrás visto la tabla de contenido de arriba, o la notificación de cookies en la barra lateral.
Ambos son elementos dinámicos que he programado con HTML y javascript y que puedes insertar en múltiples sitios de tu WordPress usando un bloque "Custom HTML".
Simplemente inserta este bloque y dentro podrás introducir tu código HTML personalizado y programable con javascript. Veamos unos ejemplos.
Notificación de cookies
La barra lateral de este blog muestra un mensaje de consentimiento de cookies, con un enlace a la política de privacidad.
Puede que hayas visto que al cambiar el idioma de la página, se cambia el contenido de dicho mensaje automáticamente.
Haz click derecho para inspeccionar la estructura de la página.
Para que funcione correctamente, imagina que el bloque Custom HTML que insertas es un iframe o una especie de página insertada; una sub-página dentro de nuestra página.
Editamos el contenido del Custom HTML como si de otra página se tratara, y podemos añadir libremente lo que queramos.
Para la notificación, solo quiero una línea de texto, a la que asigno la id "cookie-txt". Es bueno añadir toda la estructura HTML básica, aunque se puede prescindir de muchos elementos.
Ahora añado una función javascript que lea el idioma de la página y rellene esta línea en consecuencia.
Puedes hacer distintas pruebas usando la consola y el inspector del navegador, haciendo click derecho en la página.
Una forma rápida de obtener el idioma es leyendo la propiedad lang="es-ES" del elemento <html> de la página (o lang="en-GB" para inglés).
El resto es una condición:
Si se detecta "es-ES", definimos el mensaje en Español.
Si se detecta "en-GB", definimos el mensaje en Inglés.
El contenido del mensaje lo definimos mediante la propiedad innerHTML del elemento <p>, por lo que podemos darle cualquier formato HTML, como incrustarle un enlace o resaltar en negrita.
<script>
var lang=document.getElementsByTagName("html")[0].lang;
if(lang=="es-ES"){
document.getElementById("cookie-txt").innerHTML="🍪 <a href='https://theroamingworkshop.cloud/b/?page_id=1225' target='_blank'>Política</a> <b>anti-Cookies</b> aceptada al navegar.</p>";
}else if(lang=="en-GB"){
document.getElementById("cookie-txt").innerHTML="<b>🍪 anti-Cookies</b> <a href='https://theroamingworkshop.cloud/b/?page_id=3' target='_blank'>policy</a> accepted while browsing.";
}
</script>
Por lo que quedaría algo así:
El código completo del Custom HTML que muestra la notificación de cookies es este:
El bloque Custom HTML, en este caso, lo inserto como un elemento de la barra lateral:
Tabla de contenido
La tabla de contenido que aparece en cada post viene a ser más o menos lo mismo que lo anterior.
En primer lugar, defino la tabla dándole formato, y dejando el contenido vacío para rellenar luego con una función.
<div id="menu" style="padding:20px 20px 20px 20px; border-left:2px solid darkgrey;">
<p style="font-weight:bold;">Contenido</p>
</div>
En este caso, lo que haré es buscar los "headings" o títulos de cada apartado, en concreto los de etiqueta <h2>. Por ello, al redactar los posts debo usar siempre este tipo de encabezado (que es el habitual) si quiero que aparezca en la tabla.
Además, defino un ancla o html Anchor, que se asignará como "id", lo cual nos permitirá crear un enlace que nos lleve hasta dicho encabezado.
La función hará lo siguiente:
Buscar los elementos <h2> uno por uno. for (let i=0;i < window.document.getElementsByTagName("h2").length; i++) { element = window.document.getElementsByTagName("h2")[i]; ...
Tomar el texto que contiene. text = "▹ "+element.innerHTML;
Crear el nuevo elemento de tipo hiperenlace (<a>) que irá a la tabla de contenido, con el texto anterior. var newelement = document.createElement("a"); newelement.innerHTML=text;
Tomar la "id" del post y del encabezado para crear un enlace a dicho encabezado. var postid = window.document.getElementsByTagName("article")[0].id; var url = "https://theroamingworkshop.cloud/b/?p="+postid.substr(5,postid.length)+"#"+element.id;
Añadirlo todo en una línea al elemento de la tabla de contenido newelement.setAttribute("href", url); newelement.appendChild(document.createElement("br")); window.document.getElementById("menu").appendChild(newelement);
TIP! Añadiendo #id-de-la-sección al final de una URL te dirije a dicho apartado.
Por último, algunas páginas tardan un tiempo en cargar y no están todos los encabezados disponibles al inicio, por lo que meto todo el código anterior en una función, y la invoco con un tiempo de retardo. window.setTimeout(fillmenu,500);
El código del bloque completo sería el siguiente:
<div id="menu" style="padding:20px 20px 20px 20px; border-left:2px solid darkgrey;">
<p style="font-weight:bold;">Contenido</p>
</div>
<script>
var text;
var element;
function fillmenu(){
for (let i=0; i<window.document.getElementsByTagName("h2").length; i++){
element = window.document.getElementsByTagName("h2")[i];
text = "▹ "+element.innerHTML;
var newelement = document.createElement("a");
newelement.innerHTML=text;
var postid=window.document.getElementsByTagName("article")[0].id;
var url = "https://theroamingworkshop.cloud/b/?p="+postid.substr(5,postid.length)+"#"+element.id;
newelement.setAttribute("href", url);
newelement.appendChild(document.createElement("br"));
window.document.getElementById("menu").appendChild(newelement);
}
}
window.setTimeout(fillmenu,500);
</script>
TIP! Añade este bloque HTML a tus bloques reusables y lo podrás insertar en todos tus posts. Este bloque de TIP! es otro ejemplo.
Bloque de TIP!
TIP! Este bloque de TIP! es otro ejemplo. Tendrás que reconvertir a un bloque regular si quieres alterar el contenido solo en el bloque insertado
Aquí su código:
<p style="border-left:3px solid orange;padding-left:5px;font-size:14px;"><i><b>TIP! </b>Este bloque de <b>TIP!</b> es otro ejemplo. Tendrás que reconvertir a un bloque regular si quieres alterar el contenido <b>solo</b> en el bloque insertado</i></p>
Conclusión
Como verás, las posibilidades son realmente ilimitadas así que queda todo a expensas de tu imaginación.
Se creativo y diseña tus propios widgets, ya verás lo bien complementan tu blog!
Como siempre, dudas o comentarios al Twitter 🐦 ¡Hasta otra!
(el bloque de Twitter también es un reutilizable 👀 )
Hay muchas explicaciones tediosas en la red de cómo clonar un SO Linux a un nuevo dispositivo, pero me topé con esta genial herramienta on mi Raspberry que reduce todo a unos pocos minutos y sin necesidad apenas de teclear.
Es el programa «SD Card Copier» que puedes usar de manera regular para hacer copias de seguridad de tu SO, o trasladar tu sistema de archivos a un dispositivo de mayor almacenamiento, como es mi caso.
Contenido
1. Requisitos y configuración.
Quiero mover mi Raspbian OS de mi actual tarjeta SD a una mayor y más rápida, por lo que debo poder acceder a ambas tarjetas simultáneamente. Por ello, he seguido esta configuración:
Raspberry Pi 4B.
Tarjeta SD de 32Gb en la ranura de la Raspberry con Raspbian 10 Buster.
Tarjeta SD rápida de 128Gb (nueva y vacía) conectada mediante adaptador USB a la Raspberry.
Opcionalmente, puedes transferir todo el sistema de archivos a un tercer USB para recuperar los ficheros en caso de fallo.
Además, instalaremos piclone si no tenemos el programa SD Card Copier por defecto en nuestro SO.
sudo apt-get update
sudo apt-get install piclone
[No comprobado!] Piclone debería funcionar en otras distribuciones de Linux, si tienes la habilidad suficiente de montar todas las dependencias que requiere. En ese caso, puedes seguir las instrucciones que se detallan en su propio github:
¿Te preguntabas de dónde he sacado la foto de fondo del blog?
No es de internet ni de ningún telescopio. Es del genial programa Stellarium, el planetario de código abierto de precisión astronómica y realismo sin igual.
Contenido
Requisitos
Stellarium está disponible para Windows, Mac y Linux, así como en una versión web igualmente impresionante, pero sin todo su potencial de edición que ofrecen las versiones de escritorio gracias a numerosos plugins que aporta la comunidad.
Según nos indican en su página web, los requisitos mínimos son los siguientes:
Linux/Unix; Windows 7 o superior; Mac OS X 10.12.0 o superior
Tarjeta gráfica con 3D y soporte para OpenGL 3.0 y GLSL 1.3 o OpenGL ES 2.0
512 MiB RAM
600 MiB de espacio en disco
Teclado
Ratón, touchpad o similar
Y los recomendados:
Sistema operativo de 64 bits
Linux/Unix; Windows 7 o superior; Mac OS X 10.12.0 o superior
Tarjeta gráfica con 3D y soporte para OpenGL 3.3 o superior
1 GiB RAM o más
1.5 GiB de espacio en disco
Teclado
Ratón, touchpad o similar
Ambiente moderadamente oscuro
Vamos, que funciona casi en cualquier dispositivo y lo podemos descargar desde su página web mediante los botones del panel superior.
Configuración inicial
Al inicio se sincroniza automáticamente la posición de todos los cuerpos celestes con la hora de nuestro PC y se actualizarán en tiempo real.
Mediante el menú inferior (o sus [atajos] ) podremos activar o desactivar distintos elementos de la vista. Yo te recomiendo que juegues un poco con ellas y lo configures como prefieras:
Lineas de constelaciones [C].
Etiquetas de constelación [V].
Dibujos de constelaciones [R].
Cuadrícula ecuatorial [E].
Cuadrícula azimutal [Z].
Suelo [G].
Atmósfera [A].
Puntos cardinales [Q].
Objetos de Espacio profundo [D].
Etiquetas de planetas [Alt+P].
Alternar entre montura ecuatorial o azimutal [Ctrl+M].
Centrar sobre el objeto seleccionado [Espacio].
Modo nocturno [Ctrl+N].
Modo pantalla completa [F11].
Mostrar exoplanetas [Ctrl+Alt+E].
Mostrar lluvia de meteoros [Ctrl+Shift+M].
Mostrar diálogo de búsqueda de lluvia de meteoros [Ctrl+Alt+M].
Posiciones de satélites [Ctrl+Z].
Disminuir velocidad del tiempo [J].
Establecer ritmo normal de tiempo [N].
Establecer tiempo en ahora [8].
Aumentar velocidad del tiempo [L].
Salir [Ctrl+Q].
Por otro lado, mediante el menú lateral tenemos las siguientes opciones:
Ventana de ubicación [F6]. Aquí podemos especificar la localización de nuestra vista, pudiendo ser un lugar de la tierra o de algún otro planeta de la lista.
Ventana fecha/hora [F5]. Podemos elegir cualquier fecha del pasado o del futuro ya que las órbitas de los objetos están perfectamente definidas desde hace milenios.
Ventana de opciones de cielo y vista [F4]. Nos permite calibrar la visibilidad de los objetos, la proyección o la imagen de paisaje, entre otras.
Ventana de búsqueda [F3]. Nos localizará un objeto del espacio por su nombre.
Ventana de configuración [F2]. Muestra los ajustes del programa como idioma, fecha del equipo o el uso de extras o scripts.
Ventana de cálculo astronómicos [F10]. Muestra los detalles de los cálculos realizados por el programa, como las posiciones de los cuerpos, o eventos que ocurran hoy.
Ventana de ayuda [F1].
Usos
Podemos desactivar la atmósfera [A] para curiosear los cuerpos del espacio pulsando con el botón izquierdo del ratón, lo que nos dará información sobre el cuerpo seleccionado. Si pulsamos [Espacio], la vista lo seguirá.
También podemos activar las líneas [C] y etiquetas de las constelaciones [V], mostrar las lluvias de meteoros [Ctrl+Shift+M] y adelantar el tiempo hasta que anochezca [F5] o [L]. Así podremos averiguar si habrá lluvia de estrellas esta noche (o en cualquier otra fecha) y conocer su orientación.
Ahora, en agosto de 2022, estamos a punto de llegar al máximo de actividad de las Perseidas, que se producirá el 13 de agosto según estos cálculos realizados desde la España peninsular, y las podremos ver desplazándose desde el Norte hacia el Noreste.
O simplemente juega con las muchas posibilidades que da el programa y obtén una impresionante imagen de fondo como la que conforma el encabezado de este blog.
¿Se te ocurren otras posibilidades para este genial programa? ¿Algún truco de configuración o algún script que merezca la pena compartir? Dejálo caer en Twitter 🐦 ¡Hasta pronto!
ACTUALIZACIÓN 2023! Se elimina el servicio WMS horario y se actualiza la versión diaria a V2. Version WMS actualizada a 1.3.0
Estas semanas está de moda comentar el calentamiento que está sufriendo el Mar Mediterráneo y he encontrado muy pocos mapas que me permita pinchar fácilmente sobre él para saber la temperatura que pretende indicar.
Así que he hecho el mío propio:
Vamos a buscar un WMS con la información en formato ráster,
A replicar su leyenda mediante el uso de lienzos <canvas> html,
Y obtener el valor del pixel seleccionado que corresponda con la leyenda.
Contenido
Los datos
Existen muchas y muy liosas fuentes de información.
Puertos del Estado: Mi primer intento fue acudir a Puertos del Estado, pero lo único bueno que encontré es que usan Leaflet.. Tienen un visor en tiempo real, pero es muy complicado acceder a los datos para hacer algo con ellos (aunque ya veremos cómo ).
Copernicus: "Copernicus es el Programa de Observación de la Tierra de la Unión Europea", como bien dicen en su página web, y aglutinan la mayoría de información geográfica y medioambiental producida por los paises miembros de la UE. En su sección marítima, encontramos datos de Temperatura Superficial del Mar (SST: Sea Surface Temperature) obtenidas por satélite y otros sensores de diferentes organismos europeos.
Global Ocean OSTIA Diurnal Skin Sea Surface Temperature
Después de probar todos, el más completo es el mapa global generado por la MetOffice (la AEMET inglesa).
Según indican, se muestra la media horaria en un mapa sin huecos, usando datos de campo, satelitales y de medidores infra-rojo.
El mapa base
Voy a crear un mapa base como ya hemos visto en otros post.
La descargo en formato geoJSON y, para que sea fácil insertarla, la convierto en una variable llamada "countries" en un nuevo fichero CNTR_RG_01M_2020_4326.js insertándole este encabezado (ten en cuenta que hay que cerrar el objeto JSON con "]}"para que se lea correctamente).
A este enlace le añadimos las siguientes funciones de GeoServer "?service=WMS&request=GetCapabilities" lo cual nos dará la información disponible en dicho servicio WMS, como capas, leyendas, estilos, unidades, etc.
Para saber que opciones debemos introducir, consultamos el fichero de metadatos, en concreto las etiquetas:
<Layer queryable="1"><Name> nos dará el nombre de las capas que introduciremos en la propiedad "layers:"
<Style><Name> nos dará los nombres de los distintos estilos disponibles para la representación del ráster, que podemos especificar en la propiedad "styles:".
<LegenURL> nos dará el enlace a la leyenda que emplea ese estilo.
<Dimension> nos dará unidades que podemos consultar en el servicio WMS. En nuestro caso la unidad es temporal, ya que podemos variar la fecha de los datos representados. Lo voy a dejar comentado, por lo que tomará la última fecha disponible, pero luego lo utilizaremos para personalizar la consulta.
SST raster data
Por último, vamos a añadirle la leyenda al mapa para tener una referencia visual.
La insertamos como imagen en el <body> y añadimos el CSS al <style>:
Como verás, así es muy complicado intentar averiguar la temperatura de un punto concreto.
Replicar la leyenda para consultar los datos
Para poder conocer la temperatura correspondiente a un color concreto, deberíamos conocer la posición de dicho color en la leyenda y calcular su valor proporcional a los valores extremos (310kPa= 36.85ºC y 210kPa=-3.15ºC).
El problema es que por política CORS, no podemos hacer una consulta sobre la imagen, que está fuera del dominio de nuestra aplicación. Por otro lado, si añadimos la imagen a nuestro dominio, esta tendrá resolución determinada y puede restringir la precisión de los colores consultados.
Por ello, para replicar la leyenda añado un elemento de lienzo o <canvas> junto a la leyenda.
Y mediante javascript, ayudándonos del HTML Color Picker, vamos definiendo las distintas paradas de un relleno tipo "gradiente" que reemplazará a nuestra leyenda (la añado como función para poder usarla de forma dinámica).
function grad(){
//Generamos la leyenda en el canvas 'gradientC'
var ctx=document.getElementById("gradientC").getContext('2d');
//Definimos un gradiente lineal
var grd=ctx.createLinearGradient(0,150,0,0);
//Calibrar las paradas del gradiente tomando muestras de la imagen
//Descomentar la imagen que va junto al canvas en el html
//Usar HTML color picker: https://www.w3schools.com/colors/colors_picker.asp
grd.addColorStop(0, "rgb(0, 0, 146)"); //0 -> -3.15
grd.addColorStop(0.09, "rgb(0, 0, 247)"); //1
grd.addColorStop(0.185, "rgb(1, 61, 255)"); //2
grd.addColorStop(0.26, "rgb(0, 146, 254)"); //3
grd.addColorStop(0.3075, "rgb(0, 183, 255)"); //4
grd.addColorStop(0.375, "rgb(3, 251, 252)"); //5
grd.addColorStop(0.5, "rgb(111, 255, 144)"); //6 -> 20.0
grd.addColorStop(0.575, "rgb(191, 255, 62)"); //7
grd.addColorStop(0.64, "rgb(255, 255, 30)"); //8
grd.addColorStop(0.74, "rgb(255, 162, 1)"); //9
grd.addColorStop(0.805, "rgb(255, 83, 0)"); //10
grd.addColorStop(0.90, "rgb(252, 4, 1)"); //11
grd.addColorStop(1, "rgb(144, 0, 0)"); //12 -> 36.85
//añadir el gradiente al canvas
ctx.fillStyle = grd;
ctx.fillRect(0,0,255,255);
}
//ejecutamos la funcion del gradiente al inicio
grad();
SST raster data
Crear selector de pixel y calculador de temperatura
Una vez tenemos una leyenda propia, vamos a crear un elemento que muestre el color del pixel seleccionado, así como la temperatura obtenida.
Para poder obtener el color del pixel seleccionado, éste también lo insertamos en un lienzo en el body:
<canvas id="temp">
<img id="pixel" src="" ALT="CLICK PARA OBTENER TEMPERATURA"></img>
</canvas>
<div id="tempTxt">PINCHA SOBRE EL MAR PARA CONOCER SU TEMPERATURA</div>
Y damos un formato adecuado a los nuevos elementos en el <style>:
onMapClick() para obtener el pixel seleccionado y trasladarlo al recuadro inferior. Esto lo hacemos con una petición GET al servicio WMS con las coordenadas correspondientes al pixel donde hacemos click. Es importante tener en cuenta el sistema de referencia que use el mapa del servicio WMS, que en nuestro caso no es el habitual, sino que es EPSG:3857, para la conversión de unidades.
//Añadimos función al hacer click en el mapa
map.addEventListener('click', onMapClick);
function onMapClick(e) {
//ejecutamos la función grad con cada click
grad();
//Obtenemos las coordenadas del pinto seleccionado
var latlngStr = '(' + e.latlng.lat.toFixed(3) + ', ' + e.latlng.lng.toFixed(3) + ')';
//console.log(latlngStr);
//Definir el CRS para enviar la consulta al WMS
const proj = L.CRS.EPSG3857;
//const proj = L.CRS.EPSG4326;
//Definimos los límites del mapa que pediremos al WMS para que sea aproximadamente de 1 pixel
var BBOX=((proj.project(e.latlng).x)-10)+","+((proj.project(e.latlng).y)-10)+","+((proj.project(e.latlng).x)+10)+","+((proj.project(e.latlng).y)+10);
//console.log(BBOX);
//Restablecemos la imagen en cada click
var tTxt=document.getElementById("tempTxt");
var pix= document.getElementById("pixel");
var ctx=document.getElementById("temp").getContext("2d");
//pix.src="";
ctx.fillStyle="lightgrey";
ctx.fillRect(0,0,300,300);
//Realizamos la petición del pixel seleccionado
var xPix= new XMLHttpRequest();
xPix.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200) {
pix.src=URL+WMS+BBOX;
pix.onload=function(){
ctx.drawImage(pix,0,0,300,300);
tTxt.innerHTML="INTERPRETANDO LEYENDA...";
//Interpretamos el pixel según la leyenda
leyenda();
}
pix.crossOrigin="anonymous";
}
};
xPix.open("GET", URL+WMS+BBOX);
xPix.send();
tTxt.innerHTML="CARGANDO TEMPERATURA...";
}
leyenda() calcula la temperatura que corresponde a dicho pixel seleccionado según la leyenda que hemos creado anteriormente. Muestra el valor de la temperatura en el recuadro inferior y también se indica en la leyenda con una franja blanca. El algoritmo de cálculo consiste en recorrer la leyenda pixel a pixel (verticalmente) y comparar la diferencia de los valores rgb(x,y,z) de la leyenda con los valores rgb del pixel seleccionado. Iremos guardando el valor que vaya obteniendo una menor diferencia hasta llegar al final, por lo que habrá casos en que la solución no sea 100% exacta. No es la mejor manera pero es rápida (de entender y de ejecutar) y bastante efectiva.
function leyenda(){
var ctx=document.getElementById("temp").getContext("2d");
var tTxt=document.getElementById("tempTxt");
//obtenemos el valor RGB del pixel seleccionado
var RGB=ctx.getImageData(5,5,1,-1).data;
//console.log(ctx.getImageData(10,10,1,-1).data);
var key=document.getElementById("gradientC").getContext("2d");
var max=150;
var min=1000;//la máxima diferencia sólo puede ser de 255x3=765
var dif="";
var val="";
//recorremos el gradiente de la leyenda pixel a pixel para obtener el valor de temperatura
for(var p=1;p<=max;p++){
//obtenemos el valor actual
var temp=key.getImageData(1,p,1,-1).data;
//console.log(temp);
//comparamos con el seleccionado y obtenemos la diferencia total
dif=Math.abs(parseInt(temp[0])-parseInt(RGB[0]))+Math.abs(parseInt(temp[1])-parseInt(RGB[1]))+Math.abs(parseInt(temp[2])-parseInt(RGB[2]));
if(dif<min){
min=dif;
val=p;
//console.log("Obj:"+RGB[0]+","+RGB[1]+","+RGB[2]+"\nTemp:"+temp[0]+","+temp[1]+","+temp[2]+"\nDif:"+dif);
}
}
var T=36.85-(val*40/max);
T=T.toFixed(2);
//pintamos una línea de referencia en la leyenda
key.fillStyle="white";
key.fillRect(0,val,255,1);
//definimos la temperatura en el texto
//si el color da gris, hemos pinchado en la tierra
//console.log("T= "+T);
if(RGB[0]==211&RGB[1]==211&RGB[2]==211){
tTxt.innerHTML="PINCHA SOBRE EL MAR PARA CONOCER SU TEMPERATURA";
}else if(typeof T == "undefined"){
tTxt.innerHTML="¡ERROR!<BR>PRUEBA OTRO PUNTO DEL MAR.";
}else{
tTxt.innerHTML="TEMPERATURA APROXIMADA: <br><br>"+T+" ºC";
}
//console.log(key.getImageData(1,150,1,-1).data);
}
Además, omitimos la imagen original de la leyenda y añadimos nuestros propios rótulos.
Por último, añadimos un controlador de fecha en el body:
y definir los valores máximos y mínimos permitidos
//Obtener última hora de actualizacion del mapa
var timeInp=document.getElementById("timeInp");
var t;
var maxT;
var minT;
var xTime = new XMLHttpRequest();
xTime.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200) {
//convertimos el XML según https://www.w3schools.com/xml/xml_parser.asp
var xmlDoc=this.responseXML;
t=xmlDoc.children[0].children[1].children[2].children[12].children[1].children[5].attributes[4].value;
//Lo convertimos en un objeto fecha quitando los segundos
t=new Date(t);
t=t.toISOString().substring(0,t.toISOString().length-8);
//Lo pasamos al selector y lo establecemos como máximo
timeInp.max=t;
timeInp.value=t;
maxT=new Date(t);
//también establecemos el minimo
t=xmlDoc.children[0].children[1].children[2].children[12].children[1].children[5].innerHTML.trim();
t=t.substring(0,16);
timeInp.min=t;
minT=new Date(t);
}
};
xTime.open("GET", URL+"?service=WMS&request=GetCapabilities");
xTime.send();
//Selector de fecha para WMS
timeInp.addEventListener("change", function(){
t=new Date(timeInp.value.toString());
t.setHours(12-t.getTimezoneOffset()/60);
t=t.toISOString().substring(0,t.toISOString().length-8);
timeInp.value=t;
t=new Date(timeInp.value);
t.setHours(12-t.getTimezoneOffset()/60);
//si estamos en el rango de datos..
if(t>=minT && t<=maxT){
t=t.toISOString();
//actualziamos el mapa
base.setParams({
time: t,
styles: "boxfill/rainbow",
},0);
}else{//mostramos error
alert("La fecha introducida está fuera de rango.");
}
});
//funcion de reinicio de fecha
function reiniT(){
timeInp.value=maxT.toISOString().substring(0,maxT.toISOString().length-13)+"23:30";
}
Resultado
Con todo esto, nos quedará algo así, que puedes ver a pantalla completa aquí:
Si te ha gustado, tienes dudas, o alguna idea para mejorar este mapa, deja tus inquietudes en Twitter 🐦
La Agencia Estatal de Meteorología española (AEMET) cuenta con una API de datos abiertos con la que podemos acceder a la mayoría de datos que publican en su web.
API de AEMET OpenData
De esta forma, cualquier usuario puede crear apps muy sencillas sólo con la información que necesita y sin tener que acceder a su web.
En mi caso, quiero mostrar de forma intuitiva los datos de las estaciones en un mapa web que pueda ver desde cualquier dispositivo con internet como mi móvil. Aquí un anticipo para que sigas leyendo:
Añadimos los enlaces a las librerías de Leaflet dentro de las etiquetas <head>:
También añado las propiedades <meta> charset(1) y viewport(2) para (1)interpretar correctamente los caracteres especiales como tildes y, (2) ajustar correctamente la ventana a dispositivos móviles.
Como verás, añado border:0 y margin:0 al estilo del <body>. Esto ajusta el mapa perfectamente a la ventana, sin ningún tipo de espacio en blanco.
Height:100vh y width:100vw ajustarán el mapa al 100% del tamaño de la ventana (view height y view width). El z-index nos servirá para ordenar los objetos y que no se tapen entre ellos.
Ya podemos generar el mapa mediante javascript. Pasamos al bloque <script>
Con L.map definimos el mapa y su vista inicial (que he centrado en Madrid).
Con L.tileLayer.wms añadimos el servicio WMS del IGN para obtener un mapa base "online". Puedes encontrar las URL completas de cada servicio consultando los metadatos que acompañan a cada producto.
Además, es habitual que los WMS cuenten con varias capas, por lo que debemos definir una. Podemos obtener el listado de capas usando la función GetCapabilities de los wms. En nuestro caso usamos la <Layer> con <Name> "IGNBaseTodo-gris" que identificamos aquí:
Ahora añadimos el plugin de descarga y representación de datos de AEMET leafMET que encontrarás en mi github.
Podemos descargar el fichero leafMET.js y añadirlo como script local, o podemos enlazarlo directamente desde esta web. Dentro de las etiquetas <head> añadimos lo siguiente:
Ahora, para ver la aplicación con un sólo click desde el móvil, debemos copiar el contenido de leafMET.js dentro de las etiquetas <script> del documento .html
Así, tendremos un único archivo con todo lo necesario para correr nuestra webapp. He añadido las etiquetas <title> y "icon" en <head> para mostrar un título de página y que el acceso directo herede el icono que definamos.
Página de bloqueo al acceder a Spotify desde Firefox ESR o Chromium
Pensarías (yo al menos) que podías enchufar tu Raspberry a un monitor y poner un poco de música de fondo en Spotify con el navegador, como siempre, desde open.spotify.com. Bueno, lo más probable es que te haya salido el mensaje de arriba, hayas buscado innumerables soluciones en la web, hasta que has llegado aquí. Encantado de ayudar!
El aumento de la seguridad en Spotify solo lo hace disponible en versión web para navegadores Chrome, Firefox y Edge en dispositivos de 64bits, dificultando el hacking o el streaming fraudulento sin cuenta premium.
Contenido
Con Premium.
Si tienes suscripción Premium, puedes tomar un atajo y simplemente usar una de las apps que te dan acceso desde tu Raspberry como Raspicast (que sincroniza desde el smartphone), Raspotify o spotify-qt, y te darán acceso a tu música con muy poca configuración.
spotify-qt de snapcraft.io
Sin Premium.
Para los que adoramos escuchar anuncios (y no pagar), el camino no es tan arduo. Solo debemos instalar la librería Widevine:
sudo apt-get install libwidevinecdm0
A continuación, reiniciamos el sistema y accedemos a open.spotify.com mediante Chromium.
Iniciamos sesión en nuestra cuenta, y deberíamos estar dentro de Spotify con su interfaz habitual, y sin el mensaje que nos salía anteriormente.
Por último, podemos instalar un acceso directo a Spotify en Chromium mediante el botón que aparece en la barra de navegación. Y listo! A disfrutar de Spotify en tu Raspberry!
Spotify web en Chromium Browser para Raspberry Pi
Cualquier duda o comentario, envíamela por Twitter 🐦! Hasta pronto!
<!-- Load Lealeft Control Custom by yigityuce --> <script src="https://theroamingworkshop.cloud/b/wp-content/uploads/2021/08/Leaflet-Control-Custom.txt"></script>
<!-- FONT AWESOME CDN --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<style>
</style>
<body> <div id="mapid3" style="height:600px;"></div> <! fixed size set as a style property > </body>
Leaflet JS es uno de mis mayores descubrimientos de los últimos años. Es una de las librerías de mapas web más poderosas que encontrarás, compitiendo con la API de Google, ESRI o Mapbox gracias a su gran comunidad y los geniales plugins que van desarrollando.
El sofware libre se impone de nuevo 🤟
(Encuentra el código del mapa anterior en este post, con algunos otros ejemplos de Leaflet)
Contenido
1. Requisitos.
Todo lo que necesitas es lo siguiente:
Un navegador web con compatibilidad html y javascript (cualquier navegador moderno como Firefox, Vivaldi, Opera, Chrome, Edge, etc servirá).
Un editor de texto (como el bloc de notas mismo).
[OPCIONAL] Un servidor web para alojar la página y hacerla accesible a través de internet. En todo caso, podrás abrir el fichero localmente con algunas funciones restringidas.
2. Integrar Leaflet en cualquier página.
Al tratarse de una librería es muy simple usarla en un entorno web. De hecho verás ejemplos incrustados directamente a lo largo del post.
Para empezar, crea un nuevo fichero de texto y cambia su extensión a .html.
Luego añade la estructura básica de un documento HTML, como la que encontrarás en w3schools, web que siempre recomiendo:
Esta opción no se verá afectada por la conexión de red, o cambios en el fichero online, a la vez que nos permitirá realizar cambios personalizados en nuestro fichero local.
3. Añadir un mapa al cuerpo del HTML
Ubicado en html <body>
Leaflet añade sus componentes dentro del elemento <div> que asignemos dentro del <body> para acomodar nuestro diseño. Es necesario asignar una "id" a este <div> para que Leaflet lo identifique posteriormente. Voy a usar "mapid" para este ejemplo:
<div id="mapid" style="height:500px;"></div>
El mapa se verá afectado por las propiedades CSS que definamos para la etiqueta #mapid. Esto modifica cómo el elemento encaja y se ajusta a la página.
Como ejemplo, voy a modificar el contorno para que sea redondeado en lugar de rectangular, definiendo un radio de 30px al borde. Añado estos cambios dentro de las etiquetas CSS <style>. Puedes comentar o eliminar estas líneas para ver la diferencia.
<style>
#mapid{border-radius: 30px;}
</style>
Definir el mapa en javascript
Vamos a añadir el objeto del mapa en sí. Para ello usamos las funciones de la librería Leaflet (llamadas mediante L.). Añadimos esta función dentro de las etiquetas de <script> ya que hacen uso de javascript.
Definir el objeto de mapa. Añadimos el mapa con la función "L.map" y hacemos referencia al elemento "mapid". Luego definimos la vista y zoom iniciales con "L.setView".
Voy a centrar la vista aproximadamente en Miami (haciendo una búsqueda en internet puedes encontrar una latitud y longitud aproximadas: 25.75, -80.2). El nivel de zoom lo defino en 12 para que esté bastante cerca. Valores altos harán más zoom y valores bajos harán menos zoom.
var map = L.map('mapid').setView([25.75, -80.2], 12);
Definir la capa base. Los mapas web hacen uso de imágenes teseladas que se van cargando de forma dinámica a medida que nos movemos por el mapa. Podemos usar la función "L.tileLayer" con cualquiera los servicios referidos en este post, incluyendo Open Street Maps (OSM), Google Maps, y ESRI. Usaremos OSM para este ejemplo:
Por último, vamos a añadir un marcador, una funcionalidad básica que querrás en muchos mapas. Definiremos el texto dentro de "bindPopup", pudiendo formatearlo con etiquetas HTML. La función "openPopup" muestra la etiqueta del marcador directamente al inicio.
//marcador
var marker = L.marker([25.77, -80.13]).addTo(map);
//etiqueta
marker.bindPopup("<b>I'm in</b><br>Miami Beach!").openPopup();
Resultado final.
El siguiente rectángulo es un bloque HTML insertado en wordpress con todo el código que hemos ido desarrollando. Debería mostrar el mapa base OSM centrado en Miami con un marcador en Miami Beach y con el borde redondeado.
El código exacto que contiene ese bloque HTML es el siguiente:
TIP! Puedes copiar y pegar este código en un fichero de texto con extensión .html y abrirlo en tu navegador.
Y con esto.. a jugar! No te pierdas la documentación y los plugins en la web de Leaflet. Hay cantidad de características increíbles para añadir a tu mapa.
Aquí te indico las más interesantes que he probado: