Añadir un rótulo flotante
Esta es una continuación de gráfico de columnas (1)
Para añadir rótulos flotantes, con el nombre del navegador y el porcentaje de usuarios, necesitamos poder detectar la la posición del ratón encima del <canvas>
La función dibujar columnas
Siempre que el código se repite de manera monótona es mejor escribir una función.
La función dibujarColumnas()
toma tres argumentos:
o
de offset – el desplazamiento en x, propiedad
– en este caso el año, y nav
– el navegador. Después de dibujar las columnas la función dibujarColumnas()
llama la función rotulador()
.
function dibujarColumnas(o, propiedad, nav) {
var H = (oData[propiedad][nav] * 60) / 15;
ctx.fillStyle = oColores[nav];
ctx.beginPath();
ctx.rect(o, 270 - H, 20, H);
ctx.fill();
//llama la funcion rotulador
rotulador(o, propiedad, nav, H)
}
La función rotulador
La lógica utilizada:
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 rectángulo
(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 (enganchada al ratón)
Observación: Para que el método isPointInPath()
funcione, tendremos que volver a esbozar el rectángulo.
function rotulador(o, propiedad, nav, H) {
if (typeof window.addEventListener === "function") {
canvas.addEventListener("mousemove", function(evt) {
var mousePos = oMousePos(canvas, evt);
// esboza de nuevo el rectángulo
ctx.beginPath();
ctx.rect(o, 270 - H, 20, H);
if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
rotulo.innerHTML = nav + " - " + propiedad + "
" + oData[propiedad][nav] + "%";
rotulo.style.display = "block";
rotulo.style.top = mousePos.y + "px";
rotulo.style.left = mousePos.x + 10 + "px";
return false;
}
}, false);
}
}
La función oMousePos
Puede ver la descripción de esta función a la posición 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)
}
}
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 = {
2008:{"IE":"54.7", "Firefox":"36.4"},
2009:{"IE":"44.8", "Firefox":"45.5"},
2010:{"IE":"36.2", "Firefox":"46.3"},
2011:{"IE":"26.6", "Firefox":"42.8"},
2012:{"IE":"20.1", "Firefox":"37.2"},
2013:{"IE":"14.3", "Firefox":"30.2"},
2014:{"IE":"10.2", "Firefox":"26.9"} ,
};
var oColores = {"IE":"#6495ED", "Firefox":"#FF8C00"};
function dibujarColumnas(o, propiedad, nav) {
var H = (oData[propiedad][nav] * 60) / 15;
ctx.fillStyle = oColores[nav];
ctx.beginPath();
ctx.rect(o, 270 - H, 20, H);
ctx.fill();
//llama la funcion rotulador
rotulador(o, propiedad, nav, H)
}
function rotulador(o, propiedad, nav, H) {
if (typeof window.addEventListener === "function") {
canvas.addEventListener("mousemove", function(evt) {
var mousePos = oMousePos(canvas, evt);
ctx.beginPath();
ctx.rect(o, 270 - H, 20, H);
if (ctx.isPointInPath(mousePos.x, mousePos.y)) {
rotulo.innerHTML = nav + " - " + propiedad + "
" + oData[propiedad][nav] + "%";
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 del rotulo "on mousemove" encima del canvas
var rotulo = document.getElementById("rotulo");
canvas.addEventListener("mousemove", function(evt) {
rotulo.innerHTML = "";
rotulo.style.display = "none";
}, false);
//////////////////////////////////////////////////////
// construye la cuadricula
// dibuja el eje vertical
ctx.strokeStyle = "#ccc";
ctx.lineWidth = 1;
ctx.save();
ctx.translate(0.5, 0.5);
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.5, 0.5);
ctx.beginPath();
ctx.moveTo(40, y);
ctx.lineTo(475, y);
ctx.stroke();
ctx.restore();
//el porcentaje disminuye en un 15%
porcentaje -= 15;
}
// construye las columnas
ctx.textAlign = "left";
ctx.textBaseline = "top";
var o = 60;
for (var propiedad in oData) {
ctx.fillStyle = "blue";
ctx.fillText(propiedad, o, 275);
dibujarColumnas(o, propiedad, "IE")
dibujarColumnas(o + 20, propiedad, "Firefox")
o += 60;
}
}
}