Añadir un rótulo flotante
Esta es una continuación de gráficos de líneas (2)
La función oMousePos
Puede ver la descripción de esta función a la posición del ratón. Lo que hay que saber es que devuelve un objeto con las coordenadas del ratón.
function oMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return { // devuelve un objeto
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
};
}
La función rotulador
Cuando el ratón pasa por encima del <canvas>
la función rotulador llama la función oMousePos()
que detecta la posición del ratón y devuelve un objeto con las coordenadas x e y de este.
Si el ratón ( cuyas coordenadas son mousePos.x
y mousePos.y
) esta encima del pequeño círculo
if (ctx.isPointInPath(mousePos.x, mousePos.y)){...}
la función rotulador()
:
- escribe el rotulo
- hace visible el rotulo ( rotulo.style.display="block";
)
- define la posición del rotulo ( enganchado al ratón )
Observación: Para que el método isPointInPath() funcione, tenemos que volver a esbozar el pequeño círculo.
function rotulador(o, nav, ano) {
if (typeof window.addEventListener === "function") {
canvas.addEventListener("mousemove", function(evt) {
var mousePos = oMousePos(canvas, evt);
ctx.beginPath();
// esboza de nuevo el pequeño círculo
ctx.arc(o, 270 - (oData[nav][ano] * 60) / 15, 5, 0, 2 * Math.PI);
if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
rotulo.innerHTML = nav + " - " + ano + "
" + oData[nav][ano] + "%";
rotulo.style.display = "block";
rotulo.style.top = mousePos.y + "px";
rotulo.style.left = mousePos.x + 10 + "px";
return false;
}
}, false);
}
}
También habrá que declarar la variable var rotulo
y establecer algunas características por defecto de este cuando el ratón pase por encima.
var rotulo = document.getElementById("rotulo");
canvas.addEventListener("mousemove", function(evt) {
rotulo.innerHTML = "";
rotulo.style.display = "none";
}, false);
Poniendolo todo junto
var canvas = document.getElementById("lienzo");
if (canvas && canvas.getContext) {
var ctx = canvas.getContext("2d");
if (ctx) {
var oData = {
"IE": {"2008":"54.7","2009":"44.8", "2010":"36.2", "2011":"26.6", "2012":"20.1", "2013":"14.3", "2014":"10.2", "color":"#6495ED"},
"Firefox":{"2008":"36.4","2009":"45.5", "2010":"46.3", "2011":"42.8", "2012":"37.2", "2013":"30.2", "2014":"26.9", "color":"#FF8C00"},
"Chrome": {"2008":"0", "2009":"3.9", "2010":"10.8", "2011":"23.8", "2012":"35.3", "2013":"48.4", "2014":"55.7", "color":"#FFD700"},
"Safari": {"2008":"1.9", "2009":"3.0", "2010":"3.7", "2011":"4.0", "2012":"4.3", "2013":"4.2", "2014":"3.9", "color":"#32CD32"},
"Opera": {"2008":"1.4", "2009":"2.3", "2010":"2.2", "2011":"2.5", "2012":"2.4", "2013":"1.9", "2014":"1.8", "color":"#DC143C"}
};
function rotulador(o, nav, ano) {
if (typeof window.addEventListener === "function") {
canvas.addEventListener("mousemove", function(evt) {
var mousePos = oMousePos(canvas, evt);
ctx.beginPath();
// esboza de nuevo el pequeño círculo
ctx.arc(o, 270 - (oData[nav][ano] * 60) / 15, 5, 0, 2 * Math.PI);
if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
rotulo.innerHTML = nav + " - " + ano + "
" + oData[nav][ano] + "%";
rotulo.style.display = "block";
rotulo.style.top = mousePos.y + "px";
rotulo.style.left = mousePos.x + 10 + "px";
return false;
}
}, false);
}
}
function oMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return { // devuelve un objeto
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
};
}
// características por defecto de rotulo on mousemove encima del canvas
var rotulo = document.getElementById("rotulo");
canvas.addEventListener("mousemove", function(evt) {
rotulo.innerHTML = "";
rotulo.style.display = "none";
}, false);
function laLeyenda() {
// las coordenadas de la esquina derecha arriba de la leyenda
var ly = 160;
var lx = 500;
ctx.textBaseline = "top";
ctx.textAlign = "left";
ctx.font = "12px Verdana";
for (var nav in oData) {
ctx.beginPath();
// el color que representa el navegador
ctx.fillStyle = oData[nav]["color"];
// la casilla
ctx.fillRect(lx, ly, 15, 15);
ctx.beginPath();
ctx.fillStyle = "blue";
// el nombre del navegador
ctx.fillText(nav, lx + 25, ly);
// calcula el valor de ly para la siguiente línea
ly += 23;
}
}
// construye la cuadricula
// dibuja el eje vertical
ctx.strokeStyle = "#ccc";
ctx.lineWidth = 1;
ctx.save();
ctx.translate(0.5, 0);
ctx.beginPath();
ctx.moveTo(45, 25);
ctx.lineTo(45, 275);
ctx.stroke();
ctx.restore();
// define el estilo de texto
ctx.font = "12px Verdana";
ctx.fillStyle = "blue";
ctx.textAlign = "right";
ctx.textBaseline = "middle";
// el porcentaje máximo
var porcentaje = 60;
// cada 60px
for (var y = 30; y < 275; y += 60) {
// dibuja el texto
ctx.fillText(porcentaje + "%", 40, y);
//dibuja una línea horizontal
ctx.save();
ctx.translate(0, 0.5);
ctx.beginPath();
ctx.moveTo(40, y);
ctx.lineTo(475, y);
ctx.stroke();
ctx.restore();
//el porcentaje disminuye en un 15%
porcentaje -= 15;
}
// define el estilo de texto
ctx.textAlign = "center";
ctx.textBaseline = "top";
// los anos
// empezamos a dibujar a 60px del margen izquierdo
var o = 80;
for (var i = 2008; i <= 2014; i++) {
ctx.fillStyle = "blue";
ctx.fillText(i, o, 275);
o += 60;
}
// GRAFICO
ctx.lineWidth = 2;
for (var nav in oData) {
ctx.beginPath();
ctx.strokeStyle = oData[nav]["color"];
ctx.fillStyle = oData[nav]["color"];
ctx.moveTo(80, 270 - (oData[nav][i] * 60) / 15);
var o = 80;
// para cada propiedad en el objeto oData
for (var i = 2008; i <= 2014; i++) {
ctx.lineTo(o, 270 - (oData[nav][i] * 60) / 15);
ctx.stroke();
ctx.beginPath();
ctx.arc(o, 270 - (oData[nav][i] * 60) / 15, 3, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
rotulador(o, nav, i); // i = ano
ctx.moveTo(o, 270 - (oData[nav][i] * 60) / 15);
o += 60;
}
}
// llama la función laLeyenda();
laLeyenda();
}
}
Al pasar por encima de los "nodos" aparece un rotulo con el nombre del navegador, el año y el porcentaje correspondiente de usuarios.