David Mingorance || Creador XR (AR/MR/VR) | Diseñador || Artista


(2025-2026) Xenopoéticas

// Título: Fragmento de especulación afectiva codificada

// Autor: David_Mingorance

<!DOCTYPE html>
<html lang=«es»>
<head>
    <meta charset=«UTF-8»><title>Xenopoética</title>
    <style>
        body { margin: 0; overflow: hidden; background: #000; font: 300 1.5rem Helvetica, sans-serif; cursor: crosshair; transition: .6s; }
        #t { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); color: #fff; text-align: center; pointer-events: none; width: 80%; opacity: 0; transition: .5s; text-transform: uppercase; letter-spacing: 2px; }
        .g { animation: a .2s steps(2) infinite; }
        @keyframes a { 0% { clip-path: inset(20% 0 50% 0); transform: translate(-5px); } 50% { clip-path: inset(80% 0 5% 0); transform: translate(5px); } 100% { clip-path: inset(0); } }
    </style>
</head>

// Infección afectiva se inocula por ósmosis. Comienza lenta, sin dar cuenta, sin apenas esperarlo. 

// Los síntomas no son evidentes. La predisposición baja las defensas: las torna débiles, el cuerpo y el alma se confían.

<body>
    <div id=«t»>Fragmento de especulación afectiva codificada</div>
<script type=«module»>
    import * as THREE from ‘https://unpkg.com/three@0.150.0/build/three.module.js’;

    const s = new THREE.Scene(), c = new THREE.PerspectiveCamera(75, innerWidth/innerHeight, 0.1, 1000),
          r = new THREE.WebGLRenderer({antialias: true, alpha: true}),
          count = 7000, m = new THREE.Vector2(), target = new THREE.Vector2(),
          text = document.getElementById(‘t’), orig = text.innerText;
   
    let cur = orig, clicks = 0, vis = false, hue = 180;
    r.setSize(innerWidth, innerHeight); document.body.appendChild(r.domElement);
    c.position.z = 5;

// Extrañamiento xeno,

// Lejos de estas realidades, 

// las predicciones devienen incertidumbre. 

// La seguridad se transforma en un fluido sin densidad, 

// etéreo, vacío, imposible de asir.

// Y sin embargo, pisa terreno firme:

// un planeta otrora nuestra única realidad. 

// Pero cuando la vida evoluciona, 

// tiene necesidades de expansión, de panspermia, 

// es por eso que visita nuevos cuerpos celestes.

const cv = document.createElement(‘canvas’); cv.width = cv.height = 32;
    const ctx = cv.getContext(‘2d’);
    ctx.arc(16, 16, 14, 0, Math.PI * 2); ctx.fillStyle = ‘#fff’; ctx.fill();
    const tex = new THREE.CanvasTexture(cv);

    const geo = new THREE.BufferGeometry(), pos = new Float32Array(count * 3), vel = new Float32Array(count * 3);
    for(let i=0; i<count*3; i++) { pos[i] = (Math.random()-0.5)*15; vel[i] = (Math.random()-0.5)*0.01; }
    geo.setAttribute(‘position’, new THREE.BufferAttribute(pos, 3));
    const mat = new THREE.PointsMaterial({size: 0.04, map: tex, transparent: true, opacity: 0.4, blending: THREE.AdditiveBlending, color: 0x00ffff});
    const pts = new THREE.Points(geo, mat); s.add(pts);

    const reset = () => { vis = false; clicks = 0; cur = orig; text.innerText = orig; text.style.opacity = 0; document.body.style.backgroundColor = «#000»; mat.color.set(0x00ffff); };

// Intentó abandonar sus investigaciones, 

// se prometió a sí mismx que se trataba de una extravagancia fortuita, 

// más no puede dejar de otear aquella zona, fuera del campo de visión, 

// donde lo fantasmagórico emerge como posible.

window.onclick = () => {
        if(!vis) return (text.style.opacity = 1, vis = true);
        clicks++; hue = (hue + 40) % 360;
        document.body.style.backgroundColor = `hsl(${hue}, 20%, 3%)`;
        mat.color.setHSL(hue/360, 0.8, 0.5);
        text.className = ‘g’; setTimeout(() => text.className = », 200);
       
        let a = cur.split(»);
        for(let i=0; i<Math.ceil(a.length*0.12); i++) {
            let idx = Math.floor(Math.random()*a.length);
            if(a[idx] !== » «) a[idx] = Math.random() > 0.5 ? String.fromCharCode(33+Math.random()*20) : » «;
        }
        cur = a.join(»); text.innerText = cur;
        if(!cur.trim()) setTimeout(reset, 800);
    };

// Bifurcación de caminos, 

// horizonte de sucesos en el agujero negro de la razón. 

// La intuición es un juego de azar. 

// Apostar todo significaría la destrucción.

window.onmousemove = e => { target.x = (e.clientX/innerWidth-0.5)*2; target.y = -(e.clientY/innerHeight-0.5)*2; };

    function animate() {
        requestAnimationFrame(animate);
        m.lerp(target, 0.08);
        pts.rotation.y = m.x * 0.5; pts.rotation.x = -m.y * 0.5;
        const p = geo.attributes.position.array;
        for(let i=0; i<count*3; i+=3) {
            p[i] += vel[i]*(clicks+1); p[i+1] += vel[i+1]*(clicks+1);
            if(Math.abs(p[i]) > 12 || Math.abs(p[i+1]) > 8) { p[i] *= -0.9; p[i+1] *= -0.9; }
        }
        geo.attributes.position.needsUpdate = true;
        r.render(s, c);
    }

// ¿Quién decide el futuro, cuando se vuelve volátil?

// Sus sistemas de medición no cotejan los registros, 

// confía en la tecnología, pero sabe que no debe. 

// Los filtros anímicos nublan toda interpretación aséptica. 

// A su vez, 

// las plataformas distorsionan lo examinado, 

// trastocan las percepciones 

// sin necesidad siquiera de que su traducción sea la apropiada.

  animate();
    window.onresize = () => { c.aspect = innerWidth/innerHeight; c.updateProjectionMatrix(); r.setSize(innerWidth, innerHeight); };

// Todo esto acontece mientras el mundo transcurre a su velocidad habitual, 

// sin pararse a reflexionar sobre la disposición de las cosas. 

// El paso del tiempo modifica nuestra existencia. 

// Quién sabe si durante un instante o quizás durante una eternidad.

</script>
</body>
</html>