Reorganize POCs and demos under POCS/ folder
- Move BACK_BACK/ → POCS/BACK_BACK/ (image pipeline scripts) - Move VISUALIZACION/ → POCS/VISUALIZACION/ (demos + static assets) - No path changes needed: ../VISUALIZACION/public still resolves correctly from POCS/BACK_BACK/FLUJOS_APP_PRUEBAS.js - Add FLUJOS_DATOS/DOCS/extraer_info_bbdd.txt (DB state snapshot + commands) FLUJOS/ and FLUJOS_DATOS/ untouched (production). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
932e8e80db
commit
25953376cd
15 changed files with 172 additions and 0 deletions
301
POCS/VISUALIZACION/public/demos/demo_img_nodes.html
Normal file
301
POCS/VISUALIZACION/public/demos/demo_img_nodes.html
Normal file
|
|
@ -0,0 +1,301 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>FLUJOS — Demo: Image Nodes</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"three": "https://esm.sh/three@0.168",
|
||||
"three/": "https://esm.sh/three@0.168/",
|
||||
"3d-force-graph": "https://esm.sh/3d-force-graph@1.73?external=three"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Fira Code', monospace; }
|
||||
body { background: #000; color: #39ff14; overflow: hidden; }
|
||||
|
||||
#graph { position: fixed; top: 0; left: 0; width: 100%; height: 100%; }
|
||||
|
||||
#header {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 10;
|
||||
padding: 10px 20px;
|
||||
background: linear-gradient(180deg, rgba(0,0,0,0.9) 0%, transparent 100%);
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
}
|
||||
#header h1 { font-size: 1.1em; color: #39ff14; letter-spacing: 3px; text-shadow: 0 0 10px #39ff14; }
|
||||
#header .tag {
|
||||
font-size: 0.65em; padding: 3px 8px;
|
||||
border: 1px solid #ff4500; color: #ff4500;
|
||||
opacity: 0.8; letter-spacing: 2px;
|
||||
}
|
||||
|
||||
#info-panel {
|
||||
position: fixed; bottom: 30px; right: 20px; z-index: 10;
|
||||
width: 300px;
|
||||
background: rgba(0,0,0,0.9);
|
||||
border: 1px solid #333;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
#info-panel .panel-img {
|
||||
width: 100%; height: 120px;
|
||||
object-fit: cover; display: block;
|
||||
opacity: 0.8;
|
||||
}
|
||||
#info-panel .panel-img-placeholder {
|
||||
width: 100%; height: 120px;
|
||||
background: #111;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
font-size: 2em; color: #333;
|
||||
}
|
||||
#info-panel .panel-body { padding: 12px 16px; }
|
||||
#info-panel h3 { font-size: 0.85em; color: #fff; margin-bottom: 6px; }
|
||||
#info-panel .group-badge {
|
||||
display: inline-block; padding: 2px 8px;
|
||||
font-size: 0.65em; letter-spacing: 2px; margin-bottom: 8px;
|
||||
}
|
||||
#info-panel p { font-size: 0.72em; color: #888; line-height: 1.5; }
|
||||
#info-panel .close {
|
||||
position: absolute; top: 8px; right: 10px; z-index: 1;
|
||||
cursor: pointer; color: #fff; font-size: 0.8em;
|
||||
background: rgba(0,0,0,0.6); border: none; font-family: inherit;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
#technique-label {
|
||||
position: fixed; top: 50px; right: 20px; z-index: 10;
|
||||
font-size: 0.6em; color: #333; letter-spacing: 1px;
|
||||
text-align: right; line-height: 1.8;
|
||||
}
|
||||
|
||||
#legend {
|
||||
position: fixed; bottom: 30px; left: 20px; z-index: 10;
|
||||
background: rgba(0,0,0,0.8); border: 1px solid #222;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
#legend h4 { font-size: 0.6em; color: #444; margin-bottom: 8px; letter-spacing: 2px; }
|
||||
.legend-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
|
||||
.legend-img { width: 20px; height: 20px; object-fit: cover; opacity: 0.7; }
|
||||
.legend-sphere { width: 10px; height: 10px; border-radius: 50%; }
|
||||
.legend-label { font-size: 0.62em; color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="graph"></div>
|
||||
|
||||
<div id="header">
|
||||
<h1>FLUJOS</h1>
|
||||
<span class="tag">IMAGE NODES</span>
|
||||
<span class="tag">THREE.Sprite + TextureLoader</span>
|
||||
</div>
|
||||
|
||||
<div id="info-panel">
|
||||
<button class="close" onclick="document.getElementById('info-panel').style.display='none'">✕</button>
|
||||
<img id="panel-img" class="panel-img" src="" alt="" style="display:none">
|
||||
<div id="panel-placeholder" class="panel-img-placeholder">◈</div>
|
||||
<div class="panel-body">
|
||||
<h3 id="node-title"></h3>
|
||||
<span class="group-badge" id="node-group"></span>
|
||||
<p id="node-content"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="legend">
|
||||
<h4>NODOS CON IMAGEN</h4>
|
||||
<div class="legend-row">
|
||||
<img class="legend-img" src="/images/flujos_logo.png" alt="">
|
||||
<span class="legend-label">FLUJOS (core)</span>
|
||||
</div>
|
||||
<div class="legend-row">
|
||||
<img class="legend-img" src="/images/flujos3.jpg" alt="">
|
||||
<span class="legend-label">Cambio Climático</span>
|
||||
</div>
|
||||
<div class="legend-row">
|
||||
<img class="legend-img" src="/images/journalist_fondo.jpg" alt="">
|
||||
<span class="legend-label">Libertad de Prensa</span>
|
||||
</div>
|
||||
<h4 style="margin-top:8px">NODOS ESFERA</h4>
|
||||
<div class="legend-row">
|
||||
<div class="legend-sphere" style="background:#ff69b4"></div>
|
||||
<span class="legend-label">security</span>
|
||||
</div>
|
||||
<div class="legend-row">
|
||||
<div class="legend-sphere" style="background:#ffdc00"></div>
|
||||
<span class="legend-label">corporate</span>
|
||||
</div>
|
||||
<div class="legend-row">
|
||||
<div class="legend-sphere" style="background:#4488ff"></div>
|
||||
<span class="legend-label">politics</span>
|
||||
</div>
|
||||
<div class="legend-row">
|
||||
<div class="legend-sphere" style="background:#cc44ff"></div>
|
||||
<span class="legend-label">data</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="technique-label">
|
||||
nodeThreeObject(node => Sprite)<br>
|
||||
new THREE.TextureLoader().load(img)<br>
|
||||
new THREE.SpriteMaterial({ map })<br>
|
||||
— THREE.js Sprite billboard —
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import ForceGraph3D from '3d-force-graph';
|
||||
import * as THREE from 'three';
|
||||
|
||||
// Nodes with `img` get rendered as image sprites.
|
||||
// Nodes without `img` fall back to a colored sphere (default).
|
||||
const GROUP_COLORS = {
|
||||
core: '#39ff14',
|
||||
climate: '#ff4500',
|
||||
security: '#ff69b4',
|
||||
journalism: '#00fff2',
|
||||
corporate: '#ffdc00',
|
||||
politics: '#4488ff',
|
||||
data: '#cc44ff'
|
||||
};
|
||||
|
||||
// Images are served from the project's /images/ folder
|
||||
const MOCK_DATA = {
|
||||
nodes: [
|
||||
{ id: 'FLUJOS', group: 'core', img: '/images/flujos_logo.png', size: 22, content: 'Sistema de visualización de flujos de información global' },
|
||||
{ id: 'Cambio Climático', group: 'climate', img: '/images/flujos3.jpg', size: 18, content: 'Crisis climática y sus efectos sociopolíticos' },
|
||||
{ id: 'Seguridad Intl.', group: 'security', img: '/images/flujos4.jpg', size: 16, content: 'Geopolítica y conflictos armados globales' },
|
||||
{ id: 'Libertad de Prensa', group: 'journalism', img: '/images/journalist_fondo.jpg', size: 16, content: 'Estado global de la libertad periodística' },
|
||||
{ id: 'Eco-Corporativo', group: 'corporate', img: '/images/flujos7.jpg', size: 16, content: 'Poder corporativo e influencia política' },
|
||||
{ id: 'Populismo', group: 'politics', img: '/images/flujos8.jpg', size: 16, content: 'Auge de movimientos populistas globales' },
|
||||
{ id: 'Wikipedia', group: 'data', img: '/images/flujos_logo3.png', size: 14, content: 'Enciclopedia libre como fuente de datos' },
|
||||
// Leaf nodes — rendered as default colored spheres
|
||||
{ id: 'Emisiones CO₂', group: 'climate', content: 'Emisiones industriales de CO₂' },
|
||||
{ id: 'Energía Renovable', group: 'climate', content: 'Transición a fuentes sostenibles' },
|
||||
{ id: 'Pérdida Biodiversidad',group: 'climate', content: 'Extinción de especies y ecosistemas' },
|
||||
{ id: 'Ciberseguridad', group: 'security', content: 'Ataques cibernéticos estatales' },
|
||||
{ id: 'Vigilancia Masiva', group: 'security', content: 'Programas de espionaje gubernamental' },
|
||||
{ id: 'Privacidad Datos', group: 'security', content: 'Derechos digitales y datos personales' },
|
||||
{ id: 'Desinformación', group: 'journalism', content: 'Fake news y manipulación informativa' },
|
||||
{ id: 'Whistleblowers', group: 'journalism', content: 'Snowden, Assange, Panama Papers...' },
|
||||
{ id: 'Big Tech', group: 'corporate', content: 'Monopolios: Google, Meta, Amazon...' },
|
||||
{ id: 'Paraísos Fiscales', group: 'corporate', content: 'Evasión fiscal corporativa offshore' },
|
||||
{ id: 'Lobbying', group: 'corporate', content: 'Grupos de presión legislativa' },
|
||||
{ id: 'Elecciones', group: 'politics', content: 'Procesos electorales e interferencia' },
|
||||
{ id: 'Migración', group: 'politics', content: 'Crisis migratoria y fronteras' },
|
||||
{ id: 'Extremismo', group: 'politics', content: 'Radicalización y movimientos extremistas' },
|
||||
{ id: 'Redes Sociales', group: 'data', content: 'Plataformas sociales como vectores' },
|
||||
{ id: 'IA & Algoritmos', group: 'data', content: 'IA, sesgos y control algorítmico' },
|
||||
{ id: 'Torrents & P2P', group: 'data', content: 'Distribución descentralizada de info' },
|
||||
],
|
||||
links: [
|
||||
{ source: 'FLUJOS', target: 'Cambio Climático', value: 90 },
|
||||
{ source: 'FLUJOS', target: 'Seguridad Intl.', value: 85 },
|
||||
{ source: 'FLUJOS', target: 'Libertad de Prensa', value: 88 },
|
||||
{ source: 'FLUJOS', target: 'Eco-Corporativo', value: 87 },
|
||||
{ source: 'FLUJOS', target: 'Populismo', value: 82 },
|
||||
{ source: 'FLUJOS', target: 'Wikipedia', value: 95 },
|
||||
{ source: 'FLUJOS', target: 'Torrents & P2P', value: 88 },
|
||||
{ source: 'Cambio Climático', target: 'Emisiones CO₂', value: 92 },
|
||||
{ source: 'Cambio Climático', target: 'Energía Renovable', value: 88 },
|
||||
{ source: 'Cambio Climático', target: 'Pérdida Biodiversidad',value: 85 },
|
||||
{ source: 'Emisiones CO₂', target: 'Eco-Corporativo', value: 78 },
|
||||
{ source: 'Energía Renovable', target: 'Big Tech', value: 65 },
|
||||
{ source: 'Seguridad Intl.', target: 'Ciberseguridad', value: 88 },
|
||||
{ source: 'Seguridad Intl.', target: 'Vigilancia Masiva', value: 85 },
|
||||
{ source: 'Seguridad Intl.', target: 'Migración', value: 75 },
|
||||
{ source: 'Ciberseguridad', target: 'Privacidad Datos', value: 90 },
|
||||
{ source: 'Vigilancia Masiva', target: 'Privacidad Datos', value: 92 },
|
||||
{ source: 'Vigilancia Masiva', target: 'Big Tech', value: 75 },
|
||||
{ source: 'Vigilancia Masiva', target: 'IA & Algoritmos', value: 82 },
|
||||
{ source: 'Libertad de Prensa',target: 'Desinformación', value: 88 },
|
||||
{ source: 'Libertad de Prensa',target: 'Whistleblowers', value: 85 },
|
||||
{ source: 'Desinformación', target: 'Redes Sociales', value: 90 },
|
||||
{ source: 'Desinformación', target: 'Elecciones', value: 85 },
|
||||
{ source: 'Desinformación', target: 'Extremismo', value: 80 },
|
||||
{ source: 'Eco-Corporativo', target: 'Big Tech', value: 85 },
|
||||
{ source: 'Eco-Corporativo', target: 'Paraísos Fiscales', value: 88 },
|
||||
{ source: 'Eco-Corporativo', target: 'Lobbying', value: 90 },
|
||||
{ source: 'Big Tech', target: 'IA & Algoritmos', value: 88 },
|
||||
{ source: 'Big Tech', target: 'Redes Sociales', value: 92 },
|
||||
{ source: 'Lobbying', target: 'Elecciones', value: 78 },
|
||||
{ source: 'Populismo', target: 'Elecciones', value: 88 },
|
||||
{ source: 'Populismo', target: 'Migración', value: 85 },
|
||||
{ source: 'Populismo', target: 'Extremismo', value: 82 },
|
||||
{ source: 'Extremismo', target: 'Redes Sociales', value: 78 },
|
||||
{ source: 'IA & Algoritmos', target: 'Redes Sociales', value: 85 },
|
||||
{ source: 'Wikipedia', target: 'Desinformación', value: 72 },
|
||||
]
|
||||
};
|
||||
|
||||
const textureCache = {};
|
||||
const loader = new THREE.TextureLoader();
|
||||
|
||||
function getTexture(url) {
|
||||
if (!textureCache[url]) {
|
||||
const tex = loader.load(url);
|
||||
tex.colorSpace = THREE.SRGBColorSpace;
|
||||
textureCache[url] = tex;
|
||||
}
|
||||
return textureCache[url];
|
||||
}
|
||||
|
||||
const elem = document.getElementById('graph');
|
||||
|
||||
const Graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel(node => `<span style="font-family:Fira Code,monospace;color:${GROUP_COLORS[node.group]};font-size:12px">${node.id}</span>`)
|
||||
.nodeColor(node => GROUP_COLORS[node.group] || '#ffffff')
|
||||
.nodeVal(node => node.size ? node.size / 3 : 1.2)
|
||||
.linkColor(() => 'rgba(57,255,20,0.25)')
|
||||
.linkWidth(link => (link.value || 50) / 55)
|
||||
.nodeThreeObject(node => {
|
||||
if (!node.img) return null; // use default sphere for leaf nodes
|
||||
|
||||
const texture = getTexture(node.img);
|
||||
const material = new THREE.SpriteMaterial({ map: texture, transparent: true });
|
||||
const sprite = new THREE.Sprite(material);
|
||||
const s = node.size || 12;
|
||||
sprite.scale.set(s, s);
|
||||
return sprite;
|
||||
})
|
||||
.onNodeClick(node => {
|
||||
const panel = document.getElementById('info-panel');
|
||||
document.getElementById('node-title').textContent = node.id;
|
||||
|
||||
const badge = document.getElementById('node-group');
|
||||
badge.textContent = node.group.toUpperCase();
|
||||
badge.style.background = GROUP_COLORS[node.group] + '22';
|
||||
badge.style.border = `1px solid ${GROUP_COLORS[node.group]}`;
|
||||
badge.style.color = GROUP_COLORS[node.group];
|
||||
|
||||
document.getElementById('node-content').textContent = node.content || '';
|
||||
|
||||
const imgEl = document.getElementById('panel-img');
|
||||
const placeholder = document.getElementById('panel-placeholder');
|
||||
if (node.img) {
|
||||
imgEl.src = node.img;
|
||||
imgEl.style.display = 'block';
|
||||
placeholder.style.display = 'none';
|
||||
} else {
|
||||
imgEl.style.display = 'none';
|
||||
placeholder.style.display = 'flex';
|
||||
}
|
||||
|
||||
panel.style.display = 'block';
|
||||
})
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.graphData(MOCK_DATA);
|
||||
|
||||
Graph.d3Force('charge').strength(-200);
|
||||
setTimeout(() => Graph.zoomToFit(600, 80), 1500);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
Graph.width(elem.clientWidth).height(elem.clientHeight);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue