I just saw Stack Overflow's invitation in Spanish to participate in the New Year's contest for the best questions and answers tagged algorithms . And since Valentine's Day is approaching, I would like to collect algorithms to draw hearts in CSS, on canvas, in SVG or whatever you think.
Update
@Trauma comments:
Ok, the contest is fine, a prize is a prize and such, but... shouldn't it be a good question in itself? Because as it is... it leaves a lot to be desired
This comment made me think that I would have to add some code to my question so here I go:
The algorithm that I use to draw a heart is quite versatile since I can use it in CSS, in canvas and in SVG:
First I am creating an array of points
function corazon(r, paso) {
let puntos = [];
for (var a = 0; a < 2 * Math.PI; a += paso) {
let p = {};
p.x = cx + 16 * r * (Math.sin(a) * Math.sin(a) * Math.sin(a));
p.y =
cy -
13 * r * Math.cos(a) +
5 * r * Math.cos(2 * a) +
2 * r * Math.cos(3 * a) +
1 * r * Math.cos(4 * a);
puntos.push(p);
}
return puntos;
}
I found this formula here Draw a parametric heart-shaped curve in C#
The function function corazon()
returns an array of points and I'm going to use these points to draw a heart using the HTML5 canvas, SVG and finally CSS and the propertybox-shadow
on canvas
// inicia el canvas
const c = document.getElementById("canv");
const ctx = c.getContext("2d");
const cw = (c.width = 200);
const ch = (c.height = 200);
const cx = cw / 2,
cy = ch / 2;
// define el grosor de línea
ctx.lineWidth = 4;
// define el color de línea
ctx.strokeStyle = "crimson";
// el algoritmo del corazón
function corazon(r, paso) {
let puntos = [];
for (var a = 0; a < 2 * Math.PI; a += paso) {
let p = {};
p.x = cx + 16 * r * (Math.sin(a) * Math.sin(a) * Math.sin(a));
p.y =
cy -
13 * r * Math.cos(a) +
5 * r * Math.cos(2 * a) +
2 * r * Math.cos(3 * a) +
1 * r * Math.cos(4 * a);
puntos.push(p);
}
return puntos;
}
function dibujarCorazonEnCanvas() {
// crea un array vacío para guardar los puntos
let puntos = corazon(5, 0.05);
// empieza el trazado
ctx.beginPath();
// mueve el puntero al primer punto del array
ctx.moveTo(puntos[0].x, puntos[0].y);
// dibuja el corazon
puntos.forEach(p => {
ctx.lineTo(p.x, p.y);
});
// cierra el trazado
ctx.closePath();
// dibuja el corazón
ctx.stroke();
}
dibujarCorazonEnCanvas();
canvas{
border: 1px solid #d9d9d9;
}
<canvas id='canv'></canvas>
in SVG
// el centro del lienzo SVG
const cx = 100,cy = 100;
function corazon(r, paso) {
let puntos = [];
for (var a = 0; a < 2 * Math.PI; a += paso) {
let p = {};
p.x = cx + 16 * r * (Math.sin(a) * Math.sin(a) * Math.sin(a));
p.y =
cy -
13 * r * Math.cos(a) +
5 * r * Math.cos(2 * a) +
2 * r * Math.cos(3 * a) +
1 * r * Math.cos(4 * a);
puntos.push(p);
}
return puntos;
}
function dibujarCorazonEnSVG() {
// crea el array de los puntos
let puntos = corazon(5, 0.05);
// crea una cadena de texto para el atributo d de un trazado path
let d = `M${puntos[0].x},${puntos[0].y}L`;
puntos.forEach(p => {
d += `${p.x},${p.y} `;
});
// establece el valor del atributo d
corazonSVG.setAttributeNS(null, "d", d);
}
dibujarCorazonEnSVG();
svg{
border: 1px solid #d9d9d9;
}
path {
fill: none;
stroke: crimson;
stroke-width: 4px;
}
<svg id="svg" viewBox = "0 0 200 200" width="200">
<path id="corazonSVG" d="" />
</svg>
in css
I'm going to use the same algorithm to draw a heart using box-shadow
. I am going to use JavaScript to calculate the value of box-shadow
.
// crea una nueva hoja de estilos y la agrega al head
const s = document.createElement("style");
document.head.appendChild(s);
// el centro del div
const cx = 100,cy = 100;
// el algoritmo del corazón
function corazon(r, paso) {
let puntos = [];
for (var a = 0; a < 2 * Math.PI; a += paso) {
let p = {};
p.x = cx + 16 * r * (Math.sin(a) * Math.sin(a) * Math.sin(a));
p.y =
cy -
13 * r * Math.cos(a) +
5 * r * Math.cos(2 * a) +
2 * r * Math.cos(3 * a) +
1 * r * Math.cos(4 * a);
puntos.push(p);
}
return puntos;
}
function dibujarCorazonBoxShadow() {
// crea el array de los puntos
let puntos = corazon(5, 0.01);
// un array par los fragmentos de reglas css para box-shadow
let reglas = [];
// para cada punto en el array
puntos.forEach(p => {
reglas.push(`${p.x}px ${p.y}px 0px 1px crimson`);
});
// construye el valor de box-shadow utilizando la propiedad textContent de la nueva hoja de estilo
s.textContent = "div::before{box-shadow:";
s.textContent += reglas.join();
s.textContent += ";}";
}
dibujarCorazonBoxShadow();
div {
border: 1px solid #d9d9d9;
width: 200px;
height: 200px;
position: relative;
}
div::before {
content: "";
width: 1px;
height: 1px;
border-radius: 50%;
position: absolute;
top: 0px;
left: 0px;
}
<div></div>
How to draw a heart explained with primitives, Greetings
In R there are several ways that you can see here , the one that convinces me the most is the one that uses a particular parametric equation to build a "cardioid":
Explanation:
t <- seq(0, 2*pi, by=0.1)
we generate a sequence of numbers that go from0
2 timespi
in steps of 0.1x
ey
generamos estos valores que representarán los puntos externos de la formaplot(x, y, type="l")
vamos dibujando líneas a partir de cada pareja de puntosx
,y
. Conpolygon(x, y, col="hotpink")
creamos un polígono con la forma dada por los puntos y lo rellenamos con color.Otra opción es el path con Bezier Curve de Ricardo Cabello en uno de sus demos de como crear shapes con THREE.js.
Aquí un demo que hice usando esa figura agregándole algo de extrude para darle volúmen y multiplicándola:
Dejo mi aporte de un corazón con brillo en SVG jeje
no es un algoritmo como tal, solo una forma de dibujar un corazón con gradient.
https://codepen.io/memoadian/pen/vvMZOK
Dear old Codepen
https://codepen.io/stellina91/pen/grIHf
https://codepen.io/kunalvarma05/pen/mJbBNY
https://codepen.io/mindstorm/pen/aZZvKq
https://codepen.io/tameraydin/pen/bAfws
https://codepen.io/vivinantony/pen/gbENBB
Example source:
Agrego el código logo. Lo generé automáticamente usando una librería mía que convierte un path svg a comandos logo.
Esta es la imagen svg que utilicé, tal cual como la bajé de flaticon:
Esta es la misma imagen en png
Este es el código en python que utilizo para convertir el path svg a logo. Genero dos scripts, el primero es para MSWLogo y el segundo para otros intérpretes
Este es el script generado para MSWLogo
Este es el código generado para otros intérpretes
En la primera parte de los scripts se incluyen funciones generales y al final se incluyen los comandos que realizan el dibujo en sí
Este es el resultado de ejecutar el segundo script en https://www.calormen.com/jslogo/
Acá explico como funciona la biblioteca http://lopezezequiel.com/svgpath2logo/
Acá esta el repo https://github.com/lopezezequiel/SvgPath2Logo
Corazon en HTML CSS
corazon que late en mouse hover !
A la clase
Corazon
se le da una medida teniendo en cuenta el siguiente dato :el margen es a eleccion, en este caso lo use mas que nada para centrarlo.
a este punto creamos 2 rectangulos, aprovechando el
:before
y el:after
, a estos les agregamos el radius a los angulos superiores, que tienen que tener un radius que tiene que ser la mitad del width (no funciona con el 50%).el width de los rectangulos es la mitad del
width
de la clase corazon. mientras alheight
se le saca, mas o menos un 5% de la altura de la clase.despues se rotean gracias al
transform: rotate()
nuestrosbefore
yafter
uno de45deg
y el otro de-45deg
. recordar que elafter
, que en este caso esta girado de-45deg
, tiene que tener la propriedadleft
con un valor equivalente a su width.Le agregamos tambien el
box-shadow
para hacer mas atractiva nuestra figura, aca es a gusto proprio.y le agregamos una animacion en
hover
que aumente su medida, en los porcentajes :0% 20% 40% y 100%
.espero que les guste !!
Una forma de dibujar un corazón via css:
1. An algorithm to use in SVG and Canvas
This is an algorithm that Anne Tudor uses in some pens. I have adapted this algorithm for use in SVG and canvas:
2. Another way to draw a heart in CSS
In this case I use two elements
div
with rounded edges. This creates two ovals that I am turning to the right and to the left. You can change the value of the variable--h
to generate hearts of various sizes.