Yin y Yang con path
El yin y yang son dos conceptos del taoísmo, cuyo significado y origen es en este momento irrelevante. Sin embargo nos interesa saber como dibujar una representación gráfica de estos. Lo que queremos conseguir es algo así:
A continuación dibujaremos esta imagen utilizando el elemento <path> y el comando arco elíptico ( elliptical Arc ) A
o a
como instrucción de control ( commands ). También utilizaremos el elemento <circle>.
Un poco de JavaScript
Para crear dinámicamente un nuevo elemento en SVG
utilizamos el método createElementNS()
donde NS viene de Namespaces ( espacio de nombres ). No olvidemos que SVG define gráficos en formato XML.
Para establecer, determinar o modificar el valor de un atributo podemos utilizar el método setAttributeNS()
o setAttribute()
.
Los elementos creados dinámicamente y dotados con atributos ( o no ) pueden ser insertados en el documento utilizando uno de los métodos appendChild()
o insertBefore()
, utilizando el nodo padre ( parent node ) como argumento. Veamos un ejemplo.
Empezamos dibujando un círculo blanco ( fill="#fff"
) con un borde fino negro ( stroke="#000"
).
Definimos algunas variables necesarias: las coordenadas cx
e cy
del centro y el radio R
del yin y yang:
var cx = 125, cy = 100;
var R = 80;
Utilizando el método createElementNS, creamos un nuevo elemento <circle>
y lo almacenamos dentro de una variable ( var circulo
).
var circulo = document.createElementNS("http://www.w3.org/2000/svg","circle");
Utilizamos el método setAttributeNS para establecer los atributos necesarios del nuevo elemento:
( cx
, cy
, r
, fill
y stroke
).
circulo.setAttributeNS(null,"cx", cx);
circulo.setAttributeNS(null,"cy", cy);
etc . . .
Al final adjuntamos el elemento circulo
al contenedor
SVG.
var contenedor = document.getElementById("contenedor");
contenedor.appendChild(circulo);
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.
var cx = 125, cy = 100;
var R = 80;
// crea un circulo blanco con borde negro
var circulo = document.createElementNS("http:\/\/www.w3.org/2000/svg","circle");
circulo.setAttributeNS(null,"cx", cx);
circulo.setAttributeNS(null,"cy", cy);
circulo.setAttributeNS(null,"r", R);
circulo.setAttributeNS(null,"fill", "#fff");
circulo.setAttributeNS(null,"stroke","#000");
var contenedor = document.getElementById("contenedor");
contenedor.appendChild(circulo);
El Yin es la parte negra del yin y yang, y para dibujarla necesitamos juntar tres semicírculos ( arcos elípticos ) en un trazado ( <path>
).
Exactamente como en el caso del <circle>
, creamos un nuevo elemento <path>
utilizando el método createElementNS()
, y después, utilizando setAttributeNS
establecemos el único atributo necesario: d
, el atributo que define el trazado a dibujar.
Calcular el parámetro d
para Yin
1. Empezamos moviendo el lápiz en el punto cx,cy
( el centro del círculo ). Para esto el atributo d
de <path>
empieza con el comando M
( moveto ) seguido del valor de las variables cx
y cy
.
var dYin = "M"+cx+", "+cy+" A"+R/2+ ","+R/2 +"0 0,1"+ (cx+R) +","+cy
2. A continuación dibujamos hacia la derecha y en el sentido del reloj un semicírculo cuyo diámetro es igual al radio de yin y yang, y por lo tanto su radio r = R/2
. El comando A
comunica al <path>
que el trazado que queremos dibujar es un arco eliptico.
var dYin = "M"+cx+", "+cy+" A"+R/2 + ","+ R/2 +"0 0,1"+ (cx+R) +","+cy
No queremos girar la elipse ( x-axis-rotation = 0
),
var dYin = "M"+cx+", "+cy+" A"+R/2+ ","+R/2 +"0 0,1"+ (cx+R) +","+cy
y ya que se trata de un semicírculo el valor del parámetro large-arc-flag
puede ser tanto 0
como 1
.
var dYin = "M"+cx+", "+cy+" A"+R/2+ ","+R/2 +"0 0,1"+ (cx+R) +","+cy
Dibujamos el arco en el sentido del reloj ( sweep-flag = 1
).
var dYin = "M"+cx+", "+cy+" A"+R/2+ ","+R/2 +"0 0,1"+ (cx+R) +","+cy
El arco acaba en el punto de coordinadas cx + R, cy
.
var dYin = "M"+cx+", "+cy+" A"+R/2+ ","+R/2 +"0 0,1"+ (cx+R) +","+cy
3. Desde este punto ( cx + R, cy
) dibujamos otro arco de círculo, también en el sentido del reloj ( sweep-flag = 1
) , pero hacia
la izquierda y abajo. El radio de este segundo arco es R
. El arco acaba en el punto de coordinadas cx - R, cy
.
var dYin =
"M" + cx + ", " + cy+
" A"+ R/2 +","+ R/2 +" 0 0,1 "+ (cx+R) +","+cy+
" A"+ R +","+ R +" 0 0,1 -"+ (cx-R) +","+cy;
4. Desde el punto donde se acabó el arco anterior ( cx - R, cy
) dibujamos otro arco de circulo cuyo diámetro es igual al radio de yin y yang ( r = R/2
).
Esta vez dibujamos hacia abajo y la derecha, o sea en el sentido contrario del reloj ( sweep-flag = 0
).
El arco acaba en el centro de la imagen.
var dYin ="M" + cx + ", " + cy+
" A"+ R/2 +","+ R/2 +" 0 0,1 "+ (cx+R) +","+cy+
" A"+ R +","+ R +" 0 0,1 "+ (cx-R) +","+cy+
" A"+ R/2 +","+ R/2 +" 0 0,0 "+cx+","+cy
En el JavaScript
creamos con createElementNS()
un nuevo elemento <path>
.
Utilizando el metodo setAttributeNS()
atribuimos al nuevo elemento <path>
el atributo d
( el valor del atributo d = dYin
).
Al final insertamos el nuevo elemento <path>
en el documento utilizando el método appendChild()
.
Ya tenemos el yin.
Finalmente, creamos también los dos círculos rojos.
var cx = 125, cy = 100;
var R = 80;
var r = R/10; // el radio de los circulos rojos
var dYin = "M" + cx + ", " + cy+
" A"+ R/2 +","+ R/2 +" 0 0,1 "+ (cx+R) +","+cy+
" A"+ R +","+ R +" 0 0,1 "+ (cx-R) +","+cy+
" A"+ R/2 +","+ R/2 +" 0 0,0 "+cx+","+cy;
var contenedorSVG = document.getElementById("contenedorSVG");
// declara el espacio de nombre
var svgNS = "http:\/\/www.w3.org/2000/svg"
// crea un circulo blanco con borde negro
var circulo=document.createElementNS(svgNS,"circle");
circulo.setAttributeNS(null,"cx", cx);
circulo.setAttributeNS(null,"cy", cy);
circulo.setAttributeNS(null,"r", R);
circulo.setAttributeNS(null,"fill", "#fff");
circulo.setAttributeNS(null,"stroke","#000");
contenedorSVG.appendChild(circulo);
// crea el yin
var Yin=document.createElementNS(svgNS,"path");
Yin.setAttributeNS(null,"d", dYin);
contenedorSVG.appendChild(Yin);
// crea un circulo rojo encima de yin
var circleYin = document.createElementNS(svgNS,"circle");
circleYin.setAttributeNS(null,"cx", cx-R/2);
circleYin.setAttributeNS(null,"cy", cy);
circleYin.setAttributeNS(null,"r", r);
circleYin.setAttributeNS(null,"fill", "#f00");
contenedorSVG.appendChild(circleYin);
// crea un circulo rojo encima de yang
var circleYang = document.createElementNS(svgNS,"circle");
circleYang.setAttributeNS(null,"cx", cx+R/2);
circleYang.setAttributeNS(null,"cy", cy);
circleYang.setAttributeNS(null,"r", r);
circleYang.setAttributeNS(null,"fill", "#f00");
contenedorSVG.appendChild(circleYang);