Amor + lienzo = corazón



¡Buen dia amigos!

El 14 de febrero es el Día de San Valentín o el Día de San Valentín en el patio.

Todo el mundo lo sabe (¿qué, alguien no lo sabe?).

Sin embargo, no todos saben (creo que no hay muchos de ellos en Habré) que el 14 de febrero de 1946, se demostró al mundo científico y a todos los interesados ​​la primera computadora electrónica realmente en funcionamiento ENIAC I (Integrador y calculador numérico eléctrico) y, por lo tanto, a todos los interesados, el 14 de febrero también es el Día de la Computadora.

El amor es un sentimiento maravilloso. Como dijo Hemingway, si dos se aman, esto no puede terminar bien. Solo una broma, amigos.

La programación de JavaScript también es algo genial.

¿Qué se te viene a la mente cuando dices "amor"? Por supuesto, el corazón. ¿Cómo hacer un corazón en JS? Por supuesto usando lienzo. Por cierto, mencionar el lienzo como HTML5 Canvas siempre me divirtió, porque desde html solo hay una etiqueta (elemento, si lo desea), el resto es JS, y cuando se trata de proyectos más o menos serios (interesantes), lejos de ser simples JS.



Tengo un corazón curioso en los contenedores. Y hoy decidí compartirlo contigo.

El código no es mío, aquí está su autor . Y aquí hay un artículo con los detalles.

Entonces vamos.

Marcado y estilos:

<body style="margin: 0; display: flex;">
    <canvas></canvas>
</body>

Sí, eso es todo el marcado y los estilos. Jajaja

JS parece mucho más serio:

let c = document.querySelector('canvas'),
    $ = c.getContext('2d'),
    w = c.width = innerWidth,
    h = c.height = innerHeight,
    random = Math.random

$.fillStyle = 'black'
$.fillRect(0, 0, w, h)

let heartPos = function (rad) {
    return [Math.pow(Math.sin(rad), 3), -(15 * Math.cos(rad) - 5 * Math.cos(2 * rad) - 2 * Math.cos(3 * rad) - Math.cos(4 * rad))]
}

let scaleAndTranslate = function (pos, sx, sy, dx, dy) {
    return [dx + pos[0] * sx, dy + pos[1] * sy]
}

window.addEventListener('resize', function () {
    w = c.width = innerWidth
    h = c.height = innerHeight
    $.fillStyle = 'black'
    $.fillRect(0, 0, w, h)
})

let traceCount = 50,
    pointsOrigin = [],
    dr = .1,
    i

for (i = 0; i < Math.PI * 2; i += dr)
    pointsOrigin.push(scaleAndTranslate(heartPos(i), 210, 13, 0, 0))

for (i = 0; i < Math.PI * 2; i += dr)
    pointsOrigin.push(scaleAndTranslate(heartPos(i), 150, 9, 0, 0))

for (i = 0; i < Math.PI * 2; i += dr)
    pointsOrigin.push(scaleAndTranslate(heartPos(i), 90, 5, 0, 0))

let heartPointsCount = pointsOrigin.length,
    targetPoints = []

let pulse = function (kx, ky) {
    for (i = 0; i < pointsOrigin.length; i++) {
        targetPoints[i] = []
        targetPoints[i][0] = kx * pointsOrigin[i][0] + w / 2
        targetPoints[i][1] = ky * pointsOrigin[i][1] + h / 2
    }
}

let e = []
for (i = 0; i < heartPointsCount; i++) {
    let x = random() * w
    let y = random() * h
    
    e[i] = {
        vx: 0,
        vy: 0,
        R: 2,
        speed: random() + 5,
        q: ~~(random() * heartPointsCount),
        D: 2 * (i % 2) - 1,
        force: .2 * random() + .7,
        f: 'hsla(0,' + ~~(40 * random() + 60) + '%,' + ~~(60 * random() + 20) + '%,.3)',
        trace: []
    }
    
    for (let k = 0; k < traceCount; k++) e[i].trace[k] = {
        x: x,
        y: y
    }
}

let config = {
    traceK: .4,
    timeDelta: .01
}

let time = 0
let loop = function () {
    let n = -Math.cos(time)
    
    pulse((1 + n) * .5, (1 + n) * .5)
    
    time += ((Math.sin(time)) < 0 ? 9 : (n > .8) ? .2 : 1) * config.timeDelta
    
    $.fillStyle = 'rgba(0,0,0,.1)'
    $.fillRect(0, 0, w, h)
    
    for (i = e.length; i--;) {
        let u = e[i],
            q = targetPoints[u.q],
            dx = u.trace[0].x - q[0],
            dy = u.trace[1].y - q[1],
            length = Math.sqrt(dx * dx + dy * dy)
        
        if (10 > length) {
            if (.95 < random()) {
                u.q = ~~(random() * heartPointsCount)
            } else {
                if (.99 < random()) {
                    u.D *= -1
                }
                
                u.q += u.D
                u.q %= heartPointsCount
                
                if (0 > u.q) {
                    u.q += heartPointsCount
                }
            }
        }
        
        u.vx += -dx / length * u.speed
        u.vy += -dy / length * u.speed
        
        u.trace[0].x += u.vx
        u.trace[0].y += u.vy
        
        u.vx *= u.force
        u.vy *= u.force
        
        for (k = 0; k < u.trace.length - 1;) {
            let T = u.trace[k]
            let N = u.trace[++k]
            N.x -= config.traceK * (N.x - T.x)
            N.y -= config.traceK * (N.y - T.y)
        }

        $.fillStyle = u.f
        for (k = 0; k < u.trace.length; k++) {
            $.fillRect(u.trace[k].x, u.trace[k].y, 1, 1)
        }
    }
    
    requestAnimationFrame(loop, c)
}

loop()

El único propósito de este artículo es entretenerte un poco durante las vacaciones (especialmente porque hoy es viernes).

Mi versión se puede ver aquí .

Para mí personalmente, este código es una prueba más de las posibilidades casi ilimitadas del tándem Canvas-JavaScript.

Gracias por su atención. Buen fin de semana.

All Articles