Añadir un rótulo flotante

facebook-svg gplus-svg twitter-svg

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; } } }