Gráficos circulares (2)
Añadir una amimación con <set>
Además de dibujar los sectores circulares, queremos añadir una animación muy sencilla: cada vez que pasamos con el ratón por encima de uno de los sectores circulares, queremos que aparezca, como una sombra, un arco de círculo del mismo color, pero con una opacidad de 40%.
Para esto dibujamos un trazado <path id="sombra". . .
cuyos atributos stroke-opacity="0.4"
y  stroke-width="0"
.
<path id="sombra" d="M119, 54 A100,100 0 0, 1250,150" fill="none" stroke="#FCCA03" stroke-opacity="0.4" stroke-width="0" ></path>
Ya que la grosor de línea stroke-width="0"
, el trazado será prácticamente invisible.
Importante: tanto el trazado que dibuja el "gajo" como el trazado que dibuja la "sombra" tienen una identificación ( id
) para poder referenciarlos después, utilizando los atributos begin
y end
de <set> .
<path id= "gajo" d="M150, 150 L119,54 A100,100 0 0, 1 250,150 z". . . <path id= "sombra" d="M119,54 A100,100 0 0, 1 250,150". . .
Dentro del elemento <path id="sombra"
aparece anidado un elemento <set> que hace que la grosor de línea ( attributeName = "stroke-width"
) cambie a 15px ( to="15"
) cada vez que pasamos con el ratón por encima ( mouseenter
). La animación acaba cuando el ratón se sale ( mouseleave
) fuera del gajo o de la sombra.
begin=Â "gajo.mouseenter; sombra.mouseenter;" end=Â "gajo.mouseleave; sombra.mouseleave;"Â >
A continuación escribiremos las funciones necesarias para conseguir este efecto.
La función dSombra
Muy parecida a la función dGajo
, la función dSombra
calcula el parámetro d
de <path>
para dibujar un arco de círculo entre los puntos ap
y af
.
function dSombra(ap,af){ var Xap = coords(ap).x; var Yap = coords(ap).y; var Xaf = coords(af).x; var Yaf = coords(af).y; var parametro_d = "M" + Xap + ", " + Yap+ " A"+r+","+r+" 0 0, 1"+Xaf+","+Yaf; return parametro_d; }
La función nuevaSombra
Crea un nuevo elemento <path>
y establece los atributos necesarios para dibujar la "sombra". En el caso de id utiliza la variable i
del bucle for
para atribuir una identificación única a cada arco de círculo que dibujamos:
nuevaSombra.setAttributeNS( null, "id", "sombra"+i ).
Después de adjuntar ( append ) el nuevo elemento al DOM  como hijo del lienzo SVG.
lienzoSVG.appendChild( nuevaSombra );
creamos un nuevo elemento <set>
y lo dotamos con los atributos necesarios.
Finalmente adjuntamos ( append ) el nuevo elemento al DOM, como hijo de nuevaSombra
.
function nuevaSombra(ap,af,color, i ){
var nuevaSombra=document.createElementNS("http:\/\/www.w3.org/2000/svg","path");
nuevaSombra.setAttributeNS(null,"id", "sombra"+i);
nuevaSombra.setAttributeNS(null,"d", dSombra(ap,af));
nuevaSombra.setAttributeNS(null,"fill", "none");
nuevaSombra.setAttributeNS(null,"stroke", color);
nuevaSombra.setAttributeNS(null,"stroke-opacity", .4);
nuevaSombra.setAttributeNS(null,"stroke-width", 0);
lienzoSVG.appendChild(nuevaSombra);
var sombraSet = document.createElementNS("http:\/\/www.w3.org/2000/svg","set");
sombraSet.setAttributeNS(null,"attributeName", "stroke-width");
sombraSet.setAttributeNS(null,"attributeType", "XML");
sombraSet.setAttributeNS(null,"to", 15);
sombraSet.setAttributeNS(null,"begin", "gajo"+i+".mouseover; sombra"+i+".mouseover");
sombraSet.setAttributeNS(null,"end", "gajo"+i+".mouseleave; sombra"+i+".mouseleave");
nuevaSombra.appendChild(sombraSet);
}
La función nuevoGajo
Modificamos ligeramente la función nuevoGajo
añadiendo otro atributo: id
, que exactamente como en el caso de nuevaSombra
utiliza la variable i
del bucle for
para generar una identificación única.
function nuevoGajo (ap,af,color,i){ var nuevoGajo=document.createElementNS ("http:\/\/www.w3.org/2000/svg","path"); nuevoGajo.setAttributeNS (null,"id", "gajo"+i); nuevoGajo.setAttributeNS (null,"d", dGajo (ap,af)); . . . . . }
Veamos como queda
Ahora cada vez que pasamos con el ratón por encima de uno de los sectores circulares ( "gajo"+i+".mouseover;
),o por encima de la "sombra" ( sombra"+i+".mouseover;
) aparece, como una sombra, un arco de círculo del mismo color, pero con una opacidad de 40%.
<svg id = "lienzoSVG" width="260" height="250"></svg>
var lienzoSVG = document.getElementById("lienzoSVG");
var cx = 130;
var cy = 120;
var r = 100;
var oGrafico = [
{nombre:"vitamina A", porcentaje:"40",color:"#0140CA"},
{nombre:"vitamina B", porcentaje:"12",color:"#DD1812"},
{nombre:"vitamina C", porcentaje:"6",color:"#16A6FE"},
{nombre:"vitamina D", porcentaje:"17",color:"#6ab150"},
{nombre:"vitamina E", porcentaje:"25",color:"#FCCA03"}
];
function coords( a ){
var arad = ( Math.PI / 180 ) * a;
var coords = {
"x" : cx + r * Math.cos( arad ),
"y" : cy + r * Math.sin( arad )
};
return coords;
}
function dGajo(ap,af){
var Xap = coords(ap).x;
var Yap = coords(ap).y;
var Xaf = coords(af).x;
var Yaf = coords(af).y;
var parametro_d = "M" + cx + ", " + cy+
" L"+Xap+","+Yap+
" A"+r+","+r+" 0 0, 1 "+Xaf+","+Yaf+
" z";
return parametro_d;
}
function dSombra(ap,af){
var Xap = coords(ap).x;
var Yap = coords(ap).y;
var Xaf = coords(af).x;
var Yaf = coords(af).y;
var parametro_d = "M" + Xap + ", " + Yap+
" A"+r+","+r+" 0 0, 1"+Xaf+","+Yaf;
return parametro_d;
}
function nuevaSombra(ap,af,color,i){
var nuevaSombra=document.createElementNS("http:\/\/www.w3.org/2000/svg","path");
nuevaSombra.setAttributeNS(null,"id", "sombra"+i);
nuevaSombra.setAttributeNS(null,"d", dSombra(ap,af));
nuevaSombra.setAttributeNS(null,"fill", "none");
nuevaSombra.setAttributeNS(null,"stroke", color);
nuevaSombra.setAttributeNS(null,"stroke-opacity", .4);
nuevaSombra.setAttributeNS(null,"stroke-width", 0);
lienzoSVG.appendChild(nuevaSombra);
var sombraSet = document.createElementNS("http:\/\/www.w3.org/2000/svg","set");
sombraSet.setAttributeNS(null,"attributeName", "stroke-width");
sombraSet.setAttributeNS(null,"attributeType", "XML");
sombraSet.setAttributeNS(null,"to", 15);
sombraSet.setAttributeNS(null,"begin", "gajo"+i+".mouseover; sombra"+i+".mouseover");
sombraSet.setAttributeNS(null,"end", "gajo"+i+".mouseleave; sombra"+i+".mouseleave");
nuevaSombra.appendChild(sombraSet);
}
function nuevoGajo(ap,af,color,i){
var nuevoGajo=document.createElementNS("http:\/\/www.w3.org/2000/svg","path");
nuevoGajo.setAttributeNS(null,"id", "gajo"+i);
nuevoGajo.setAttributeNS(null,"d", dGajo(ap,af));
nuevoGajo.setAttributeNS(null,"fill", color);
nuevoGajo.setAttributeNS(null,"stroke", "#fff");
nuevoGajo.setAttributeNS(null,"stroke-width", "2");
lienzoSVG.appendChild(nuevoGajo);
}
var ap = Array(); // angulos de partida
var af = Array(); // angulos finales
for( var i=0; i < oGrafico.length; i++ ){
var porcentaje = oGrafico[ i ].porcentaje;
var color = oGrafico[ i ].color;
// calcula el valor del ángulo
af[i] = ((porcentaje*360)/100);
if( i>0 ){
af[ i ] += af[ i-1 ]
ap[ i ] = af[ i-1 ];
} else { ap[ i ] = 0; }
nuevoGajo(ap[ i ],af[ i ],color,i);
nuevaSombra(ap[ i ],af[ i ],color,i);
}
No te olvides: siempre que sea posible, pon el JavaScript
dentro del <body>
, justo antes de su cierre: los estilos arriba, los scripts al fondo.
A continuación añadiremos una leyenda.