flow like the river
80
VISUALIZACION/public/3dscript_eco-corp.css
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
:root {
|
||||
--cube-size: 80px;
|
||||
--line-color: #333;
|
||||
--hover-color: #2ecc71;
|
||||
--background-color: #000;
|
||||
--sidebar-width: 250px; /* Ajustamos el ancho del sidebar */
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: flex-start; /* Asegura que el contenido comience desde la izquierda */
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
position: relative;
|
||||
width: calc(100vw - var(--sidebar-width)); /* Restamos el ancho del sidebar */
|
||||
height: 100vh;
|
||||
margin-left: var(--sidebar-width); /* Añadimos margen para que no se solape */
|
||||
}
|
||||
|
||||
.cube-container {
|
||||
position: absolute;
|
||||
width: var(--cube-size);
|
||||
height: var(--cube-size);
|
||||
transform-style: preserve-3d;
|
||||
transition: transform 1s ease;
|
||||
}
|
||||
|
||||
.cube-container:hover {
|
||||
transform: rotateX(360deg) rotateY(360deg); /* Efecto al pasar el mouse */
|
||||
}
|
||||
|
||||
.cube {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.face {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--hover-color);
|
||||
border: 1px solid #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.65rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.front { transform: translateZ(calc(var(--cube-size) / 2)); }
|
||||
.back { transform: rotateY(180deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.left { transform: rotateY(-90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.right { transform: rotateY(90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.top { transform: rotateX(90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.bottom { transform: rotateX(-90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
|
||||
.lines {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.line-path {
|
||||
stroke: var(--line-color);
|
||||
stroke-width: 2;
|
||||
transition: stroke 0.3s;
|
||||
}
|
||||
|
||||
.line-path:hover {
|
||||
stroke: #e74c3c;
|
||||
}
|
||||
147
VISUALIZACION/public/3dscript_eco-corp.html
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Visualización 2D de Noticias Políticas</title>
|
||||
<link rel="stylesheet" href="3dscript_eco-corp.css">
|
||||
<style>
|
||||
.popup {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
color: black;
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
z-index: 2;
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.popup:focus,
|
||||
.cube-container:focus + .popup {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.popup button {
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
padding: 10px;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.popup button:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="graph-container" id="graph-container">
|
||||
<svg class="lines" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="svg-lines">
|
||||
<!-- Líneas generadas dinámicamente -->
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const numCubes = 9; // Número total de cubos
|
||||
const spacing = 150; // Espacio mínimo entre los cubos
|
||||
const graphContainer = document.getElementById('graph-container');
|
||||
const svgLines = document.getElementById('svg-lines');
|
||||
let cubePositions = [];
|
||||
|
||||
// Función para detectar colisiones y asegurarse de que los cubos no se solapen
|
||||
function detectCollision(newX, newY, positions) {
|
||||
for (let pos of positions) {
|
||||
const distance = Math.sqrt((newX - pos.x) ** 2 + (newY - pos.y) ** 2);
|
||||
if (distance < spacing) {
|
||||
return true; // Hay colisión
|
||||
}
|
||||
}
|
||||
return false; // No hay colisión
|
||||
}
|
||||
|
||||
// Función para generar una posición aleatoria sin que los cubos se solapen
|
||||
function getRandomPosition(maxWidth, maxHeight) {
|
||||
let x, y;
|
||||
do {
|
||||
x = Math.random() * (maxWidth - spacing);
|
||||
y = Math.random() * (maxHeight - spacing);
|
||||
} while (detectCollision(x, y, cubePositions));
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
// Función para generar cubos con posiciones aleatorias
|
||||
function generateRandomCubes(cubeCount) {
|
||||
for (let i = 0; i < cubeCount; i++) {
|
||||
const position = getRandomPosition(window.innerWidth, window.innerHeight);
|
||||
const cubeContainer = document.createElement('div');
|
||||
cubeContainer.classList.add('cube-container');
|
||||
cubeContainer.setAttribute('tabindex', '0');
|
||||
cubeContainer.style.top = position.y + 'px';
|
||||
cubeContainer.style.left = position.x + 'px';
|
||||
|
||||
cubeContainer.innerHTML = `
|
||||
<div class="cube">
|
||||
<div class="face front">País ${i}</div>
|
||||
<div class="face back">Detalle ${i}</div>
|
||||
<div class="face left">Año ${2000 + i}</div>
|
||||
<div class="face right">Muertos ${(i + 1) * 1000}</div>
|
||||
<div class="face top">ONU</div>
|
||||
<div class="face bottom">Fuente</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Crear un popup para cada cubo
|
||||
const popup = document.createElement('div');
|
||||
popup.classList.add('popup');
|
||||
popup.innerHTML = `
|
||||
<p>Noticia relacionada con País ${i}</p>
|
||||
<button>Close</button>
|
||||
`;
|
||||
|
||||
popup.querySelector('button').addEventListener('click', () => {
|
||||
popup.style.display = 'none';
|
||||
cubeContainer.focus(); // Regresar el foco al cubo
|
||||
});
|
||||
|
||||
cubeContainer.addEventListener('focus', () => {
|
||||
popup.style.display = 'block';
|
||||
});
|
||||
|
||||
cubePositions.push({ x: position.x + 35, y: position.y + 35 }); // Guardar la posición
|
||||
graphContainer.appendChild(cubeContainer);
|
||||
graphContainer.appendChild(popup); // Añadir el popup después del cubo
|
||||
}
|
||||
}
|
||||
|
||||
// Función para generar las líneas entre cubos relacionados
|
||||
function generateLines() {
|
||||
for (let i = 0; i < cubePositions.length - 1; i++) {
|
||||
const x1 = cubePositions[i].x;
|
||||
const y1 = cubePositions[i].y;
|
||||
const x2 = cubePositions[i + 1].x;
|
||||
const y2 = cubePositions[i + 1].y;
|
||||
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', x1);
|
||||
line.setAttribute('y1', y1);
|
||||
line.setAttribute('x2', x2);
|
||||
line.setAttribute('y2', y2);
|
||||
line.setAttribute('stroke', '#333');
|
||||
line.setAttribute('stroke-width', '2');
|
||||
|
||||
svgLines.appendChild(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Generar cubos aleatorios y las líneas de conexión
|
||||
generateRandomCubes(numCubes);
|
||||
generateLines();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
332
VISUALIZACION/public/climate.css
Executable file
|
|
@ -0,0 +1,332 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "Retrolift", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 6px 6px 6px #73ff00;
|
||||
margin-bottom: 10px;
|
||||
|
||||
}
|
||||
|
||||
.glob-war:hover .logo { text-shadow: 2px 2px 8px #39ff14; }
|
||||
.int-sec:hover .logo { text-shadow: 2px 2px 8px #ff69b4; }
|
||||
.climate:hover .logo { text-shadow: 2px 2px 8px #ff4500; }
|
||||
.eco-corp:hover .logo { text-shadow: 2px 2px 8px #006400; }
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
|
||||
/* Estilo de los botones */
|
||||
position:relative;
|
||||
border: none;
|
||||
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border:3vw;
|
||||
|
||||
align-items: center;
|
||||
border: 3px solid ;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
|
||||
/* Estilo hover de los botones */
|
||||
|
||||
box-shadow: 2vw 1vw;
|
||||
|
||||
border: 3px solid black ;
|
||||
}
|
||||
|
||||
.glob-war:hover { color: #39ff14; }
|
||||
.int-sec:hover { color: #ff69b4; }
|
||||
.climate:hover { color: #ff4500; }
|
||||
.eco-corp:hover { color: #00fff2; }
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
|
||||
.glob-war {
|
||||
color: #FF4136;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.int-sec {
|
||||
color: #0074D9;
|
||||
background-color: darkblue;
|
||||
}
|
||||
|
||||
.climate {
|
||||
color: #2ECC40;
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
.eco-corp {
|
||||
color: #FFDC00;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.popl-up {
|
||||
color: #FF851B;
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background a img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
|
||||
#sidebar.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-90%);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size:18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
position: absolute;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
background: #007BFF;
|
||||
color: #39ff14;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background 0.3s ease;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14; /* Añade el borde verde al input */
|
||||
background: black; /* Cambia el fondo del input a negro */
|
||||
color: #39ff14; /* Cambia el color del texto en el input a verde */
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#climateContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.5;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-links a {
|
||||
font-size: 0.8em; /* reduce el tamaño de la fuente */
|
||||
padding: 10px 20px; /* reduce el padding */
|
||||
}
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 2em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.fade-out {
|
||||
animation: fadeOut 2s forwards; /* Fades out over 3 seconds */
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
from {opacity: 1;}
|
||||
to {opacity: 0;}
|
||||
}
|
||||
|
||||
|
||||
.grafico {
|
||||
z-index: 1; /* Bring to front */
|
||||
/* Rest of your styles */
|
||||
}
|
||||
|
||||
|
||||
.grafico {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
87
VISUALIZACION/public/climate.html
Executable file
|
|
@ -0,0 +1,87 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CLIMATE</title>
|
||||
<link rel="stylesheet" href="climate.css">
|
||||
<!-- Fuentes de Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Cargar 3d-force-graph (incluye Three.js) -->
|
||||
<!-- CORRECTO: d3 primero, force-graph después -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
|
||||
<script src="https://unpkg.com/3d-force-graph"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="climate.html" class="climate">CLIMATE</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<div id="climateContainer" style="position: absolute; width: 100%; height: 100%;"></div>
|
||||
<div class="background">
|
||||
<img src="/images/flujos6.jpg">
|
||||
<img src="/images/flujos6.jpg">
|
||||
<img src="/images/flujos6.jpg">
|
||||
<img src="/images/flujos6.jpg">
|
||||
<img src="/images/flujos6.jpg">
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
var fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
||||
</main>
|
||||
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="100">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="40" value="20">
|
||||
|
||||
<label for="param1">Búsqueda por palabra:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="color1">Color 1:</label>
|
||||
<input type="color" id="color1" name="color1">
|
||||
|
||||
<label for="param2">Búsqueda por temática personalizada:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<label for="color2">Color 2:</label>
|
||||
<input type="color" id="color2" name="color2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- Movemos la inclusión del script aquí, al final del body -->
|
||||
<script src="output_climate_pruebas.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
0
VISUALIZACION/public/climate.js
Executable file
236
VISUALIZACION/public/eco-corp.css
Executable file
|
|
@ -0,0 +1,236 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "Retrolift", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 6px 6px 6px #73ff00;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.glob-war:hover .logo { text-shadow: 2px 2px 8px #39ff14; }
|
||||
.int-sec:hover .logo { text-shadow: 2px 2px 8px #ff69b4; }
|
||||
.climate:hover .logo { text-shadow: 2px 2px 8px #ff4500; }
|
||||
.eco-corp:hover .logo { text-shadow: 2px 2px 8px #006400; }
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
|
||||
position: relative;
|
||||
border: none;
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border: 3vw;
|
||||
align-items: center;
|
||||
border: 3px solid;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
.glob-war:hover { color: #39ff14; }
|
||||
.int-sec:hover { color: #ff69b4; }
|
||||
.climate:hover { color: #ff4500; }
|
||||
.eco-corp:hover { color: #00fff2; }
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
|
||||
.glob-war { color: #FF4136; background-color: red; }
|
||||
.int-sec { color: #0074D9; background-color: darkblue; }
|
||||
.climate { color: #2ECC40; background-color: lightgreen; }
|
||||
.eco-corp { color: #FFDC00; background-color: yellow; }
|
||||
.popl-up { color: #FF851B; background-color: orange; }
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Sidebar con comportamiento onhover */
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-220px);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size: 18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14;
|
||||
background: black;
|
||||
color: #39ff14;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Ajuste del iframe para que respete el espacio del sidebar */
|
||||
.iframe-container {
|
||||
width: calc(100% - 250px);
|
||||
height: 100vh;
|
||||
background: #000000;
|
||||
margin: 0 auto;
|
||||
border: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
left: 250px;
|
||||
}
|
||||
|
||||
77
VISUALIZACION/public/eco-corp.html
Executable file
|
|
@ -0,0 +1,77 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Economía y Corporaciones</title>
|
||||
<link rel="stylesheet" href="eco-corp.css">
|
||||
<!-- Fuentes de Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Cargar D3.js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
|
||||
<!-- Cargar 3d-force-graph (incluye Three.js) -->
|
||||
<script src="https://unpkg.com/3d-force-graph"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="eco-corp.html" class="eco-corp">Economía y Corporaciones</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<div id="ecoCorpContainer" style="position: absolute; width: 100%; height: 100%;"></div>
|
||||
<div class="background">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
var fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="100">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="40" value="20">
|
||||
|
||||
<label for="param1">Búsqueda por palabra:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="param2">Búsqueda por temática personalizada:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- Incluir tu script al final del body -->
|
||||
<script src="output_eco_corp_pruebas.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
89
VISUALIZACION/public/eco-corp.html.save
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="eco-corp.css">
|
||||
<title>ECO-CORP</title>
|
||||
<script type="module" src="output.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="eco-corp.html" class="eco-corp">ECO-CORP</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<div id="canvasContainer" style="position: absolute; width: 100%; height: 100%; opacity: 0.5;"></div>
|
||||
<div class="background">
|
||||
<img src="/images/flujos4.jpg">
|
||||
<img src="/images/flujos4.jpg">
|
||||
<img src="/images/flujos4.jpg">
|
||||
<img src="/images/flujos4.jpg">
|
||||
<img src="/images/flujos4.jpg">
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
var fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<div id="contentDisplay" class="content-display"></div>
|
||||
</main>
|
||||
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Número máximo de nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="200" min="50" max="500">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="10">
|
||||
|
||||
<label for="param1">Búsqueda por palabra clave:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="param2">Filtrar por subtemática:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
document.getElementById('sidebarToggle').addEventListener('click', function() {
|
||||
var sidebar = document.getElementById('sidebar');
|
||||
sidebar.classList.toggle('active');
|
||||
});
|
||||
|
||||
document.getElementById('paramForm').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
const maxNodes = document.getElementById('nodos').value;
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
|
||||
// Ejecutar la lógica para actualizar el gráfico con los nuevos parámetros
|
||||
myGraph.setMaxNodes(maxNodes);
|
||||
myGraph.drawGraph(subtematica, palabraClave, fechaInicio, fechaFin);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
331
VISUALIZACION/public/glob-war.css
Executable file
|
|
@ -0,0 +1,331 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background-color: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
background-color: #000000;
|
||||
color: #000000;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "Retrolift", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 6px 6px 6px #73ff00;
|
||||
margin-bottom: 10px;
|
||||
|
||||
}
|
||||
|
||||
.glob-war:hover .logo { text-shadow: 2px 2px 8px #39ff14; }
|
||||
.int-sec:hover .logo { text-shadow: 2px 2px 8px #ff69b4; }
|
||||
.climate:hover .logo { text-shadow: 2px 2px 8px #ff4500; }
|
||||
.eco-corp:hover .logo { text-shadow: 2px 2px 8px #006400; }
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
|
||||
/* Estilo de los botones */
|
||||
position:relative;
|
||||
border: none;
|
||||
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border:3vw;
|
||||
|
||||
align-items: center;
|
||||
border: 3px solid ;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
|
||||
/* Estilo hover de los botones */
|
||||
|
||||
box-shadow: 2vw 1vw;
|
||||
|
||||
border: 3px solid black ;
|
||||
}
|
||||
|
||||
.glob-war:hover { color: #39ff14; }
|
||||
.int-sec:hover { color: #ff69b4; }
|
||||
.climate:hover { color: #ff4500; }
|
||||
.eco-corp:hover { color: #00fff2; }
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
|
||||
.glob-war {
|
||||
color: #FF4136;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.int-sec {
|
||||
color: #0074D9;
|
||||
background-color: darkblue;
|
||||
}
|
||||
|
||||
.climate {
|
||||
color: #2ECC40;
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
.eco-corp {
|
||||
color: #FFDC00;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.popl-up {
|
||||
color: #FF851B;
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background a img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
|
||||
#sidebar.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-90%);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size:18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
position: absolute;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
background: #007BFF;
|
||||
color: #39ff14;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background 0.3s ease;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14; /* Añade el borde verde al input */
|
||||
background: black; /* Cambia el fondo del input a negro */
|
||||
color: #39ff14; /* Cambia el color del texto en el input a verde */
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#glob_war_container{
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.5;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-links a {
|
||||
font-size: 0.8em; /* reduce el tamaño de la fuente */
|
||||
padding: 10px 20px; /* reduce el padding */
|
||||
}
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 2em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.fade-out {
|
||||
animation: fadeOut 3s forwards; /* Fades out over 3 seconds */
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
from {opacity: 1;}
|
||||
to {opacity: 0;}
|
||||
}
|
||||
|
||||
|
||||
.grafico {
|
||||
z-index: 1; /* Bring to front */
|
||||
/* Rest of your styles */
|
||||
}
|
||||
|
||||
|
||||
.grafico {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
83
VISUALIZACION/public/glob-war.html
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Glob-War</title>
|
||||
<link rel="stylesheet" href="glob-war.css">
|
||||
<!-- Fuentes de Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Cargar D3.js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
|
||||
<!-- Cargar 3d-force-graph (incluye Three.js) -->
|
||||
<script src="https://unpkg.com/3d-force-graph"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="glob-war.html" class="glob-war">GLOB-WAR</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<div id="globWarContainer" style="position: absolute; width: 100%; height: 100%;"></div>
|
||||
<div class="background">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
var fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="100">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="40" value="20">
|
||||
|
||||
<label for="param1">Búsqueda por palabra:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="color1">Color 1:</label>
|
||||
<input type="color" id="color1" name="color1">
|
||||
|
||||
<label for="param2">Búsqueda por temática personalizada:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<label for="color2">Color 2:</label>
|
||||
<input type="color" id="color2" name="color2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- Incluir tu script al final del body -->
|
||||
<script src="output_glob_war_pruebas.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
VISUALIZACION/public/images/flujos.jpg
Executable file
|
After Width: | Height: | Size: 160 KiB |
BIN
VISUALIZACION/public/images/flujos2.jpg
Executable file
|
After Width: | Height: | Size: 256 KiB |
BIN
VISUALIZACION/public/images/flujos3.jpg
Executable file
|
After Width: | Height: | Size: 223 KiB |
BIN
VISUALIZACION/public/images/flujos4.jpg
Executable file
|
After Width: | Height: | Size: 313 KiB |
BIN
VISUALIZACION/public/images/flujos6.jpg
Executable file
|
After Width: | Height: | Size: 79 KiB |
BIN
VISUALIZACION/public/images/flujos7.jpg
Executable file
|
After Width: | Height: | Size: 65 KiB |
BIN
VISUALIZACION/public/images/flujos8.jpg
Executable file
|
After Width: | Height: | Size: 151 KiB |
BIN
VISUALIZACION/public/images/flujos9.jpg
Executable file
|
After Width: | Height: | Size: 154 KiB |
BIN
VISUALIZACION/public/images/flujos_logo.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
BIN
VISUALIZACION/public/images/flujos_logo3.png
Executable file
|
After Width: | Height: | Size: 44 KiB |
BIN
VISUALIZACION/public/images/flujos_logo4.png
Executable file
|
After Width: | Height: | Size: 37 KiB |
BIN
VISUALIZACION/public/images/flujos_logo5.png
Executable file
|
After Width: | Height: | Size: 44 KiB |
BIN
VISUALIZACION/public/images/fujos5.jpg
Executable file
|
After Width: | Height: | Size: 163 KiB |
BIN
VISUALIZACION/public/images/journalist_fondo.jpg
Executable file
|
After Width: | Height: | Size: 81 KiB |
BIN
VISUALIZACION/public/images/journalist_fondo2.jpg
Executable file
|
After Width: | Height: | Size: 12 KiB |
BIN
VISUALIZACION/public/images/journalist_fondo3.jpg
Executable file
|
After Width: | Height: | Size: 38 KiB |
100
VISUALIZACION/public/index.html
Executable file
|
|
@ -0,0 +1,100 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<title>FLOWS</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&family=Nosifer&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<h1 class="title">FLOWS</h1>
|
||||
<div class="header-buttons">
|
||||
<a href="journalist.html" class="small-button">Journalist</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="glob-war.html" class="glob-war">GLOB-WAR</a></li>
|
||||
<li><a href="int-sec.html" class="int-sec">INT-SEC</a></li>
|
||||
<li><a href="climate.html" class="climate">CLIMATE</a></li>
|
||||
<li><a href="eco-corp.html" class="eco-corp">ECO-CORP</a></li>
|
||||
<li><a href="popl-up.html" class="popl-up">Popl-up</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
<div id="canvasContainer" style="position: absolute; width: 100%; height: 100%; opacity: 0.5;"></div>
|
||||
<div class="background">
|
||||
<a href="glob-war.html">
|
||||
<img class="img1" src="/images/flujos.jpg">
|
||||
</a>
|
||||
<a href="int-sec.html">
|
||||
<img class="img2" src="/images/fujos5.jpg">
|
||||
</a>
|
||||
<a href="climate.html">
|
||||
<img class="img3" src="/images/flujos6.jpg">
|
||||
</a>
|
||||
<a href="eco-corp.html">
|
||||
<img class="img4" src="/images/flujos4.jpg">
|
||||
</a>
|
||||
<a href="popl-up.html">
|
||||
<img class="img5" src="/images/flujos3.jpg">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Botones sobre las imágenes -->
|
||||
<div class="button-overlay">
|
||||
<div class="button-column">
|
||||
<a href="glob-war.html?subtematica=conflictos_internacionales" class="overlay-button">Conflictos Internacionales</a>
|
||||
<a href="glob-war.html?subtematica=guerras_civiles" class="overlay-button">Guerras Civiles</a>
|
||||
<a href="glob-war.html?subtematica=terrorismo" class="overlay-button">Terrorismo</a>
|
||||
<a href="glob-war.html?subtematica=armas" class="overlay-button">Armas</a>
|
||||
<a href="glob-war.html?subtematica=alianzas_militares" class="overlay-button">Alianzas Militares</a>
|
||||
</div>
|
||||
<div class="button-column">
|
||||
<a href="int-sec.html?subtematica=inteligencia" class="overlay-button">Inteligencia</a>
|
||||
<a href="int-sec.html?subtematica=ciberseguridad" class="overlay-button">Ciberseguridad</a>
|
||||
<a href="int-sec.html?subtematica=espionaje" class="overlay-button">Espionaje</a>
|
||||
<a href="int-sec.html?subtematica=seguridad_nacional" class="overlay-button">Seguridad Nacional</a>
|
||||
<a href="int-sec.html?subtematica=contraterrorismo" class="overlay-button">Contraterrorismo</a>
|
||||
</div>
|
||||
<div class="button-column">
|
||||
<a href="climate.html?subtematica=cambio_climatico" class="overlay-button">Cambio Climático</a>
|
||||
<a href="climate.html?subtematica=desastres_naturales" class="overlay-button">Desastres Naturales</a>
|
||||
<a href="climate.html?subtematica=conservacion" class="overlay-button">Conservación</a>
|
||||
<a href="climate.html?subtematica=energia_renovable" class="overlay-button">Energía Renovable</a>
|
||||
<a href="climate.html?subtematica=contaminacion" class="overlay-button">Escasez de agua</a>
|
||||
</div>
|
||||
<div class="button-column">
|
||||
<a href="eco-corp.html?subtematica=economia_global" class="overlay-button">Economía Global</a>
|
||||
<a href="eco-corp.html?subtematica=corporaciones_multinacionales" class="overlay-button">Corporaciones Multinacionales</a>
|
||||
<a href="eco-corp.html?subtematica=comercio_internacional" class="overlay-button">Comercio Internacional</a>
|
||||
<a href="eco-corp.html?subtematica=organismos_financieros" class="overlay-button">Organismos Financieros</a>
|
||||
<a href="eco-corp.html?subtematica=desigualdad_economica" class="overlay-button">Desigualdad Económica</a>
|
||||
</div>
|
||||
<div class="button-column">
|
||||
<a href="popl-up.html?subtematica=sobrepoblacion" class="overlay-button">Sobrepoblación</a>
|
||||
<a href="popl-up.html?subtematica=covid" class="overlay-button">COVID</a>
|
||||
<a href="popl-up.html?subtematica=migraciones" class="overlay-button">Migraciones</a>
|
||||
<a href="popl-up.html?subtematica=urbanizacion" class="overlay-button">Urbanización</a>
|
||||
<a href="popl-up.html?subtematica=distribucion_edad" class="overlay-button">Despoblaciòn rural</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
277
VISUALIZACION/public/int-sec.css
Executable file
|
|
@ -0,0 +1,277 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "Retrolift", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 6px 6px 6px #73ff00;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.glob-war:hover .logo { text-shadow: 2px 2px 8px #39ff14; }
|
||||
.int-sec:hover .logo { text-shadow: 2px 2px 8px #ff69b4; }
|
||||
.climate:hover .logo { text-shadow: 2px 2px 8px #ff4500; }
|
||||
.eco-corp:hover .logo { text-shadow: 2px 2px 8px #006400; }
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em;
|
||||
}
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
position: relative;
|
||||
border: none;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
align-items: center;
|
||||
border: 3px solid;
|
||||
}
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 2vw 1vw;
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
.glob-war { color: #FF4136; background-color: red; }
|
||||
.int-sec { color: #0074D9; background-color: darkblue; }
|
||||
.climate { color: #2ECC40; background-color: lightgreen; }
|
||||
.eco-corp { color: #FFDC00; background-color: yellow; }
|
||||
.popl-up { color: #FF851B; background-color: orange; }
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-90%); /* Oculta el 90%, deja 10% visible */
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size: 18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
#sidebar:hover {
|
||||
transform: translateX(0); /* Aparece entero al hacer hover */
|
||||
}
|
||||
#sidebar.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black;
|
||||
}
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14;
|
||||
background: black;
|
||||
color: #39ff14;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 1;
|
||||
}
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#intSecContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
background-color: #101020;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-links a {
|
||||
font-size: 0.8em;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.nav-links {
|
||||
gap: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
.fade-out {
|
||||
animation: fadeOut 2s forwards;
|
||||
}
|
||||
@keyframes fadeOut {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
/* ===== Añadidos para split-screen ===== */
|
||||
main.split-screen {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
margin-left: 0; /* El sidebar está fijo encima */
|
||||
}
|
||||
|
||||
#graphPanel {
|
||||
width: 100%;
|
||||
transition: width 0.3s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#detailPanel {
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
transition: width 0.3s ease;
|
||||
}
|
||||
|
||||
/* Al hacer click en un nodo */
|
||||
main.split-screen.show-detail #graphPanel {
|
||||
width: 45%;
|
||||
}
|
||||
main.split-screen.show-detail #detailPanel {
|
||||
width: 50%;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
/* Asegurar que el grafo ocupe todo su panel */
|
||||
#graphPanel #intSecContainer {
|
||||
position: absolute;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Estilos del panel de detalle */
|
||||
#detailPanel {
|
||||
background: #101020;
|
||||
color: #fff;
|
||||
box-shadow: inset 1px 0 5px rgba(0,0,0,0.5);
|
||||
}
|
||||
#detailPanel h2 {
|
||||
margin-bottom: .5em;
|
||||
color: #39ff14;
|
||||
}
|
||||
#detailPanel p {
|
||||
line-height: 1.4;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
#detailPanel .placeholder {
|
||||
color: rgba(255,255,255,0.3);
|
||||
font-style: italic;
|
||||
}
|
||||
89
VISUALIZACION/public/int-sec.html
Executable file
|
|
@ -0,0 +1,89 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Inteligencia y Seguridad</title>
|
||||
<link rel="stylesheet" href="int-sec.css">
|
||||
<!-- Fuentes de Google Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Cargar D3.js -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
|
||||
<!-- Cargar 3d-force-graph (incluye Three.js) -->
|
||||
<script src="https://unpkg.com/3d-force-graph"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="int-sec.html" class="int-sec">Inteligencia y Seguridad</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<main class="split-screen">
|
||||
<!-- PANEL IZQUIERDO: el grafo -->
|
||||
<div id="graphPanel">
|
||||
<div id="intSecContainer"></div>
|
||||
<div class="background">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<img src="/images/flujos.jpg">
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
const fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PANEL DERECHO: detalle de la noticia -->
|
||||
<div id="detailPanel">
|
||||
<p class="placeholder">Haz click en un nodo para ver aquí la noticia completa.</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="100">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="40" value="20">
|
||||
|
||||
<label for="param1">Búsqueda por palabra:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="param2">Búsqueda por temática personalizada:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
<a href="#">GitHub</a> |
|
||||
<a href="#">Telegram</a> |
|
||||
<a href="#">Email</a> |
|
||||
<a href="#">Web de Tor</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Incluir tu script al final del body -->
|
||||
<script src="output_int_sec.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
132
VISUALIZACION/public/journalist.css
Executable file
|
|
@ -0,0 +1,132 @@
|
|||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #000000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #ffffff; /* Cambiar el color del texto a blanco */
|
||||
}
|
||||
|
||||
/* Estilo del formulario */
|
||||
.login-container {
|
||||
max-width: 400px;
|
||||
margin: 30px auto;
|
||||
background-color: #111111; /* Fondo negro */
|
||||
border: 2px solid #39ff14; /* Borde verde claro */
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
position: relative; /* Añadimos posición relativa para que los elementos internos se posicionen respecto a este contenedor */
|
||||
}
|
||||
|
||||
|
||||
/* ... Estilos existentes ... */
|
||||
|
||||
/* Estilos para los enlaces dentro del formulario */
|
||||
.login-container a {
|
||||
color: #39ff14; /* Cambiar el color del enlace a verde claro */
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.login-container a:hover {
|
||||
color: #2ECC40; /* Cambiar el color del enlace en hover a verde más claro */
|
||||
}
|
||||
|
||||
/* ... Resto de tus estilos ... */
|
||||
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
color: #39ff14; /* Cambiar el color del título a verde claro */
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 8px;
|
||||
color: #39ff14; /* Cambiar el color de las etiquetas a verde claro */
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
background-color: #222222; /* Fondo negro */
|
||||
color: #ffffff; /* Texto blanco */
|
||||
}
|
||||
|
||||
input[type="submit"] {
|
||||
background-color: #007BFF;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input[type="submit"]:hover {
|
||||
background-color: #0056b3;
|
||||
border: 2px solid #39ff14; /* Borde verde claro en hover */
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 0px; /* Añadir margen inferior para separar el formulario del logo */
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 400px; /* Ajustar el tamaño de la imagen según sea necesario */
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Estilos para las imágenes de fondo */
|
||||
.canvas-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
min-height: 100vh; /* Ajusta la altura mínima para que ocupe toda la pantalla */
|
||||
margin: 20px 0;
|
||||
overflow: hidden; /* Evita que las imágenes desborden del contenedor */
|
||||
}
|
||||
|
||||
.image-left,
|
||||
.image-right {
|
||||
height: 100vh; /* Ajusta la altura para que ocupe toda la pantalla */
|
||||
width: auto; /* Ajusta el ancho de las imágenes para mantener la relación de aspecto */
|
||||
position: absolute;
|
||||
top: 0;
|
||||
max-width: 40%; /* Ajusta el ancho máximo de las imágenes de fondo */
|
||||
}
|
||||
|
||||
.image-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.image-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.login-content {
|
||||
/* Ajusta estos estilos según tus necesidades */
|
||||
padding: 20px;
|
||||
margin: 0 auto;
|
||||
max-width: 300px; /* Ajusta el ancho máximo del contenido */
|
||||
position: relative; /* Añadimos posición relativa para que los elementos internos se posicionen respecto a este contenedor */
|
||||
}
|
||||
|
||||
/* Añade el siguiente estilo para evitar que las imágenes desborden del contenedor */
|
||||
.login-content > img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
66
VISUALIZACION/public/journalist.html
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Journalist Login</title>
|
||||
<link rel="stylesheet" href="journalist.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<img class="logo" src="/images/flujos_logo5.png" alt="Flujos Logo">
|
||||
</div>
|
||||
|
||||
<div class="canvas-container">
|
||||
<img class="image-left" src="/images/journalist_fondo.jpg" alt="Fondo izquierdo">
|
||||
<div class="login-container">
|
||||
<h1>Journalist Login</h1>
|
||||
<form onsubmit="login(event)">
|
||||
<label for="username">Username:</label>
|
||||
<input type="text" id="username" name="username" required>
|
||||
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
|
||||
<label for="publicKey">Public Key:</label>
|
||||
<input type="text" id="publicKey" name="publicKey" required>
|
||||
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
</div>
|
||||
<img class="image-right" src="/images/journalist_fondo2.jpg" alt="Fondo derecho">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function login(event) {
|
||||
event.preventDefault(); // Evitar que el formulario se envíe por defecto
|
||||
|
||||
const username = document.getElementById('username').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const publicKey = document.getElementById('publicKey').value;
|
||||
|
||||
// Enviar los datos del formulario mediante una petición AJAX a nuestro endpoint de login
|
||||
fetch('/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ username, password, publicKey })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Si el servidor devuelve un redireccionamiento, redirigimos al usuario
|
||||
if (data.redirect) {
|
||||
window.location.href = data.redirect;
|
||||
} else {
|
||||
// Si no hay redireccionamiento, se podría mostrar un mensaje de error
|
||||
console.log('Credenciales inválidas');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error en la petición AJAX:', error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
377
VISUALIZACION/public/journalist_enter.css
Executable file
|
|
@ -0,0 +1,377 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
header {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
background-color: #000000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 400px;
|
||||
height: 140px;
|
||||
margin-left: 400px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.small-button {
|
||||
margin-left: 5px;
|
||||
margin-right: 3px;
|
||||
padding: 4px 8px;
|
||||
font-size: 10px;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background-color: #000000;
|
||||
border: 2px solid #ffffff;
|
||||
border-radius: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.small-button:hover {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
/* ... Resto de tus estilos ... */
|
||||
|
||||
|
||||
/* ... Estilos existentes ... */
|
||||
|
||||
|
||||
|
||||
|
||||
.logo {
|
||||
/* Ajusta el tamaño de la imagen según tus necesidades */
|
||||
width: 400px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 20px;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.buttons a {
|
||||
display: block;
|
||||
margin-left: 10px;
|
||||
padding: 10px 15px;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
border: 1px solid #ffffff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.glob-war:hover .logo { text-shadow: 2px 2px 8px #39ff14; }
|
||||
.int-sec:hover .logo { text-shadow: 2px 2px 8px #ff69b4; }
|
||||
.climate:hover .logo { text-shadow: 2px 2px 8px #ff4500; }
|
||||
.eco-corp:hover .logo { text-shadow: 2px 2px 8px #006400; }
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
|
||||
/* Estilo de los botones */
|
||||
position:relative;
|
||||
border: none;
|
||||
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border:3vw;
|
||||
|
||||
align-items: center;
|
||||
border: 3px solid ;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
|
||||
/* Estilo hover de los botones */
|
||||
|
||||
box-shadow: 2vw 1vw;
|
||||
|
||||
border: 3px solid black ;
|
||||
}
|
||||
|
||||
.glob-war:hover { color: #39ff14; }
|
||||
.int-sec:hover { color: #ff69b4; }
|
||||
.climate:hover { color: #ff4500; }
|
||||
.eco-corp:hover { color: #00fff2; }
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
|
||||
.glob-war {
|
||||
color: #FF4136;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.int-sec {
|
||||
color: #0074D9;
|
||||
background-color: darkblue;
|
||||
}
|
||||
|
||||
.climate {
|
||||
color: #2ECC40;
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
.eco-corp {
|
||||
color: #FFDC00;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.popl-up {
|
||||
color: #FF851B;
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background a img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
|
||||
#sidebar.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-90%);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size:18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
position: absolute;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
background: #007BFF;
|
||||
color: #39ff14;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background 0.3s ease;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size:20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; /* Añade el borde al texto */
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14; /* Añade el borde verde al input */
|
||||
background: black; /* Cambia el fondo del input a negro */
|
||||
color: #39ff14; /* Cambia el color del texto en el input a verde */
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#canvasContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
/* ... Estilos existentes ... */
|
||||
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-links a {
|
||||
font-size: 0.8em; /* reduce el tamaño de la fuente */
|
||||
padding: 10px 20px; /* reduce el padding */
|
||||
}
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 2em; /* incrementa la distancia entre los elementos */
|
||||
}
|
||||
}
|
||||
79
VISUALIZACION/public/journalist_enter.html
Executable file
|
|
@ -0,0 +1,79 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Journalist Enter</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Header -->
|
||||
<header>
|
||||
<div class="header-content">
|
||||
<img src="/images/flujos_logo5.png" alt="FLUJØS 3D Logo" class="logo">
|
||||
<div class="header-buttons">
|
||||
<a href="login.html" class="small-button">Login/Sign Up</a>
|
||||
<div class="small-button">Language</div> <!-- El botón de idioma con el dropdown se implementará más adelante -->
|
||||
<a href="journalist.html" class="small-button">Journalist</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Sidebar Toggle Button -->
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
<!-- Graficos generados por el script de output.js -->
|
||||
<div id="canvasContainer"></div>
|
||||
<div class="background">
|
||||
<!-- Enlaces a otras páginas -->
|
||||
<a href="glob-war.html">
|
||||
<img class="img1" src="/images/flujos.jpg">
|
||||
</a>
|
||||
<a href="int-sec.html">
|
||||
<img class="img2" src="/images/fujos5.jpg">
|
||||
</a>
|
||||
<a href="climate.html">
|
||||
<img class="img3" src="/images/flujos6.jpg">
|
||||
</a>
|
||||
<a href="eco-corp.html">
|
||||
<img class="img4" src="/images/flujos4.jpg">
|
||||
</a>
|
||||
<a href="popl-up.html">
|
||||
<img class="img5" src="/images/flujos3.jpg">
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Sidebar with Parameters -->
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form>
|
||||
<!-- Aquí van los parámetros específicos para añadir nodos -->
|
||||
<label for="nodo_nombre">Nombre del Nodo:</label>
|
||||
<input type="text" id="nodo_nombre" name="nodo_nombre" required>
|
||||
|
||||
<label for="nodo_descripcion">Descripción del Nodo:</label>
|
||||
<input type="text" id="nodo_descripcion" name="nodo_descripcion" required>
|
||||
|
||||
<label for="nodo_imagen">Imagen del Nodo:</label>
|
||||
<input type="file" id="nodo_imagen" name="nodo_imagen" accept="image/*" required>
|
||||
|
||||
<input type="submit" value="Añadir Nodo">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<p><a href="#">GitHub</a> | <a href="#">Telegram</a> | <a href="#">Email</a> | <a href="#">Web de Tor</a></p>
|
||||
</footer>
|
||||
|
||||
<!-- Script para los gráficos generados por output.js -->
|
||||
<script src="output.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
438
VISUALIZACION/public/libs/3d-force-graph.js
Executable file
|
|
@ -0,0 +1,438 @@
|
|||
import { AmbientLight, DirectionalLight, Vector3, REVISION } from "./three.module.js";
|
||||
|
||||
|
||||
const three = window.THREE
|
||||
? window.THREE // Prefer consumption from global THREE, if exists
|
||||
: { AmbientLight, DirectionalLight, Vector3, REVISION };
|
||||
|
||||
import { DragControls as ThreeDragControls } from './DragControls.js';
|
||||
|
||||
import ThreeForceGraph from "./three-forcegraph.js";
|
||||
import ThreeRenderObjects from "./three-render-objects.js";
|
||||
|
||||
import accessorFn from "./accessor-fn.js";
|
||||
import Kapsule from "./kapsule.js";
|
||||
|
||||
import linkKapsule from './kapsule-link.js';
|
||||
|
||||
//
|
||||
|
||||
const CAMERA_DISTANCE2NODES_FACTOR = 170;
|
||||
|
||||
//
|
||||
|
||||
// Expose config from forceGraph
|
||||
const bindFG = linkKapsule('forceGraph', ThreeForceGraph);
|
||||
const linkedFGProps = Object.assign(...[
|
||||
'jsonUrl',
|
||||
'graphData',
|
||||
'numDimensions',
|
||||
'dagMode',
|
||||
'dagLevelDistance',
|
||||
'dagNodeFilter',
|
||||
'onDagError',
|
||||
'nodeRelSize',
|
||||
'nodeId',
|
||||
'nodeVal',
|
||||
'nodeResolution',
|
||||
'nodeColor',
|
||||
'nodeAutoColorBy',
|
||||
'nodeOpacity',
|
||||
'nodeVisibility',
|
||||
'nodeThreeObject',
|
||||
'nodeThreeObjectExtend',
|
||||
'linkSource',
|
||||
'linkTarget',
|
||||
'linkVisibility',
|
||||
'linkColor',
|
||||
'linkAutoColorBy',
|
||||
'linkOpacity',
|
||||
'linkWidth',
|
||||
'linkResolution',
|
||||
'linkCurvature',
|
||||
'linkCurveRotation',
|
||||
'linkMaterial',
|
||||
'linkThreeObject',
|
||||
'linkThreeObjectExtend',
|
||||
'linkPositionUpdate',
|
||||
'linkDirectionalArrowLength',
|
||||
'linkDirectionalArrowColor',
|
||||
'linkDirectionalArrowRelPos',
|
||||
'linkDirectionalArrowResolution',
|
||||
'linkDirectionalParticles',
|
||||
'linkDirectionalParticleSpeed',
|
||||
'linkDirectionalParticleWidth',
|
||||
'linkDirectionalParticleColor',
|
||||
'linkDirectionalParticleResolution',
|
||||
'forceEngine',
|
||||
'd3AlphaDecay',
|
||||
'd3VelocityDecay',
|
||||
'd3AlphaMin',
|
||||
'ngraphPhysics',
|
||||
'warmupTicks',
|
||||
'cooldownTicks',
|
||||
'cooldownTime',
|
||||
'onEngineTick',
|
||||
'onEngineStop'
|
||||
].map(p => ({ [p]: bindFG.linkProp(p)})));
|
||||
const linkedFGMethods = Object.assign(...[
|
||||
'refresh',
|
||||
'getGraphBbox',
|
||||
'd3Force',
|
||||
'd3ReheatSimulation',
|
||||
'emitParticle'
|
||||
].map(p => ({ [p]: bindFG.linkMethod(p)})));
|
||||
|
||||
// Expose config from renderObjs
|
||||
const bindRenderObjs = linkKapsule('renderObjs', ThreeRenderObjects);
|
||||
const linkedRenderObjsProps = Object.assign(...[
|
||||
'width',
|
||||
'height',
|
||||
'backgroundColor',
|
||||
'showNavInfo',
|
||||
'enablePointerInteraction'
|
||||
].map(p => ({ [p]: bindRenderObjs.linkProp(p)})));
|
||||
const linkedRenderObjsMethods = Object.assign(
|
||||
...[
|
||||
'lights',
|
||||
'cameraPosition',
|
||||
'postProcessingComposer'
|
||||
].map(p => ({ [p]: bindRenderObjs.linkMethod(p)})),
|
||||
{
|
||||
graph2ScreenCoords: bindRenderObjs.linkMethod('getScreenCoords'),
|
||||
screen2GraphCoords: bindRenderObjs.linkMethod('getSceneCoords')
|
||||
}
|
||||
);
|
||||
|
||||
//
|
||||
|
||||
export default Kapsule({
|
||||
|
||||
props: {
|
||||
nodeLabel: { default: 'name', triggerUpdate: false },
|
||||
linkLabel: { default: 'name', triggerUpdate: false },
|
||||
linkHoverPrecision: { default: 1, onChange: (p, state) => state.renderObjs.lineHoverPrecision(p), triggerUpdate: false },
|
||||
enableNavigationControls: {
|
||||
default: true,
|
||||
onChange(enable, state) {
|
||||
const controls = state.renderObjs.controls();
|
||||
if (controls) {
|
||||
controls.enabled = enable;
|
||||
// trigger mouseup on re-enable to prevent sticky controls
|
||||
enable && controls.domElement && controls.domElement.dispatchEvent(new PointerEvent('pointerup'));
|
||||
}
|
||||
},
|
||||
triggerUpdate: false
|
||||
},
|
||||
enableNodeDrag: { default: true, triggerUpdate: false },
|
||||
onNodeDrag: { default: () => {}, triggerUpdate: false },
|
||||
onNodeDragEnd: { default: () => {}, triggerUpdate: false },
|
||||
onNodeClick: { triggerUpdate: false },
|
||||
onNodeRightClick: { triggerUpdate: false },
|
||||
onNodeHover: { triggerUpdate: false },
|
||||
onLinkClick: { triggerUpdate: false },
|
||||
onLinkRightClick: { triggerUpdate: false },
|
||||
onLinkHover: { triggerUpdate: false },
|
||||
onBackgroundClick: { triggerUpdate: false },
|
||||
onBackgroundRightClick: { triggerUpdate: false },
|
||||
...linkedFGProps,
|
||||
...linkedRenderObjsProps
|
||||
},
|
||||
|
||||
methods: {
|
||||
zoomToFit: function(state, transitionDuration, padding, ...bboxArgs) {
|
||||
state.renderObjs.fitToBbox(
|
||||
state.forceGraph.getGraphBbox(...bboxArgs),
|
||||
transitionDuration,
|
||||
padding
|
||||
);
|
||||
return this;
|
||||
},
|
||||
pauseAnimation: function(state) {
|
||||
if (state.animationFrameRequestId !== null) {
|
||||
cancelAnimationFrame(state.animationFrameRequestId);
|
||||
state.animationFrameRequestId = null;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
resumeAnimation: function(state) {
|
||||
if (state.animationFrameRequestId === null) {
|
||||
this._animationCycle();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
_animationCycle(state) {
|
||||
if (state.enablePointerInteraction) {
|
||||
// reset canvas cursor (override dragControls cursor)
|
||||
this.renderer().domElement.style.cursor = null;
|
||||
}
|
||||
|
||||
// Frame cycle
|
||||
state.forceGraph.tickFrame();
|
||||
state.renderObjs.tick();
|
||||
state.animationFrameRequestId = requestAnimationFrame(this._animationCycle);
|
||||
},
|
||||
scene: state => state.renderObjs.scene(), // Expose scene
|
||||
camera: state => state.renderObjs.camera(), // Expose camera
|
||||
renderer: state => state.renderObjs.renderer(), // Expose renderer
|
||||
controls: state => state.renderObjs.controls(), // Expose controls
|
||||
tbControls: state => state.renderObjs.tbControls(), // To be deprecated
|
||||
_destructor: function() {
|
||||
this.pauseAnimation();
|
||||
this.graphData({ nodes: [], links: []});
|
||||
},
|
||||
...linkedFGMethods,
|
||||
...linkedRenderObjsMethods
|
||||
},
|
||||
|
||||
stateInit: ({ controlType, rendererConfig, extraRenderers }) => {
|
||||
const forceGraph = new ThreeForceGraph();
|
||||
return {
|
||||
forceGraph,
|
||||
renderObjs: ThreeRenderObjects({ controlType, rendererConfig, extraRenderers })
|
||||
.objects([forceGraph]) // Populate scene
|
||||
.lights([
|
||||
new three.AmbientLight(0xcccccc, Math.PI),
|
||||
new three.DirectionalLight(0xffffff, 0.6 * Math.PI)
|
||||
])
|
||||
}
|
||||
},
|
||||
|
||||
init: function(domNode, state) {
|
||||
// Wipe DOM
|
||||
domNode.innerHTML = '';
|
||||
|
||||
// Add relative container
|
||||
domNode.appendChild(state.container = document.createElement('div'));
|
||||
state.container.style.position = 'relative';
|
||||
|
||||
// Add renderObjs
|
||||
const roDomNode = document.createElement('div');
|
||||
state.container.appendChild(roDomNode);
|
||||
state.renderObjs(roDomNode);
|
||||
const camera = state.renderObjs.camera();
|
||||
const renderer = state.renderObjs.renderer();
|
||||
const controls = state.renderObjs.controls();
|
||||
controls.enabled = !!state.enableNavigationControls;
|
||||
state.lastSetCameraZ = camera.position.z;
|
||||
|
||||
// Add info space
|
||||
let infoElem;
|
||||
state.container.appendChild(infoElem = document.createElement('div'));
|
||||
infoElem.className = 'graph-info-msg';
|
||||
infoElem.textContent = '';
|
||||
|
||||
// config forcegraph
|
||||
state.forceGraph
|
||||
.onLoading(() => { infoElem.textContent = 'Loading...' })
|
||||
.onFinishLoading(() => { infoElem.textContent = '' })
|
||||
.onUpdate(() => {
|
||||
// sync graph data structures
|
||||
state.graphData = state.forceGraph.graphData();
|
||||
|
||||
// re-aim camera, if still in default position (not user modified)
|
||||
if (camera.position.x === 0 && camera.position.y === 0 && camera.position.z === state.lastSetCameraZ && state.graphData.nodes.length) {
|
||||
camera.lookAt(state.forceGraph.position);
|
||||
state.lastSetCameraZ = camera.position.z = Math.cbrt(state.graphData.nodes.length) * CAMERA_DISTANCE2NODES_FACTOR;
|
||||
}
|
||||
})
|
||||
.onFinishUpdate(() => {
|
||||
// Setup node drag interaction
|
||||
if (state._dragControls) {
|
||||
const curNodeDrag = state.graphData.nodes.find(node => node.__initialFixedPos && !node.__disposeControlsAfterDrag); // detect if there's a node being dragged using the existing drag controls
|
||||
if (curNodeDrag) {
|
||||
curNodeDrag.__disposeControlsAfterDrag = true; // postpone previous controls disposal until drag ends
|
||||
} else {
|
||||
state._dragControls.dispose(); // cancel previous drag controls
|
||||
}
|
||||
|
||||
state._dragControls = undefined;
|
||||
}
|
||||
|
||||
if (state.enableNodeDrag && state.enablePointerInteraction && state.forceEngine === 'd3') { // Can't access node positions programmatically in ngraph
|
||||
const dragControls = state._dragControls = new ThreeDragControls(
|
||||
state.graphData.nodes.map(node => node.__threeObj).filter(obj => obj),
|
||||
camera,
|
||||
renderer.domElement
|
||||
);
|
||||
|
||||
dragControls.addEventListener('dragstart', function (event) {
|
||||
controls.enabled = false; // Disable controls while dragging
|
||||
|
||||
// track drag object movement
|
||||
event.object.__initialPos = event.object.position.clone();
|
||||
event.object.__prevPos = event.object.position.clone();
|
||||
|
||||
const node = getGraphObj(event.object).__data;
|
||||
!node.__initialFixedPos && (node.__initialFixedPos = {fx: node.fx, fy: node.fy, fz: node.fz});
|
||||
!node.__initialPos && (node.__initialPos = {x: node.x, y: node.y, z: node.z});
|
||||
|
||||
// lock node
|
||||
['x', 'y', 'z'].forEach(c => node[`f${c}`] = node[c]);
|
||||
|
||||
// drag cursor
|
||||
renderer.domElement.classList.add('grabbable');
|
||||
});
|
||||
|
||||
dragControls.addEventListener('drag', function (event) {
|
||||
const nodeObj = getGraphObj(event.object);
|
||||
|
||||
if (!event.object.hasOwnProperty('__graphObjType')) {
|
||||
// If dragging a child of the node, update the node object instead
|
||||
const initPos = event.object.__initialPos;
|
||||
const prevPos = event.object.__prevPos;
|
||||
const newPos = event.object.position;
|
||||
|
||||
nodeObj.position.add(newPos.clone().sub(prevPos)); // translate node object by the motion delta
|
||||
prevPos.copy(newPos);
|
||||
newPos.copy(initPos); // reset child back to its initial position
|
||||
}
|
||||
|
||||
const node = nodeObj.__data;
|
||||
const newPos = nodeObj.position;
|
||||
const translate = {x: newPos.x - node.x, y: newPos.y - node.y, z: newPos.z - node.z};
|
||||
// Move fx/fy/fz (and x/y/z) of nodes based on object new position
|
||||
['x', 'y', 'z'].forEach(c => node[`f${c}`] = node[c] = newPos[c]);
|
||||
|
||||
state.forceGraph
|
||||
.d3AlphaTarget(0.3) // keep engine running at low intensity throughout drag
|
||||
.resetCountdown(); // prevent freeze while dragging
|
||||
|
||||
node.__dragged = true;
|
||||
state.onNodeDrag(node, translate);
|
||||
});
|
||||
|
||||
dragControls.addEventListener('dragend', function (event) {
|
||||
delete(event.object.__initialPos); // remove tracking attributes
|
||||
delete(event.object.__prevPos);
|
||||
|
||||
const node = getGraphObj(event.object).__data;
|
||||
|
||||
// dispose previous controls if needed
|
||||
if (node.__disposeControlsAfterDrag) {
|
||||
dragControls.dispose();
|
||||
delete(node.__disposeControlsAfterDrag);
|
||||
}
|
||||
|
||||
const initFixedPos = node.__initialFixedPos;
|
||||
const initPos = node.__initialPos;
|
||||
const translate = {x: initPos.x - node.x, y: initPos.y - node.y, z: initPos.z - node.z};
|
||||
if (initFixedPos) {
|
||||
['x', 'y', 'z'].forEach(c => {
|
||||
const fc = `f${c}`;
|
||||
if (initFixedPos[fc] === undefined) {
|
||||
delete(node[fc])
|
||||
}
|
||||
});
|
||||
delete(node.__initialFixedPos);
|
||||
delete(node.__initialPos);
|
||||
if (node.__dragged) {
|
||||
delete(node.__dragged);
|
||||
state.onNodeDragEnd(node, translate);
|
||||
}
|
||||
}
|
||||
|
||||
state.forceGraph
|
||||
.d3AlphaTarget(0) // release engine low intensity
|
||||
.resetCountdown(); // let the engine readjust after releasing fixed nodes
|
||||
|
||||
if (state.enableNavigationControls) {
|
||||
controls.enabled = true; // Re-enable controls
|
||||
controls.domElement && controls.domElement.ownerDocument && controls.domElement.ownerDocument.dispatchEvent(
|
||||
// simulate mouseup to ensure the controls don't take over after dragend
|
||||
new PointerEvent('pointerup', { pointerType: 'touch' })
|
||||
);
|
||||
}
|
||||
|
||||
// clear cursor
|
||||
renderer.domElement.classList.remove('grabbable');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// config renderObjs
|
||||
three.REVISION < 155 && (state.renderObjs.renderer().useLegacyLights = false); // force behavior for three < 155
|
||||
state.renderObjs
|
||||
.hoverOrderComparator((a, b) => {
|
||||
// Prioritize graph objects
|
||||
const aObj = getGraphObj(a);
|
||||
if (!aObj) return 1;
|
||||
const bObj = getGraphObj(b);
|
||||
if (!bObj) return -1;
|
||||
|
||||
// Prioritize nodes over links
|
||||
const isNode = o => o.__graphObjType === 'node';
|
||||
return isNode(bObj) - isNode(aObj);
|
||||
})
|
||||
.tooltipContent(obj => {
|
||||
const graphObj = getGraphObj(obj);
|
||||
return graphObj ? accessorFn(state[`${graphObj.__graphObjType}Label`])(graphObj.__data) || '' : '';
|
||||
})
|
||||
.hoverDuringDrag(false)
|
||||
.onHover(obj => {
|
||||
// Update tooltip and trigger onHover events
|
||||
const hoverObj = getGraphObj(obj);
|
||||
|
||||
if (hoverObj !== state.hoverObj) {
|
||||
const prevObjType = state.hoverObj ? state.hoverObj.__graphObjType : null;
|
||||
const prevObjData = state.hoverObj ? state.hoverObj.__data : null;
|
||||
const objType = hoverObj ? hoverObj.__graphObjType : null;
|
||||
const objData = hoverObj ? hoverObj.__data : null;
|
||||
if (prevObjType && prevObjType !== objType) {
|
||||
// Hover out
|
||||
const fn = state[`on${prevObjType === 'node' ? 'Node' : 'Link'}Hover`];
|
||||
fn && fn(null, prevObjData);
|
||||
}
|
||||
if (objType) {
|
||||
// Hover in
|
||||
const fn = state[`on${objType === 'node' ? 'Node' : 'Link'}Hover`];
|
||||
fn && fn(objData, prevObjType === objType ? prevObjData : null);
|
||||
}
|
||||
|
||||
// set pointer if hovered object is clickable
|
||||
renderer.domElement.classList[
|
||||
((hoverObj && state[`on${objType === 'node' ? 'Node' : 'Link'}Click`]) || (!hoverObj && state.onBackgroundClick)) ? 'add' : 'remove'
|
||||
]('clickable');
|
||||
|
||||
state.hoverObj = hoverObj;
|
||||
}
|
||||
})
|
||||
.clickAfterDrag(false)
|
||||
.onClick((obj, ev) => {
|
||||
const graphObj = getGraphObj(obj);
|
||||
if (graphObj) {
|
||||
const fn = state[`on${graphObj.__graphObjType === 'node' ? 'Node' : 'Link'}Click`];
|
||||
fn && fn(graphObj.__data, ev);
|
||||
} else {
|
||||
state.onBackgroundClick && state.onBackgroundClick(ev);
|
||||
}
|
||||
})
|
||||
.onRightClick((obj, ev) => {
|
||||
// Handle right-click events
|
||||
const graphObj = getGraphObj(obj);
|
||||
if (graphObj) {
|
||||
const fn = state[`on${graphObj.__graphObjType === 'node' ? 'Node' : 'Link'}RightClick`];
|
||||
fn && fn(graphObj.__data, ev);
|
||||
} else {
|
||||
state.onBackgroundRightClick && state.onBackgroundRightClick(ev);
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
// Kick-off renderer
|
||||
this._animationCycle();
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
|
||||
function getGraphObj(object) {
|
||||
let obj = object;
|
||||
// recurse up object chain until finding the graph object
|
||||
while (obj && !obj.hasOwnProperty('__graphObjType')) {
|
||||
obj = obj.parent;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
410
VISUALIZACION/public/libs/DragControls.js
Executable file
|
|
@ -0,0 +1,410 @@
|
|||
import {
|
||||
Controls,
|
||||
Matrix4,
|
||||
Plane,
|
||||
Raycaster,
|
||||
Vector2,
|
||||
Vector3,
|
||||
MOUSE,
|
||||
TOUCH
|
||||
} from './three.module.js';
|
||||
|
||||
const _plane = new Plane();
|
||||
|
||||
const _pointer = new Vector2();
|
||||
const _offset = new Vector3();
|
||||
const _diff = new Vector2();
|
||||
const _previousPointer = new Vector2();
|
||||
const _intersection = new Vector3();
|
||||
const _worldPosition = new Vector3();
|
||||
const _inverseMatrix = new Matrix4();
|
||||
|
||||
const _up = new Vector3();
|
||||
const _right = new Vector3();
|
||||
|
||||
let _selected = null, _hovered = null;
|
||||
const _intersections = [];
|
||||
|
||||
const STATE = {
|
||||
NONE: - 1,
|
||||
PAN: 0,
|
||||
ROTATE: 1
|
||||
};
|
||||
|
||||
class DragControls extends Controls {
|
||||
|
||||
constructor( objects, camera, domElement = null ) {
|
||||
|
||||
super( camera, domElement );
|
||||
|
||||
this.objects = objects;
|
||||
|
||||
this.recursive = true;
|
||||
this.transformGroup = false;
|
||||
this.rotateSpeed = 1;
|
||||
|
||||
this.raycaster = new Raycaster();
|
||||
|
||||
// interaction
|
||||
|
||||
this.mouseButtons = { LEFT: MOUSE.PAN, MIDDLE: MOUSE.PAN, RIGHT: MOUSE.ROTATE };
|
||||
this.touches = { ONE: TOUCH.PAN };
|
||||
|
||||
// event listeners
|
||||
|
||||
this._onPointerMove = onPointerMove.bind( this );
|
||||
this._onPointerDown = onPointerDown.bind( this );
|
||||
this._onPointerCancel = onPointerCancel.bind( this );
|
||||
this._onContextMenu = onContextMenu.bind( this );
|
||||
|
||||
//
|
||||
|
||||
if ( domElement !== null ) {
|
||||
|
||||
this.connect();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
connect() {
|
||||
|
||||
this.domElement.addEventListener( 'pointermove', this._onPointerMove );
|
||||
this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
|
||||
this.domElement.addEventListener( 'pointerup', this._onPointerCancel );
|
||||
this.domElement.addEventListener( 'pointerleave', this._onPointerCancel );
|
||||
this.domElement.addEventListener( 'contextmenu', this._onContextMenu );
|
||||
|
||||
this.domElement.style.touchAction = 'none'; // disable touch scroll
|
||||
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
|
||||
this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
|
||||
this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
|
||||
this.domElement.removeEventListener( 'pointerup', this._onPointerCancel );
|
||||
this.domElement.removeEventListener( 'pointerleave', this._onPointerCancel );
|
||||
this.domElement.removeEventListener( 'contextmenu', this._onContextMenu );
|
||||
|
||||
this.domElement.style.touchAction = 'auto';
|
||||
this.domElement.style.cursor = '';
|
||||
|
||||
}
|
||||
|
||||
dispose() {
|
||||
|
||||
this.disconnect();
|
||||
|
||||
}
|
||||
|
||||
_updatePointer( event ) {
|
||||
|
||||
const rect = this.domElement.getBoundingClientRect();
|
||||
|
||||
_pointer.x = ( event.clientX - rect.left ) / rect.width * 2 - 1;
|
||||
_pointer.y = - ( event.clientY - rect.top ) / rect.height * 2 + 1;
|
||||
|
||||
}
|
||||
|
||||
_updateState( event ) {
|
||||
|
||||
// determine action
|
||||
|
||||
let action;
|
||||
|
||||
if ( event.pointerType === 'touch' ) {
|
||||
|
||||
action = this.touches.ONE;
|
||||
|
||||
} else {
|
||||
|
||||
switch ( event.button ) {
|
||||
|
||||
case 0:
|
||||
|
||||
action = this.mouseButtons.LEFT;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
action = this.mouseButtons.MIDDLE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
action = this.mouseButtons.RIGHT;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
action = null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// determine state
|
||||
|
||||
switch ( action ) {
|
||||
|
||||
case MOUSE.PAN:
|
||||
case TOUCH.PAN:
|
||||
|
||||
this.state = STATE.PAN;
|
||||
|
||||
break;
|
||||
|
||||
case MOUSE.ROTATE:
|
||||
case TOUCH.ROTATE:
|
||||
|
||||
this.state = STATE.ROTATE;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
this.state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getRaycaster() {
|
||||
|
||||
console.warn( 'THREE.DragControls: getRaycaster() has been deprecated. Use controls.raycaster instead.' ); // @deprecated r169
|
||||
|
||||
return this.raycaster;
|
||||
|
||||
}
|
||||
|
||||
setObjects( objects ) {
|
||||
|
||||
console.warn( 'THREE.DragControls: setObjects() has been deprecated. Use controls.objects instead.' ); // @deprecated r169
|
||||
|
||||
this.objects = objects;
|
||||
|
||||
}
|
||||
|
||||
getObjects() {
|
||||
|
||||
console.warn( 'THREE.DragControls: getObjects() has been deprecated. Use controls.objects instead.' ); // @deprecated r169
|
||||
|
||||
return this.objects;
|
||||
|
||||
}
|
||||
|
||||
activate() {
|
||||
|
||||
console.warn( 'THREE.DragControls: activate() has been renamed to connect().' ); // @deprecated r169
|
||||
this.connect();
|
||||
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
|
||||
console.warn( 'THREE.DragControls: deactivate() has been renamed to disconnect().' ); // @deprecated r169
|
||||
this.disconnect();
|
||||
|
||||
}
|
||||
|
||||
set mode( value ) {
|
||||
|
||||
console.warn( 'THREE.DragControls: The .mode property has been removed. Define the type of transformation via the .mouseButtons or .touches properties.' ); // @deprecated r169
|
||||
|
||||
}
|
||||
|
||||
get mode() {
|
||||
|
||||
console.warn( 'THREE.DragControls: The .mode property has been removed. Define the type of transformation via the .mouseButtons or .touches properties.' ); // @deprecated r169
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function onPointerMove( event ) {
|
||||
|
||||
const camera = this.object;
|
||||
const domElement = this.domElement;
|
||||
const raycaster = this.raycaster;
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
this._updatePointer( event );
|
||||
|
||||
raycaster.setFromCamera( _pointer, camera );
|
||||
|
||||
if ( _selected ) {
|
||||
|
||||
if ( this.state === STATE.PAN ) {
|
||||
|
||||
if ( raycaster.ray.intersectPlane( _plane, _intersection ) ) {
|
||||
|
||||
_selected.position.copy( _intersection.sub( _offset ).applyMatrix4( _inverseMatrix ) );
|
||||
|
||||
}
|
||||
|
||||
} else if ( this.state === STATE.ROTATE ) {
|
||||
|
||||
_diff.subVectors( _pointer, _previousPointer ).multiplyScalar( this.rotateSpeed );
|
||||
_selected.rotateOnWorldAxis( _up, _diff.x );
|
||||
_selected.rotateOnWorldAxis( _right.normalize(), - _diff.y );
|
||||
|
||||
}
|
||||
|
||||
this.dispatchEvent( { type: 'drag', object: _selected } );
|
||||
|
||||
_previousPointer.copy( _pointer );
|
||||
|
||||
} else {
|
||||
|
||||
// hover support
|
||||
|
||||
if ( event.pointerType === 'mouse' || event.pointerType === 'pen' ) {
|
||||
|
||||
_intersections.length = 0;
|
||||
|
||||
raycaster.setFromCamera( _pointer, camera );
|
||||
raycaster.intersectObjects( this.objects, this.recursive, _intersections );
|
||||
|
||||
if ( _intersections.length > 0 ) {
|
||||
|
||||
const object = _intersections[ 0 ].object;
|
||||
|
||||
_plane.setFromNormalAndCoplanarPoint( camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( object.matrixWorld ) );
|
||||
|
||||
if ( _hovered !== object && _hovered !== null ) {
|
||||
|
||||
this.dispatchEvent( { type: 'hoveroff', object: _hovered } );
|
||||
|
||||
domElement.style.cursor = 'auto';
|
||||
_hovered = null;
|
||||
|
||||
}
|
||||
|
||||
if ( _hovered !== object ) {
|
||||
|
||||
this.dispatchEvent( { type: 'hoveron', object: object } );
|
||||
|
||||
domElement.style.cursor = 'pointer';
|
||||
_hovered = object;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( _hovered !== null ) {
|
||||
|
||||
this.dispatchEvent( { type: 'hoveroff', object: _hovered } );
|
||||
|
||||
domElement.style.cursor = 'auto';
|
||||
_hovered = null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_previousPointer.copy( _pointer );
|
||||
|
||||
}
|
||||
|
||||
function onPointerDown( event ) {
|
||||
|
||||
const camera = this.object;
|
||||
const domElement = this.domElement;
|
||||
const raycaster = this.raycaster;
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
this._updatePointer( event );
|
||||
this._updateState( event );
|
||||
|
||||
_intersections.length = 0;
|
||||
|
||||
raycaster.setFromCamera( _pointer, camera );
|
||||
raycaster.intersectObjects( this.objects, this.recursive, _intersections );
|
||||
|
||||
if ( _intersections.length > 0 ) {
|
||||
|
||||
if ( this.transformGroup === true ) {
|
||||
|
||||
// look for the outermost group in the object's upper hierarchy
|
||||
|
||||
_selected = findGroup( _intersections[ 0 ].object );
|
||||
|
||||
} else {
|
||||
|
||||
_selected = _intersections[ 0 ].object;
|
||||
|
||||
}
|
||||
|
||||
_plane.setFromNormalAndCoplanarPoint( camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) );
|
||||
|
||||
if ( raycaster.ray.intersectPlane( _plane, _intersection ) ) {
|
||||
|
||||
if ( this.state === STATE.PAN ) {
|
||||
|
||||
_inverseMatrix.copy( _selected.parent.matrixWorld ).invert();
|
||||
_offset.copy( _intersection ).sub( _worldPosition.setFromMatrixPosition( _selected.matrixWorld ) );
|
||||
|
||||
} else if ( this.state === STATE.ROTATE ) {
|
||||
|
||||
// the controls only support Y+ up
|
||||
_up.set( 0, 1, 0 ).applyQuaternion( camera.quaternion ).normalize();
|
||||
_right.set( 1, 0, 0 ).applyQuaternion( camera.quaternion ).normalize();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
domElement.style.cursor = 'move';
|
||||
|
||||
this.dispatchEvent( { type: 'dragstart', object: _selected } );
|
||||
|
||||
}
|
||||
|
||||
_previousPointer.copy( _pointer );
|
||||
|
||||
}
|
||||
|
||||
function onPointerCancel() {
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
if ( _selected ) {
|
||||
|
||||
this.dispatchEvent( { type: 'dragend', object: _selected } );
|
||||
|
||||
_selected = null;
|
||||
|
||||
}
|
||||
|
||||
this.domElement.style.cursor = _hovered ? 'pointer' : 'auto';
|
||||
|
||||
this.state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
function onContextMenu( event ) {
|
||||
|
||||
if ( this.enabled === false ) return;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
function findGroup( obj, group = null ) {
|
||||
|
||||
if ( obj.isGroup ) group = obj;
|
||||
|
||||
if ( obj.parent === null ) return group;
|
||||
|
||||
return findGroup( obj.parent, group );
|
||||
|
||||
}
|
||||
|
||||
export { DragControls };
|
||||
22
VISUALIZACION/public/libs/accessor-fn.js
Executable file
|
|
@ -0,0 +1,22 @@
|
|||
// Version 1.5.0 accessor-fn - https://github.com/vasturiano/accessor-fn
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.accessorFn = factory());
|
||||
})(this, (function () { 'use strict';
|
||||
|
||||
var index = (function (p) {
|
||||
return typeof p === 'function' ? p // fn
|
||||
: typeof p === 'string' ? function (obj) {
|
||||
return obj[p];
|
||||
} // property name
|
||||
: function (obj) {
|
||||
return p;
|
||||
};
|
||||
}); // constant
|
||||
|
||||
return index;
|
||||
|
||||
}));
|
||||
//# sourceMappingURL=accessor-fn.js.map
|
||||
export default TableCsv
|
||||
26
VISUALIZACION/public/libs/kapsule-link.js
Executable file
|
|
@ -0,0 +1,26 @@
|
|||
export default function(kapsulePropName, kapsuleType) {
|
||||
|
||||
const dummyK = new kapsuleType(); // To extract defaults
|
||||
dummyK._destructor && dummyK._destructor();
|
||||
|
||||
return {
|
||||
linkProp: function(prop) { // link property config
|
||||
return {
|
||||
default: dummyK[prop](),
|
||||
onChange(v, state) { state[kapsulePropName][prop](v) },
|
||||
triggerUpdate: false
|
||||
}
|
||||
},
|
||||
linkMethod: function(method) { // link method pass-through
|
||||
return function(state, ...args) {
|
||||
const kapsuleInstance = state[kapsulePropName];
|
||||
const returnVal = kapsuleInstance[method](...args);
|
||||
|
||||
return returnVal === kapsuleInstance
|
||||
? this // chain based on the parent object, not the inner kapsule
|
||||
: returnVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
716
VISUALIZACION/public/libs/kapsule.js
Executable file
|
|
@ -0,0 +1,716 @@
|
|||
// Version 1.14.4 kapsule - https://github.com/vasturiano/kapsule
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Kapsule = factory());
|
||||
})(this, (function () { 'use strict';
|
||||
|
||||
function _iterableToArrayLimit(arr, i) {
|
||||
var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"];
|
||||
if (null != _i) {
|
||||
var _s,
|
||||
_e,
|
||||
_x,
|
||||
_r,
|
||||
_arr = [],
|
||||
_n = !0,
|
||||
_d = !1;
|
||||
try {
|
||||
if (_x = (_i = _i.call(arr)).next, 0 === i) {
|
||||
if (Object(_i) !== _i) return;
|
||||
_n = !1;
|
||||
} else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0);
|
||||
} catch (err) {
|
||||
_d = !0, _e = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return;
|
||||
} finally {
|
||||
if (_d) throw _e;
|
||||
}
|
||||
}
|
||||
return _arr;
|
||||
}
|
||||
}
|
||||
function _classCallCheck(instance, Constructor) {
|
||||
if (!(instance instanceof Constructor)) {
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
}
|
||||
function _defineProperties(target, props) {
|
||||
for (var i = 0; i < props.length; i++) {
|
||||
var descriptor = props[i];
|
||||
descriptor.enumerable = descriptor.enumerable || false;
|
||||
descriptor.configurable = true;
|
||||
if ("value" in descriptor) descriptor.writable = true;
|
||||
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
|
||||
}
|
||||
}
|
||||
function _createClass(Constructor, protoProps, staticProps) {
|
||||
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
||||
if (staticProps) _defineProperties(Constructor, staticProps);
|
||||
Object.defineProperty(Constructor, "prototype", {
|
||||
writable: false
|
||||
});
|
||||
return Constructor;
|
||||
}
|
||||
function _slicedToArray(arr, i) {
|
||||
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
|
||||
}
|
||||
function _arrayWithHoles(arr) {
|
||||
if (Array.isArray(arr)) return arr;
|
||||
}
|
||||
function _unsupportedIterableToArray(o, minLen) {
|
||||
if (!o) return;
|
||||
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
||||
var n = Object.prototype.toString.call(o).slice(8, -1);
|
||||
if (n === "Object" && o.constructor) n = o.constructor.name;
|
||||
if (n === "Map" || n === "Set") return Array.from(o);
|
||||
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
||||
}
|
||||
function _arrayLikeToArray(arr, len) {
|
||||
if (len == null || len > arr.length) len = arr.length;
|
||||
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
||||
return arr2;
|
||||
}
|
||||
function _nonIterableRest() {
|
||||
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
||||
}
|
||||
function _toPrimitive(input, hint) {
|
||||
if (typeof input !== "object" || input === null) return input;
|
||||
var prim = input[Symbol.toPrimitive];
|
||||
if (prim !== undefined) {
|
||||
var res = prim.call(input, hint || "default");
|
||||
if (typeof res !== "object") return res;
|
||||
throw new TypeError("@@toPrimitive must return a primitive value.");
|
||||
}
|
||||
return (hint === "string" ? String : Number)(input);
|
||||
}
|
||||
function _toPropertyKey(arg) {
|
||||
var key = _toPrimitive(arg, "string");
|
||||
return typeof key === "symbol" ? key : String(key);
|
||||
}
|
||||
|
||||
/** Detect free variable `global` from Node.js. */
|
||||
var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
|
||||
|
||||
var freeGlobal$1 = freeGlobal;
|
||||
|
||||
/** Detect free variable `self`. */
|
||||
var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
|
||||
|
||||
/** Used as a reference to the global object. */
|
||||
var root = freeGlobal$1 || freeSelf || Function('return this')();
|
||||
|
||||
var root$1 = root;
|
||||
|
||||
/** Built-in value references. */
|
||||
var Symbol$1 = root$1.Symbol;
|
||||
|
||||
var Symbol$2 = Symbol$1;
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto$1 = Object.prototype;
|
||||
|
||||
/** Used to check objects for own properties. */
|
||||
var hasOwnProperty = objectProto$1.hasOwnProperty;
|
||||
|
||||
/**
|
||||
* Used to resolve the
|
||||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||||
* of values.
|
||||
*/
|
||||
var nativeObjectToString$1 = objectProto$1.toString;
|
||||
|
||||
/** Built-in value references. */
|
||||
var symToStringTag$1 = Symbol$2 ? Symbol$2.toStringTag : undefined;
|
||||
|
||||
/**
|
||||
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to query.
|
||||
* @returns {string} Returns the raw `toStringTag`.
|
||||
*/
|
||||
function getRawTag(value) {
|
||||
var isOwn = hasOwnProperty.call(value, symToStringTag$1),
|
||||
tag = value[symToStringTag$1];
|
||||
|
||||
try {
|
||||
value[symToStringTag$1] = undefined;
|
||||
var unmasked = true;
|
||||
} catch (e) {}
|
||||
|
||||
var result = nativeObjectToString$1.call(value);
|
||||
if (unmasked) {
|
||||
if (isOwn) {
|
||||
value[symToStringTag$1] = tag;
|
||||
} else {
|
||||
delete value[symToStringTag$1];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Used for built-in method references. */
|
||||
var objectProto = Object.prototype;
|
||||
|
||||
/**
|
||||
* Used to resolve the
|
||||
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
||||
* of values.
|
||||
*/
|
||||
var nativeObjectToString = objectProto.toString;
|
||||
|
||||
/**
|
||||
* Converts `value` to a string using `Object.prototype.toString`.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to convert.
|
||||
* @returns {string} Returns the converted string.
|
||||
*/
|
||||
function objectToString(value) {
|
||||
return nativeObjectToString.call(value);
|
||||
}
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
var nullTag = '[object Null]',
|
||||
undefinedTag = '[object Undefined]';
|
||||
|
||||
/** Built-in value references. */
|
||||
var symToStringTag = Symbol$2 ? Symbol$2.toStringTag : undefined;
|
||||
|
||||
/**
|
||||
* The base implementation of `getTag` without fallbacks for buggy environments.
|
||||
*
|
||||
* @private
|
||||
* @param {*} value The value to query.
|
||||
* @returns {string} Returns the `toStringTag`.
|
||||
*/
|
||||
function baseGetTag(value) {
|
||||
if (value == null) {
|
||||
return value === undefined ? undefinedTag : nullTag;
|
||||
}
|
||||
return (symToStringTag && symToStringTag in Object(value))
|
||||
? getRawTag(value)
|
||||
: objectToString(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
||||
* and has a `typeof` result of "object".
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isObjectLike({});
|
||||
* // => true
|
||||
*
|
||||
* _.isObjectLike([1, 2, 3]);
|
||||
* // => true
|
||||
*
|
||||
* _.isObjectLike(_.noop);
|
||||
* // => false
|
||||
*
|
||||
* _.isObjectLike(null);
|
||||
* // => false
|
||||
*/
|
||||
function isObjectLike(value) {
|
||||
return value != null && typeof value == 'object';
|
||||
}
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
var symbolTag = '[object Symbol]';
|
||||
|
||||
/**
|
||||
* Checks if `value` is classified as a `Symbol` primitive or object.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isSymbol(Symbol.iterator);
|
||||
* // => true
|
||||
*
|
||||
* _.isSymbol('abc');
|
||||
* // => false
|
||||
*/
|
||||
function isSymbol(value) {
|
||||
return typeof value == 'symbol' ||
|
||||
(isObjectLike(value) && baseGetTag(value) == symbolTag);
|
||||
}
|
||||
|
||||
/** Used to match a single whitespace character. */
|
||||
var reWhitespace = /\s/;
|
||||
|
||||
/**
|
||||
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
|
||||
* character of `string`.
|
||||
*
|
||||
* @private
|
||||
* @param {string} string The string to inspect.
|
||||
* @returns {number} Returns the index of the last non-whitespace character.
|
||||
*/
|
||||
function trimmedEndIndex(string) {
|
||||
var index = string.length;
|
||||
|
||||
while (index-- && reWhitespace.test(string.charAt(index))) {}
|
||||
return index;
|
||||
}
|
||||
|
||||
/** Used to match leading whitespace. */
|
||||
var reTrimStart = /^\s+/;
|
||||
|
||||
/**
|
||||
* The base implementation of `_.trim`.
|
||||
*
|
||||
* @private
|
||||
* @param {string} string The string to trim.
|
||||
* @returns {string} Returns the trimmed string.
|
||||
*/
|
||||
function baseTrim(string) {
|
||||
return string
|
||||
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
|
||||
: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if `value` is the
|
||||
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
|
||||
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 0.1.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to check.
|
||||
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
||||
* @example
|
||||
*
|
||||
* _.isObject({});
|
||||
* // => true
|
||||
*
|
||||
* _.isObject([1, 2, 3]);
|
||||
* // => true
|
||||
*
|
||||
* _.isObject(_.noop);
|
||||
* // => true
|
||||
*
|
||||
* _.isObject(null);
|
||||
* // => false
|
||||
*/
|
||||
function isObject(value) {
|
||||
var type = typeof value;
|
||||
return value != null && (type == 'object' || type == 'function');
|
||||
}
|
||||
|
||||
/** Used as references for various `Number` constants. */
|
||||
var NAN = 0 / 0;
|
||||
|
||||
/** Used to detect bad signed hexadecimal string values. */
|
||||
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
|
||||
|
||||
/** Used to detect binary string values. */
|
||||
var reIsBinary = /^0b[01]+$/i;
|
||||
|
||||
/** Used to detect octal string values. */
|
||||
var reIsOctal = /^0o[0-7]+$/i;
|
||||
|
||||
/** Built-in method references without a dependency on `root`. */
|
||||
var freeParseInt = parseInt;
|
||||
|
||||
/**
|
||||
* Converts `value` to a number.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 4.0.0
|
||||
* @category Lang
|
||||
* @param {*} value The value to process.
|
||||
* @returns {number} Returns the number.
|
||||
* @example
|
||||
*
|
||||
* _.toNumber(3.2);
|
||||
* // => 3.2
|
||||
*
|
||||
* _.toNumber(Number.MIN_VALUE);
|
||||
* // => 5e-324
|
||||
*
|
||||
* _.toNumber(Infinity);
|
||||
* // => Infinity
|
||||
*
|
||||
* _.toNumber('3.2');
|
||||
* // => 3.2
|
||||
*/
|
||||
function toNumber(value) {
|
||||
if (typeof value == 'number') {
|
||||
return value;
|
||||
}
|
||||
if (isSymbol(value)) {
|
||||
return NAN;
|
||||
}
|
||||
if (isObject(value)) {
|
||||
var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
|
||||
value = isObject(other) ? (other + '') : other;
|
||||
}
|
||||
if (typeof value != 'string') {
|
||||
return value === 0 ? value : +value;
|
||||
}
|
||||
value = baseTrim(value);
|
||||
var isBinary = reIsBinary.test(value);
|
||||
return (isBinary || reIsOctal.test(value))
|
||||
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
|
||||
: (reIsBadHex.test(value) ? NAN : +value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp of the number of milliseconds that have elapsed since
|
||||
* the Unix epoch (1 January 1970 00:00:00 UTC).
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 2.4.0
|
||||
* @category Date
|
||||
* @returns {number} Returns the timestamp.
|
||||
* @example
|
||||
*
|
||||
* _.defer(function(stamp) {
|
||||
* console.log(_.now() - stamp);
|
||||
* }, _.now());
|
||||
* // => Logs the number of milliseconds it took for the deferred invocation.
|
||||
*/
|
||||
var now = function() {
|
||||
return root$1.Date.now();
|
||||
};
|
||||
|
||||
var now$1 = now;
|
||||
|
||||
/** Error message constants. */
|
||||
var FUNC_ERROR_TEXT = 'Expected a function';
|
||||
|
||||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||||
var nativeMax = Math.max,
|
||||
nativeMin = Math.min;
|
||||
|
||||
/**
|
||||
* Creates a debounced function that delays invoking `func` until after `wait`
|
||||
* milliseconds have elapsed since the last time the debounced function was
|
||||
* invoked. The debounced function comes with a `cancel` method to cancel
|
||||
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
||||
* Provide `options` to indicate whether `func` should be invoked on the
|
||||
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
||||
* with the last arguments provided to the debounced function. Subsequent
|
||||
* calls to the debounced function return the result of the last `func`
|
||||
* invocation.
|
||||
*
|
||||
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
||||
* invoked on the trailing edge of the timeout only if the debounced function
|
||||
* is invoked more than once during the `wait` timeout.
|
||||
*
|
||||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
||||
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
||||
*
|
||||
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
||||
* for details over the differences between `_.debounce` and `_.throttle`.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 0.1.0
|
||||
* @category Function
|
||||
* @param {Function} func The function to debounce.
|
||||
* @param {number} [wait=0] The number of milliseconds to delay.
|
||||
* @param {Object} [options={}] The options object.
|
||||
* @param {boolean} [options.leading=false]
|
||||
* Specify invoking on the leading edge of the timeout.
|
||||
* @param {number} [options.maxWait]
|
||||
* The maximum time `func` is allowed to be delayed before it's invoked.
|
||||
* @param {boolean} [options.trailing=true]
|
||||
* Specify invoking on the trailing edge of the timeout.
|
||||
* @returns {Function} Returns the new debounced function.
|
||||
* @example
|
||||
*
|
||||
* // Avoid costly calculations while the window size is in flux.
|
||||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
||||
*
|
||||
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
||||
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
||||
* 'leading': true,
|
||||
* 'trailing': false
|
||||
* }));
|
||||
*
|
||||
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
||||
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
||||
* var source = new EventSource('/stream');
|
||||
* jQuery(source).on('message', debounced);
|
||||
*
|
||||
* // Cancel the trailing debounced invocation.
|
||||
* jQuery(window).on('popstate', debounced.cancel);
|
||||
*/
|
||||
function debounce(func, wait, options) {
|
||||
var lastArgs,
|
||||
lastThis,
|
||||
maxWait,
|
||||
result,
|
||||
timerId,
|
||||
lastCallTime,
|
||||
lastInvokeTime = 0,
|
||||
leading = false,
|
||||
maxing = false,
|
||||
trailing = true;
|
||||
|
||||
if (typeof func != 'function') {
|
||||
throw new TypeError(FUNC_ERROR_TEXT);
|
||||
}
|
||||
wait = toNumber(wait) || 0;
|
||||
if (isObject(options)) {
|
||||
leading = !!options.leading;
|
||||
maxing = 'maxWait' in options;
|
||||
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
|
||||
trailing = 'trailing' in options ? !!options.trailing : trailing;
|
||||
}
|
||||
|
||||
function invokeFunc(time) {
|
||||
var args = lastArgs,
|
||||
thisArg = lastThis;
|
||||
|
||||
lastArgs = lastThis = undefined;
|
||||
lastInvokeTime = time;
|
||||
result = func.apply(thisArg, args);
|
||||
return result;
|
||||
}
|
||||
|
||||
function leadingEdge(time) {
|
||||
// Reset any `maxWait` timer.
|
||||
lastInvokeTime = time;
|
||||
// Start the timer for the trailing edge.
|
||||
timerId = setTimeout(timerExpired, wait);
|
||||
// Invoke the leading edge.
|
||||
return leading ? invokeFunc(time) : result;
|
||||
}
|
||||
|
||||
function remainingWait(time) {
|
||||
var timeSinceLastCall = time - lastCallTime,
|
||||
timeSinceLastInvoke = time - lastInvokeTime,
|
||||
timeWaiting = wait - timeSinceLastCall;
|
||||
|
||||
return maxing
|
||||
? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke)
|
||||
: timeWaiting;
|
||||
}
|
||||
|
||||
function shouldInvoke(time) {
|
||||
var timeSinceLastCall = time - lastCallTime,
|
||||
timeSinceLastInvoke = time - lastInvokeTime;
|
||||
|
||||
// Either this is the first call, activity has stopped and we're at the
|
||||
// trailing edge, the system time has gone backwards and we're treating
|
||||
// it as the trailing edge, or we've hit the `maxWait` limit.
|
||||
return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
|
||||
(timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
|
||||
}
|
||||
|
||||
function timerExpired() {
|
||||
var time = now$1();
|
||||
if (shouldInvoke(time)) {
|
||||
return trailingEdge(time);
|
||||
}
|
||||
// Restart the timer.
|
||||
timerId = setTimeout(timerExpired, remainingWait(time));
|
||||
}
|
||||
|
||||
function trailingEdge(time) {
|
||||
timerId = undefined;
|
||||
|
||||
// Only invoke if we have `lastArgs` which means `func` has been
|
||||
// debounced at least once.
|
||||
if (trailing && lastArgs) {
|
||||
return invokeFunc(time);
|
||||
}
|
||||
lastArgs = lastThis = undefined;
|
||||
return result;
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
if (timerId !== undefined) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
lastInvokeTime = 0;
|
||||
lastArgs = lastCallTime = lastThis = timerId = undefined;
|
||||
}
|
||||
|
||||
function flush() {
|
||||
return timerId === undefined ? result : trailingEdge(now$1());
|
||||
}
|
||||
|
||||
function debounced() {
|
||||
var time = now$1(),
|
||||
isInvoking = shouldInvoke(time);
|
||||
|
||||
lastArgs = arguments;
|
||||
lastThis = this;
|
||||
lastCallTime = time;
|
||||
|
||||
if (isInvoking) {
|
||||
if (timerId === undefined) {
|
||||
return leadingEdge(lastCallTime);
|
||||
}
|
||||
if (maxing) {
|
||||
// Handle invocations in a tight loop.
|
||||
clearTimeout(timerId);
|
||||
timerId = setTimeout(timerExpired, wait);
|
||||
return invokeFunc(lastCallTime);
|
||||
}
|
||||
}
|
||||
if (timerId === undefined) {
|
||||
timerId = setTimeout(timerExpired, wait);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
debounced.cancel = cancel;
|
||||
debounced.flush = flush;
|
||||
return debounced;
|
||||
}
|
||||
|
||||
var Prop = /*#__PURE__*/_createClass(function Prop(name, _ref) {
|
||||
var _ref$default = _ref["default"],
|
||||
defaultVal = _ref$default === void 0 ? null : _ref$default,
|
||||
_ref$triggerUpdate = _ref.triggerUpdate,
|
||||
triggerUpdate = _ref$triggerUpdate === void 0 ? true : _ref$triggerUpdate,
|
||||
_ref$onChange = _ref.onChange,
|
||||
onChange = _ref$onChange === void 0 ? function (newVal, state) {} : _ref$onChange;
|
||||
_classCallCheck(this, Prop);
|
||||
this.name = name;
|
||||
this.defaultVal = defaultVal;
|
||||
this.triggerUpdate = triggerUpdate;
|
||||
this.onChange = onChange;
|
||||
});
|
||||
function index (_ref2) {
|
||||
var _ref2$stateInit = _ref2.stateInit,
|
||||
stateInit = _ref2$stateInit === void 0 ? function () {
|
||||
return {};
|
||||
} : _ref2$stateInit,
|
||||
_ref2$props = _ref2.props,
|
||||
rawProps = _ref2$props === void 0 ? {} : _ref2$props,
|
||||
_ref2$methods = _ref2.methods,
|
||||
methods = _ref2$methods === void 0 ? {} : _ref2$methods,
|
||||
_ref2$aliases = _ref2.aliases,
|
||||
aliases = _ref2$aliases === void 0 ? {} : _ref2$aliases,
|
||||
_ref2$init = _ref2.init,
|
||||
initFn = _ref2$init === void 0 ? function () {} : _ref2$init,
|
||||
_ref2$update = _ref2.update,
|
||||
updateFn = _ref2$update === void 0 ? function () {} : _ref2$update;
|
||||
// Parse props into Prop instances
|
||||
var props = Object.keys(rawProps).map(function (propName) {
|
||||
return new Prop(propName, rawProps[propName]);
|
||||
});
|
||||
return function () {
|
||||
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
||||
// Holds component state
|
||||
var state = Object.assign({}, stateInit instanceof Function ? stateInit(options) : stateInit,
|
||||
// Support plain objects for backwards compatibility
|
||||
{
|
||||
initialised: false
|
||||
});
|
||||
|
||||
// keeps track of which props triggered an update
|
||||
var changedProps = {};
|
||||
|
||||
// Component constructor
|
||||
function comp(nodeElement) {
|
||||
initStatic(nodeElement, options);
|
||||
digest();
|
||||
return comp;
|
||||
}
|
||||
var initStatic = function initStatic(nodeElement, options) {
|
||||
initFn.call(comp, nodeElement, state, options);
|
||||
state.initialised = true;
|
||||
};
|
||||
var digest = debounce(function () {
|
||||
if (!state.initialised) {
|
||||
return;
|
||||
}
|
||||
updateFn.call(comp, state, changedProps);
|
||||
changedProps = {};
|
||||
}, 1);
|
||||
|
||||
// Getter/setter methods
|
||||
props.forEach(function (prop) {
|
||||
comp[prop.name] = getSetProp(prop);
|
||||
function getSetProp(_ref3) {
|
||||
var prop = _ref3.name,
|
||||
_ref3$triggerUpdate = _ref3.triggerUpdate,
|
||||
redigest = _ref3$triggerUpdate === void 0 ? false : _ref3$triggerUpdate,
|
||||
_ref3$onChange = _ref3.onChange,
|
||||
onChange = _ref3$onChange === void 0 ? function (newVal, state) {} : _ref3$onChange,
|
||||
_ref3$defaultVal = _ref3.defaultVal,
|
||||
defaultVal = _ref3$defaultVal === void 0 ? null : _ref3$defaultVal;
|
||||
return function (_) {
|
||||
var curVal = state[prop];
|
||||
if (!arguments.length) {
|
||||
return curVal;
|
||||
} // Getter mode
|
||||
|
||||
var val = _ === undefined ? defaultVal : _; // pick default if value passed is undefined
|
||||
state[prop] = val;
|
||||
onChange.call(comp, val, state, curVal);
|
||||
|
||||
// track changed props
|
||||
!changedProps.hasOwnProperty(prop) && (changedProps[prop] = curVal);
|
||||
if (redigest) {
|
||||
digest();
|
||||
}
|
||||
return comp;
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Other methods
|
||||
Object.keys(methods).forEach(function (methodName) {
|
||||
comp[methodName] = function () {
|
||||
var _methods$methodName;
|
||||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
return (_methods$methodName = methods[methodName]).call.apply(_methods$methodName, [comp, state].concat(args));
|
||||
};
|
||||
});
|
||||
|
||||
// Link aliases
|
||||
Object.entries(aliases).forEach(function (_ref4) {
|
||||
var _ref5 = _slicedToArray(_ref4, 2),
|
||||
alias = _ref5[0],
|
||||
target = _ref5[1];
|
||||
return comp[alias] = comp[target];
|
||||
});
|
||||
|
||||
// Reset all component props to their default value
|
||||
comp.resetProps = function () {
|
||||
props.forEach(function (prop) {
|
||||
comp[prop.name](prop.defaultVal);
|
||||
});
|
||||
return comp;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
comp.resetProps(); // Apply all prop defaults
|
||||
state._rerender = digest; // Expose digest method
|
||||
|
||||
return comp;
|
||||
};
|
||||
}
|
||||
|
||||
return index;
|
||||
|
||||
}));
|
||||
//# sourceMappingURL=kapsule.js.map
|
||||
export default TableCsv
|
||||
8477
VISUALIZACION/public/libs/three-forcegraph.js
Executable file
6788
VISUALIZACION/public/libs/three-render-objects.js
Executable file
53917
VISUALIZACION/public/libs/three.module.js
Executable file
162
VISUALIZACION/public/output.js.save
Executable file
|
|
@ -0,0 +1,162 @@
|
|||
// Importación de ForceGraph3D
|
||||
import ForceGraph3D from './libs/3d-force-graph.min.js'; // Asegúrate de que está en la carpeta libs
|
||||
|
||||
// Importación del cliente de Elasticsearch
|
||||
import { Client } from 'https://cdn.skypack.dev/@elastic/elasticsearch';
|
||||
|
||||
// Configuración de la conexión a Elasticsearch
|
||||
const client = new Client({ node: 'http://localhost:9200' });
|
||||
|
||||
// Definir la clase Graph
|
||||
class Graph {
|
||||
constructor(containerId) {
|
||||
this.graph = ForceGraph3D()(document.getElementById(containerId));
|
||||
this.maxNodes = 200; // Número máximo de nodos a mostrar
|
||||
this.minSimilarity = 5; // Umbral mínimo de similitud
|
||||
}
|
||||
|
||||
// Configuración del número máximo de nodos
|
||||
setMaxNodes(maxNodes) {
|
||||
this.maxNodes = maxNodes;
|
||||
}
|
||||
|
||||
// Configuración del umbral de similitud
|
||||
setMinSimilarity(minSimilarity) {
|
||||
this.minSimilarity = minSimilarity;
|
||||
}
|
||||
|
||||
// Cargar nodos desde Elasticsearch
|
||||
async loadNodes(subtematica = '', palabraClave = '', fechaInicio = '', fechaFin = '') {
|
||||
const query = {
|
||||
bool: {
|
||||
must: [
|
||||
{ match: { tema: 'corporaciones y organizaciones internacionales' } }
|
||||
],
|
||||
filter: []
|
||||
}
|
||||
};
|
||||
|
||||
if (subtematica) {
|
||||
query.bool.must.push({ match: { subtema: subtematica } });
|
||||
}
|
||||
|
||||
if (palabraClave) {
|
||||
query.bool.must.push({ match: { contenido: palabraClave } });
|
||||
}
|
||||
|
||||
if (fechaInicio && fechaFin) {
|
||||
query.bool.filter.push({
|
||||
range: {
|
||||
fecha: {
|
||||
gte: fechaInicio,
|
||||
lte: fechaFin
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const response = await client.search({
|
||||
index: 'informacion', // Usamos el índice correcto
|
||||
body: {
|
||||
query: query,
|
||||
size: this.maxNodes,
|
||||
sort: { importancia: 'desc' }
|
||||
}
|
||||
});
|
||||
|
||||
return response.body.hits.hits.map(hit => ({
|
||||
id: hit._source.nombre_archivo,
|
||||
group: hit._source.tipo_archivo,
|
||||
tema: hit._source.tema,
|
||||
content: hit._source.contenido,
|
||||
fecha: hit._source.fecha
|
||||
}));
|
||||
}
|
||||
|
||||
// Cargar relaciones directamente desde Elasticsearch
|
||||
async loadLinks() {
|
||||
const response = await client.search({
|
||||
index: 'informacion', // Asegurarse de que el índice correcto se utiliza para las relaciones
|
||||
body: {
|
||||
query: {
|
||||
match_all: {} // Obtenemos todas las relaciones almacenadas
|
||||
},
|
||||
size: this.maxNodes // Limitamos el tamaño de la respuesta
|
||||
}
|
||||
});
|
||||
|
||||
const links = response.body.hits.hits.map(hit => {
|
||||
const content = hit._source.contenido;
|
||||
const lines = content.split('\n'); // Asumiendo que las relaciones están en formato línea por línea
|
||||
|
||||
return lines.map(line => {
|
||||
const [source, target, similarity] = line.split(',');
|
||||
if (parseFloat(similarity) >= this.minSimilarity) {
|
||||
return {
|
||||
source: path.basename(source.trim(), '.txt'),
|
||||
target: path.basename(target.trim(), '.txt'),
|
||||
value: parseFloat(similarity)
|
||||
};
|
||||
}
|
||||
}).filter(link => link); // Filtramos los enlaces válidos
|
||||
});
|
||||
|
||||
return links.flat();
|
||||
}
|
||||
|
||||
// Crear datos del gráfico
|
||||
createGraphData(nodes, links) {
|
||||
return {
|
||||
nodes,
|
||||
links
|
||||
};
|
||||
}
|
||||
|
||||
// Mostrar el contenido de un nodo al hacer clic
|
||||
async showNodeContent(node) {
|
||||
try {
|
||||
const response = await client.search({
|
||||
index: 'informacion',
|
||||
body: {
|
||||
query: {
|
||||
match: { nombre_archivo: node.id }
|
||||
}
|
||||
},
|
||||
size: 1
|
||||
});
|
||||
|
||||
const content = response.body.hits.hits[0]._source.contenido;
|
||||
const contentDiv = document.getElementById('contentDisplay');
|
||||
contentDiv.innerText = content || "No hay contenido disponible.";
|
||||
} catch (error) {
|
||||
console.error("Error al obtener contenido:", error);
|
||||
const contentDiv = document.getElementById('contentDisplay');
|
||||
contentDiv.innerText = "Error al obtener contenido.";
|
||||
}
|
||||
}
|
||||
|
||||
// Dibujar el gráfico
|
||||
async drawGraph(subtematica = '', palabraClave = '', fechaInicio = '', fechaFin = '') {
|
||||
const nodes = await this.loadNodes(subtematica, palabraClave, fechaInicio, fechaFin);
|
||||
const links = await this.loadLinks(); // Cargamos las relaciones desde Elasticsearch
|
||||
const graphData = this.createGraphData(nodes, links);
|
||||
|
||||
this.graph
|
||||
.graphData(graphData)
|
||||
.backgroundColor('black')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(5)
|
||||
.linkColor(() => 'yellow')
|
||||
.onNodeClick(node => {
|
||||
this.showNodeContent(node);
|
||||
})
|
||||
.forceEngine('d3')
|
||||
.d3Force('charge').strength(-200)
|
||||
.d3Force('link').distance(50);
|
||||
}
|
||||
}
|
||||
|
||||
// Inicializar el gráfico
|
||||
const myGraph = new Graph('canvasContainer');
|
||||
myGraph.drawGraph();
|
||||
126
VISUALIZACION/public/output_climate_pruebas.js
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
// output_climate_pruebas.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const elem = document.getElementById('climateContainer');
|
||||
const form = document.getElementById('paramForm');
|
||||
|
||||
// Inicializar el gráfico 3D
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(1)
|
||||
.linkColor(() => '#42FF00')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.forceEngine('d3')
|
||||
//.d3Force('charge', d3.forceManyBody().strength(-300))
|
||||
//.d3Force('link', d3.forceLink().distance(300).strength(1));
|
||||
|
||||
// Centrado automático del gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
graph.zoomToFit(400, Math.min(width, height) * 0.1);
|
||||
}, 500);
|
||||
}
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Mostrar contenido del nodo
|
||||
function showNodeContent(content) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
}
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Establecer el tema fijo
|
||||
params.append('tema', 'cambio climático');
|
||||
|
||||
// Agregar parámetros del formulario, incluyendo complejidad como umbral
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key] !== undefined && paramsObj[key] !== '') {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
console.log('🔎 Fetch URL:', url);
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
const data = await response.json();
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces inválidos
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => nodeIds.has(link.source) && nodeIds.has(link.target));
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Función principal: fetch, filtrar por complejidad/umbral y renderizar
|
||||
async function fetchAndRender() {
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
// Usamos 'complejidad' como porcentaje de similitud mínima (umbral)
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad // enviado al backend y usado de umbral en cliente
|
||||
};
|
||||
|
||||
// Parsear complejidad a número
|
||||
const umbralPct = parseFloat(complejidad) || 0;
|
||||
console.log(`Aplicando umbral de similitud: ${umbralPct}%`);
|
||||
|
||||
const graphData = await getData(paramsObj);
|
||||
if (!graphData) return;
|
||||
|
||||
// Filtrar enlaces por umbral de similitud
|
||||
let filteredLinks = graphData.links;
|
||||
if (umbralPct > 0) {
|
||||
filteredLinks = filteredLinks.filter(link => Number(link.value) >= umbralPct);
|
||||
console.log(`Enlaces tras aplicar umbral: ${filteredLinks.length}`);
|
||||
}
|
||||
|
||||
graph.graphData({ nodes: graphData.nodes, links: filteredLinks });
|
||||
centerGraph();
|
||||
}
|
||||
|
||||
// Escuchar evento submit del formulario
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
// Cargar gráfico inicial
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
120
VISUALIZACION/public/output_eco_corp_pruebas.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// output_eco_corp.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const elem = document.getElementById('ecoCorpContainer');
|
||||
const form = document.getElementById('paramForm');
|
||||
|
||||
// Inicializar el gráfico 3D
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(1)
|
||||
.linkColor(() => 'yellow')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.forceEngine('d3')
|
||||
//.d3Force('charge', d3.forceManyBody().strength(-300))
|
||||
//.d3Force('link', d3.forceLink().distance(300).strength(1));
|
||||
|
||||
// Centrado automático del gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
graph.zoomToFit(400, Math.min(width, height) * 0.1);
|
||||
}, 500);
|
||||
}
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Mostrar contenido del nodo
|
||||
function showNodeContent(content) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
}
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Establecer el tema fijo
|
||||
params.append('tema', 'economía y corporaciones');
|
||||
|
||||
// Agregar parámetros del formulario, incluyendo complejidad como umbral
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key] !== undefined && paramsObj[key] !== '') {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
console.log('🔎 Fetch URL:', url);
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
const data = await response.json();
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces inválidos
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => nodeIds.has(link.source) && nodeIds.has(link.target));
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Función principal: fetch, filtrar por complejidad/umbral y renderizar
|
||||
async function fetchAndRender() {
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
// Usamos 'complejidad' como porcentaje de similitud mínima (umbral)
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad // enviado al backend y usado de umbral en cliente
|
||||
};
|
||||
|
||||
// Parsear complejidad a número
|
||||
const umbralPct = parseFloat(complejidad) || 0;
|
||||
console.log(`Aplicando umbral de similitud: ${umbralPct}%`);
|
||||
|
||||
const graphData = await getData(paramsObj);
|
||||
if (!graphData) return;
|
||||
|
||||
// Filtrar enlaces por umbral de similitud
|
||||
let filteredLinks = graphData.links;
|
||||
if (umbralPct > 0) {
|
||||
filteredLinks = filteredLinks.filter(link => Number(link.value) >= umbralPct);
|
||||
console.log(`Enlaces tras aplicar umbral: ${filteredLinks.length}`);
|
||||
}
|
||||
|
||||
graph.graphData({ nodes: graphData.nodes, links: filteredLinks });
|
||||
centerGraph();
|
||||
}
|
||||
|
||||
// Escuchar evento submit del formulario
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
// Cargar gráfico inicial
|
||||
fetchAndRender();
|
||||
});
|
||||
123
VISUALIZACION/public/output_glob_war.js
Executable file
|
|
@ -0,0 +1,123 @@
|
|||
// output_glob_war.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
const elem = document.getElementById('globWarContainer');
|
||||
|
||||
// Inicializar el gráfico
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(2)
|
||||
.linkColor(() => 'green')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => {
|
||||
elem.style.cursor = node ? 'pointer' : null;
|
||||
})
|
||||
.forceEngine('d3')
|
||||
.d3Force('charge', d3.forceManyBody().strength(-10))
|
||||
.d3Force('link', d3.forceLink().distance(30).strength(1));
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Tema por defecto: "guerra global"
|
||||
params.append('tema', 'guerra global');
|
||||
|
||||
// Agregar parámetros del formulario si existen
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key]) {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces para nodos existentes
|
||||
const nodeIds = new Set(data.nodes.map(n => n.id));
|
||||
data.links = data.links.filter(l => nodeIds.has(l.source) && nodeIds.has(l.target));
|
||||
|
||||
console.log('Enlaces tras filtrar:', data.links);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return { nodes: [], links: [] };
|
||||
}
|
||||
}
|
||||
|
||||
// Mostrar contenido del nodo al hacer click
|
||||
function showNodeContent(content) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
// aquí podrías mostrarlo en un panel si quieres
|
||||
}
|
||||
|
||||
// Centrar y escalar el gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
const padding = Math.min(width, height) * 0.1;
|
||||
graph.zoomToFit(400, padding);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Al cambiar el tamaño de la ventana, reajustar
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Gestionar el submit del formulario de parámetros
|
||||
document.getElementById('paramForm').addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad
|
||||
};
|
||||
|
||||
getData(paramsObj).then(data => {
|
||||
graph.graphData(data);
|
||||
centerGraph();
|
||||
});
|
||||
});
|
||||
|
||||
// Cargar datos iniciales (guerra global) y renderizar
|
||||
getData().then(data => {
|
||||
if (data.nodes && data.nodes.length) {
|
||||
console.log(`Se recibieron ${data.nodes.length} nodos.`);
|
||||
graph.graphData(data);
|
||||
centerGraph();
|
||||
} else {
|
||||
console.warn('No se recibieron nodos para "guerra global".');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
120
VISUALIZACION/public/output_glob_war_pruebas.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// output_glob_war.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const elem = document.getElementById('globWarContainer');
|
||||
const form = document.getElementById('paramForm');
|
||||
|
||||
// Inicializar el gráfico 3D
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(1)
|
||||
.linkColor(() => 'red')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.forceEngine('d3')
|
||||
//.d3Force('charge', d3.forceManyBody().strength(-300))
|
||||
//.d3Force('link', d3.forceLink().distance(300).strength(1));
|
||||
|
||||
// Centrado automático del gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
graph.zoomToFit(400, Math.min(width, height) * 0.1);
|
||||
}, 500);
|
||||
}
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Mostrar contenido del nodo
|
||||
function showNodeContent(content) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
}
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Establecer el tema fijo
|
||||
params.append('tema', 'guerra global');
|
||||
|
||||
// Agregar parámetros del formulario, incluyendo complejidad como umbral
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key] !== undefined && paramsObj[key] !== '') {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
console.log('🔎 Fetch URL:', url);
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
const data = await response.json();
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces inválidos
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => nodeIds.has(link.source) && nodeIds.has(link.target));
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Función principal: fetch, filtrar por complejidad/umbral y renderizar
|
||||
async function fetchAndRender() {
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
// Usamos 'complejidad' como porcentaje de similitud mínima (umbral)
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad // enviado al backend y usado de umbral en cliente
|
||||
};
|
||||
|
||||
// Parsear complejidad a número
|
||||
const umbralPct = parseFloat(complejidad) || 0;
|
||||
console.log(`Aplicando umbral de similitud: ${umbralPct}%`);
|
||||
|
||||
const graphData = await getData(paramsObj);
|
||||
if (!graphData) return;
|
||||
|
||||
// Filtrar enlaces por umbral de similitud
|
||||
let filteredLinks = graphData.links;
|
||||
if (umbralPct > 0) {
|
||||
filteredLinks = filteredLinks.filter(link => Number(link.value) >= umbralPct);
|
||||
console.log(`Enlaces tras aplicar umbral: ${filteredLinks.length}`);
|
||||
}
|
||||
|
||||
graph.graphData({ nodes: graphData.nodes, links: filteredLinks });
|
||||
centerGraph();
|
||||
}
|
||||
|
||||
// Escuchar evento submit del formulario
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
// Cargar gráfico inicial
|
||||
fetchAndRender();
|
||||
});
|
||||
178
VISUALIZACION/public/output_int_sec.js
Executable file
|
|
@ -0,0 +1,178 @@
|
|||
// output_int_sec.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const elem = document.getElementById('intSecContainer');
|
||||
const form = document.getElementById('paramForm');
|
||||
const detailPanel = document.getElementById('detailPanel');
|
||||
|
||||
// --- Etiqueta de texto con CanvasTexture (sin SpriteText externo) ---
|
||||
function makeTextSprite(text) {
|
||||
if (!window.THREE) {
|
||||
console.warn('THREE no está disponible; omito etiquetas.');
|
||||
return undefined;
|
||||
}
|
||||
const pad = 16; // más padding para nitidez
|
||||
const font = 'bold 36px Fira Code, monospace'; // fuente más grande
|
||||
|
||||
// 1) preparar canvas al tamaño del texto
|
||||
const c = document.createElement('canvas');
|
||||
const ctx = c.getContext('2d');
|
||||
ctx.font = font;
|
||||
const w = Math.ceil(ctx.measureText(text).width) + pad * 2;
|
||||
const h = 50 + pad * 2;
|
||||
c.width = w; c.height = h;
|
||||
|
||||
// 2) dibujar texto
|
||||
ctx.font = font;
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.98)';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(text, pad, h / 2);
|
||||
|
||||
// 3) textura -> sprite
|
||||
const tex = new THREE.CanvasTexture(c);
|
||||
tex.needsUpdate = true;
|
||||
|
||||
const mat = new THREE.SpriteMaterial({
|
||||
map: tex,
|
||||
transparent: true,
|
||||
depthTest: false, // que no lo tape la esfera
|
||||
depthWrite: false // que no escriba en el z-buffer
|
||||
});
|
||||
const spr = new THREE.Sprite(mat);
|
||||
|
||||
// tamaño del texto en “mundo”
|
||||
const k = 0.22; // ajusta tamaño del texto (↑ más grande, ↓ más pequeño)
|
||||
spr.scale.set(w * k, h * k, 1);
|
||||
|
||||
// elevar el texto sobre el nodo
|
||||
spr.position.y = 8; // sube/baja si lo ves muy pegado
|
||||
|
||||
return spr;
|
||||
}
|
||||
|
||||
// Inicializar el gráfico 3D
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(1)
|
||||
.linkColor(() => 'blue')
|
||||
// Texto fijo sobre cada nodo (usando CanvasTexture)
|
||||
.nodeThreeObject(n => makeTextSprite(n.id))
|
||||
.nodeThreeObjectExtend(true) // mantiene esfera + texto
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.forceEngine('d3');
|
||||
// .d3Force('charge', d3.forceManyBody().strength(-400))
|
||||
// .d3Force('link', d3.forceLink().distance(300).strength(1))
|
||||
|
||||
// Centrado automático del gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
graph.zoomToFit(400, Math.min(width, height) * 0.1);
|
||||
}, 500);
|
||||
}
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Mostrar contenido del nodo
|
||||
function showNodeContent(content) {
|
||||
if (!detailPanel) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
return;
|
||||
}
|
||||
detailPanel.innerHTML = `
|
||||
<h2 style="margin:0 0 8px">Detalle</h2>
|
||||
<pre style="white-space:pre-wrap; line-height:1.35; font-family:'Fira Code', monospace; font-size:14px; color:#e5e5e5;">${content || 'No hay contenido disponible.'}</pre>
|
||||
`;
|
||||
const split = document.querySelector('main.split-screen');
|
||||
if (split) split.classList.add('show-detail');
|
||||
}
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Establecer el tema fijo
|
||||
params.append('tema', 'inteligencia y seguridad');
|
||||
|
||||
// Agregar parámetros del formulario, incluyendo complejidad como umbral
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key] !== undefined && paramsObj[key] !== '') {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
console.log('🔎 Fetch URL:', url);
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
const data = await response.json();
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces inválidos
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => nodeIds.has(link.source) && nodeIds.has(link.target));
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Función principal: fetch, filtrar por complejidad/umbral y renderizar
|
||||
async function fetchAndRender() {
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
// Usamos 'complejidad' como porcentaje de similitud mínima (umbral)
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad // enviado al backend y usado de umbral en cliente
|
||||
};
|
||||
|
||||
// Parsear complejidad a número
|
||||
const umbralPct = parseFloat(complejidad) || 0;
|
||||
console.log(`Aplicando umbral de similitud: ${umbralPct}%`);
|
||||
|
||||
const graphData = await getData(paramsObj);
|
||||
if (!graphData) return;
|
||||
|
||||
// Filtrar enlaces por umbral de similitud
|
||||
let filteredLinks = graphData.links;
|
||||
if (umbralPct > 0) {
|
||||
filteredLinks = filteredLinks.filter(link => Number(link.value) >= umbralPct);
|
||||
console.log(`Enlaces tras aplicar umbral: ${filteredLinks.length}`);
|
||||
}
|
||||
|
||||
graph.graphData({ nodes: graphData.nodes, links: filteredLinks });
|
||||
centerGraph();
|
||||
}
|
||||
|
||||
// Escuchar evento submit del formulario
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
// Cargar gráfico inicial
|
||||
fetchAndRender();
|
||||
});
|
||||
122
VISUALIZACION/public/output_popl_up.js
Executable file
|
|
@ -0,0 +1,122 @@
|
|||
// output_popl_up.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
const elem = document.getElementById('poplUpContainer');
|
||||
|
||||
// Inicializar el gráfico
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(5)
|
||||
.linkColor(() => 'green')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => {
|
||||
elem.style.cursor = node ? 'pointer' : null;
|
||||
})
|
||||
.forceEngine('d3')
|
||||
.d3Force('charge', d3.forceManyBody().strength(-10))
|
||||
.d3Force('link', d3.forceLink().distance(30).strength(1));
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Fijar el tema principal
|
||||
params.append('tema', 'movimientos populares y levantamientos');
|
||||
|
||||
// Agregar otros parámetros si se han definido
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key]) {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
console.log('📦 Datos recibidos:', data);
|
||||
|
||||
// Validar y limpiar links
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => {
|
||||
const valid = nodeIds.has(link.source) && nodeIds.has(link.target);
|
||||
if (!valid) {
|
||||
console.log(`❌ Enlace inválido eliminado: ${link.source} -> ${link.target}`);
|
||||
}
|
||||
return valid;
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('⚠️ Error al obtener datos:', error);
|
||||
return { nodes: [], links: [] };
|
||||
}
|
||||
}
|
||||
|
||||
// Mostrar contenido del nodo en consola (puedes ampliar esta función)
|
||||
function showNodeContent(content) {
|
||||
console.log('🧠 Contenido del nodo:', content);
|
||||
}
|
||||
|
||||
// Centrar el gráfico tras dibujarlo
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
const padding = Math.min(width, height) * 0.1;
|
||||
graph.zoomToFit(400, padding);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Redibujar al cambiar tamaño ventana
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Manejar el formulario
|
||||
document.getElementById('paramForm').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad,
|
||||
};
|
||||
|
||||
getData(paramsObj).then(graphData => {
|
||||
if (graphData) {
|
||||
console.log("✅ Redibujando con nuevos datos...");
|
||||
graph.graphData(graphData);
|
||||
centerGraph();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Obtener datos iniciales
|
||||
getData().then(graphData => {
|
||||
if (graphData && graphData.nodes && graphData.nodes.length > 0) {
|
||||
console.log(`✅ Se recibieron ${graphData.nodes.length} nodos.`);
|
||||
graph.graphData(graphData);
|
||||
centerGraph();
|
||||
} else {
|
||||
console.warn("⚠️ No se recibieron nodos para mostrar.");
|
||||
console.log("🔍 Respuesta completa:", graphData);
|
||||
}
|
||||
});
|
||||
129
VISUALIZACION/public/output_popl_up_pruebas.js
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// output_popl_up_pruebas.js
|
||||
|
||||
// Obtener el contenedor del gráfico
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const elem = document.getElementById('poplUpContainer');
|
||||
const form = document.getElementById('paramForm');
|
||||
|
||||
// Inicializar el gráfico 3D
|
||||
const graph = ForceGraph3D()(elem)
|
||||
.backgroundColor('#000000')
|
||||
.nodeLabel('id')
|
||||
.nodeAutoColorBy('group')
|
||||
.nodeVal(1)
|
||||
.linkColor(() => 'orange')
|
||||
.onNodeClick(node => showNodeContent(node.content))
|
||||
.onNodeHover(node => { elem.style.cursor = node ? 'pointer' : null; })
|
||||
.forceEngine('d3')
|
||||
//.d3Force('charge', d3.forceManyBody().strength(-300))
|
||||
//.d3Force('link', d3.forceLink().distance(300).strength(1));
|
||||
|
||||
// Centrado automático del gráfico
|
||||
function centerGraph() {
|
||||
setTimeout(() => {
|
||||
const width = elem.clientWidth;
|
||||
const height = elem.clientHeight;
|
||||
graph.zoomToFit(400, Math.min(width, height) * 0.1);
|
||||
}, 500);
|
||||
}
|
||||
window.addEventListener('resize', () => {
|
||||
graph.width(elem.clientWidth);
|
||||
graph.height(elem.clientHeight);
|
||||
centerGraph();
|
||||
});
|
||||
|
||||
// Mostrar contenido del nodo
|
||||
function showNodeContent(content) {
|
||||
console.log('Contenido del nodo:', content);
|
||||
}
|
||||
|
||||
// Función para obtener datos del servidor
|
||||
async function getData(paramsObj = {}) {
|
||||
try {
|
||||
let url = '/api/data';
|
||||
const params = new URLSearchParams();
|
||||
|
||||
// Establecer el tema fijo
|
||||
params.append('tema', 'demografía y sociedad');
|
||||
|
||||
// Agregar parámetros del formulario, incluyendo complejidad como umbral
|
||||
for (const key in paramsObj) {
|
||||
if (paramsObj[key] !== undefined && paramsObj[key] !== '') {
|
||||
params.append(key, paramsObj[key]);
|
||||
}
|
||||
}
|
||||
|
||||
url += `?${params.toString()}`;
|
||||
console.log('🔎 Fetch URL:', url);
|
||||
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(response.statusText);
|
||||
const data = await response.json();
|
||||
console.log('Datos recibidos del servidor:', data);
|
||||
|
||||
// Filtrar enlaces inválidos
|
||||
const nodeIds = new Set(data.nodes.map(node => node.id));
|
||||
data.links = data.links.filter(link => nodeIds.has(link.source) && nodeIds.has(link.target));
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Error al obtener datos del servidor:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Función principal: fetch, filtrar por complejidad/umbral y renderizar
|
||||
async function fetchAndRender() {
|
||||
const subtematica = document.getElementById('param2').value;
|
||||
const palabraClave = document.getElementById('param1').value;
|
||||
const fechaInicio = document.getElementById('fecha_inicio').value;
|
||||
const fechaFin = document.getElementById('fecha_fin').value;
|
||||
const nodos = document.getElementById('nodos').value;
|
||||
const complejidad = document.getElementById('complejidad').value;
|
||||
|
||||
// Usamos 'complejidad' como porcentaje de similitud mínima (umbral)
|
||||
const paramsObj = {
|
||||
subtematica,
|
||||
palabraClave,
|
||||
fechaInicio,
|
||||
fechaFin,
|
||||
nodos,
|
||||
complejidad // enviado al backend y usado de umbral en cliente
|
||||
};
|
||||
|
||||
// Parsear complejidad a número
|
||||
const umbralPct = parseFloat(complejidad) || 0;
|
||||
console.log(`Aplicando umbral de similitud: ${umbralPct}%`);
|
||||
|
||||
const graphData = await getData(paramsObj);
|
||||
if (!graphData) return;
|
||||
|
||||
// Filtrar enlaces por umbral de similitud
|
||||
let filteredLinks = graphData.links;
|
||||
if (umbralPct > 0) {
|
||||
filteredLinks = filteredLinks.filter(link => Number(link.value) >= umbralPct);
|
||||
console.log(`Enlaces tras aplicar umbral: ${filteredLinks.length}`);
|
||||
}
|
||||
|
||||
graph.graphData({ nodes: graphData.nodes, links: filteredLinks });
|
||||
centerGraph();
|
||||
}
|
||||
|
||||
// Escuchar evento submit del formulario
|
||||
form.addEventListener('submit', event => {
|
||||
event.preventDefault();
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
// Cargar gráfico inicial
|
||||
fetchAndRender();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
219
VISUALIZACION/public/popl-up.css
Executable file
|
|
@ -0,0 +1,219 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
text-shadow: 10px 10px 20px rgba(0, 255, 76, 0.3);
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70px;
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "Retrolift", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: bold;
|
||||
letter-spacing: 4px;
|
||||
text-shadow: 6px 6px 6px #73ff00;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.popl-up:hover .logo { text-shadow: 2px 2px 8px #00008b; }
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
position: relative;
|
||||
border: none;
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border: 3vw;
|
||||
align-items: center;
|
||||
border: 3px solid;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
.popl-up { color: #FF851B; background-color: orange; }
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 99%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 20%;
|
||||
height: 90vh;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-220px);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size: 18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14;
|
||||
background: black;
|
||||
color: #39ff14;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.iframe-container {
|
||||
width: calc(100% - 250px);
|
||||
height: 100vh;
|
||||
background: #000000;
|
||||
margin: 0 auto;
|
||||
border: none;
|
||||
z-index: 1;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
left: 250px;
|
||||
}
|
||||
90
VISUALIZACION/public/popl-up.html
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
+<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Demografía y Sociedad</title>
|
||||
<link rel="stylesheet" href="popl-up.css">
|
||||
|
||||
<!-- Fuentes -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;700&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Librerías necesarias -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
|
||||
<script src="https://unpkg.com/3d-force-graph"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- Navegación -->
|
||||
<nav>
|
||||
<ul class="nav-links">
|
||||
<li><a href="popl-up.html" class="popl-up">Demografía y Sociedad</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Contenedor principal -->
|
||||
<main>
|
||||
<div id="poplUpContainer" style="position: absolute; width: 100%; height: 100%; z-index: 0;"></div>
|
||||
|
||||
<!-- Fondo animado -->
|
||||
<div class="background">
|
||||
<img src="/images/flujos3.jpg">
|
||||
<img src="/images/flujos3.jpg">
|
||||
<img src="/images/flujos3.jpg">
|
||||
<img src="/images/flujos3.jpg">
|
||||
<img src="/images/flujos3.jpg">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
setTimeout(() => {
|
||||
const fondo = document.querySelector('.background');
|
||||
fondo.classList.add('fade-out');
|
||||
fondo.style.pointerEvents = 'none';
|
||||
}, 1000);
|
||||
</script>
|
||||
</main>
|
||||
|
||||
<!-- Barra lateral de filtros -->
|
||||
<div id="sidebar">
|
||||
<h2>Parámetros</h2>
|
||||
<form id="paramForm">
|
||||
<label for="fecha_inicio">Fecha de inicio:</label>
|
||||
<input type="date" id="fecha_inicio" name="fecha_inicio">
|
||||
|
||||
<label for="fecha_fin">Fecha de fin:</label>
|
||||
<input type="date" id="fecha_fin" name="fecha_fin">
|
||||
|
||||
<label for="nodos">Nodos:</label>
|
||||
<input type="number" id="nodos" name="nodos" value="100">
|
||||
|
||||
<label for="complejidad">Complejidad:</label>
|
||||
<input type="range" id="complejidad" name="complejidad" min="1" max="40" value="20">
|
||||
|
||||
<label for="param1">Búsqueda por palabra:</label>
|
||||
<input type="text" id="param1" name="param1">
|
||||
|
||||
<label for="param2">Búsqueda por temática personalizada:</label>
|
||||
<input type="text" id="param2" name="param2">
|
||||
|
||||
<input type="submit" value="Aplicar">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Botón para colapsar la barra -->
|
||||
<button id="sidebarToggle">Toggle Sidebar</button>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer>
|
||||
<p>
|
||||
<a href="#">GitHub</a> |
|
||||
<a href="#">Telegram</a> |
|
||||
<a href="#">Email</a> |
|
||||
<a href="#">Web de Tor</a>
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<!-- Script principal -->
|
||||
<script src="output_popl_up_pruebas.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
72
VISUALIZACION/public/script_eco-corp.css
Executable file
|
|
@ -0,0 +1,72 @@
|
|||
:root {
|
||||
--cube-size: 70px; /* Tamaño reducido de los cubos */
|
||||
--line-color: #333;
|
||||
--hover-color: #2ecc71;
|
||||
}
|
||||
|
||||
.graph-container {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: #000;
|
||||
border: 1px solid #ddd;
|
||||
margin: 20px auto;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
.cube-container {
|
||||
position: absolute;
|
||||
width: var(--cube-size);
|
||||
height: var(--cube-size);
|
||||
transform-style: preserve-3d;
|
||||
transition: transform 1s;
|
||||
}
|
||||
|
||||
.cube-container:hover {
|
||||
transform: rotateX(360deg) rotateY(360deg);
|
||||
}
|
||||
|
||||
.cube {
|
||||
position: absolute;
|
||||
width: var(--cube-size);
|
||||
height: var(--cube-size);
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
|
||||
.face {
|
||||
position: absolute;
|
||||
width: var(--cube-size);
|
||||
height: var(--cube-size);
|
||||
background-color: var(--hover-color);
|
||||
border: 1px solid #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Posiciones de las caras del cubo */
|
||||
.front { transform: translateZ(calc(var(--cube-size) / 2)); }
|
||||
.back { transform: rotateY(180deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.left { transform: rotateY(-90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.right { transform: rotateY(90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.top { transform: rotateX(90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
.bottom { transform: rotateX(-90deg) translateZ(calc(var(--cube-size) / 2)); }
|
||||
|
||||
.lines {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.line-path {
|
||||
stroke: var(--line-color);
|
||||
stroke-width: 2;
|
||||
transition: stroke 0.3s;
|
||||
}
|
||||
|
||||
.line-path:hover {
|
||||
stroke: #e74c3c;
|
||||
}
|
||||
82
VISUALIZACION/public/script_eco-corp.html
Executable file
|
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Noticias de Guerras y Conflictos Políticos - Disposición Aleatoria</title>
|
||||
<link rel="stylesheet" type="text/css" href="script_eco-corp.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Noticias de Guerras y Conflictos Políticos - Últimos 10 años</h1>
|
||||
<div class="graph-container" id="graph-container">
|
||||
<!-- Los cubos serán añadidos dinámicamente con JavaScript -->
|
||||
<svg class="lines" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" id="svg-lines">
|
||||
<!-- Las flechas también serán generadas dinámicamente -->
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const numCubes = 5; // Número de cubos
|
||||
const graphContainer = document.getElementById('graph-container');
|
||||
const svgLines = document.getElementById('svg-lines');
|
||||
let cubePositions = [];
|
||||
|
||||
// Función para generar una posición aleatoria dentro del contenedor
|
||||
function getRandomPosition(maxWidth, maxHeight) {
|
||||
return {
|
||||
x: Math.floor(Math.random() * (maxWidth - 100)),
|
||||
y: Math.floor(Math.random() * (maxHeight - 100))
|
||||
};
|
||||
}
|
||||
|
||||
// Función para generar cubos aleatoriamente
|
||||
function generateCubes(num) {
|
||||
for (let i = 0; i < num; i++) {
|
||||
const position = getRandomPosition(window.innerWidth, window.innerHeight);
|
||||
const cubeContainer = document.createElement('div');
|
||||
cubeContainer.classList.add('cube-container');
|
||||
cubeContainer.style.top = position.y + 'px';
|
||||
cubeContainer.style.left = position.x + 'px';
|
||||
|
||||
cubeContainer.innerHTML = `
|
||||
<div class="cube">
|
||||
<div class="face front">País ${i+1}</div>
|
||||
<div class="face back">Detalle ${i+1}</div>
|
||||
<div class="face left">Año ${2010 + i}</div>
|
||||
<div class="face right">Muertos ${(i+1)*1000}</div>
|
||||
<div class="face top">ONU</div>
|
||||
<div class="face bottom">Fuente</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
cubePositions.push({x: position.x + 35, y: position.y + 35}); // Ajustar al centro del cubo
|
||||
graphContainer.appendChild(cubeContainer);
|
||||
}
|
||||
}
|
||||
|
||||
// Función para generar las flechas que conectan los cubos
|
||||
function generateLines() {
|
||||
for (let i = 0; i < cubePositions.length - 1; i++) {
|
||||
const x1 = cubePositions[i].x;
|
||||
const y1 = cubePositions[i].y;
|
||||
const x2 = cubePositions[i + 1].x;
|
||||
const y2 = cubePositions[i + 1].y;
|
||||
|
||||
const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
||||
line.setAttribute('x1', x1);
|
||||
line.setAttribute('y1', y1);
|
||||
line.setAttribute('x2', x2);
|
||||
line.setAttribute('y2', y2);
|
||||
line.setAttribute('stroke', '#333');
|
||||
line.setAttribute('stroke-width', '2');
|
||||
|
||||
svgLines.appendChild(line);
|
||||
}
|
||||
}
|
||||
|
||||
// Generar cubos y flechas al cargar la página
|
||||
generateCubes(numCubes);
|
||||
generateLines();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
995
VISUALIZACION/public/styles.css
Executable file
|
|
@ -0,0 +1,995 @@
|
|||
@font-face {
|
||||
font-family: "Retrolift";
|
||||
src: url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff2") format("woff2"),
|
||||
url("/home/pancho/PROGRAMACION/FLUJOS/retrolift.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Fira Code';
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', monospace;
|
||||
background: #000000;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
header {
|
||||
position: relative;
|
||||
height: 120px;
|
||||
background-color: #000000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: 'Nosifer';
|
||||
color: #ffffff;
|
||||
font-size: 6.5rem;
|
||||
margin: 0 auto;
|
||||
line-height: 1.2;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
max-width: 1200px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.small-button {
|
||||
margin-left: 5px;
|
||||
margin-right: 3px;
|
||||
padding: 4px 8px;
|
||||
font-size: 10px;
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background-color: #000000;
|
||||
border: 2px solid #ffffff;
|
||||
border-radius: 20px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.small-button:hover {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
background-color: #000000;
|
||||
color: #ff1a1a;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.1);
|
||||
margin-top: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 14em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
font-size: 1em;
|
||||
font-weight: bold;
|
||||
transition: color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
|
||||
padding: 20px 40px;
|
||||
box-shadow: 0 0 0px rgba(28, 103, 241, 0);
|
||||
position: relative;
|
||||
border: none;
|
||||
transition: .4s ease-in;
|
||||
z-index: 1;
|
||||
width: 40vw;
|
||||
height: 20vh;
|
||||
border: 3vw;
|
||||
align-items: center;
|
||||
border: 3px solid;
|
||||
}
|
||||
|
||||
.nav-links a:hover {
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 6px rgba(0,0,0,0.3);
|
||||
box-shadow: 2vw 1vw;
|
||||
border: 3px solid black;
|
||||
}
|
||||
|
||||
.glob-war:hover { color: #39ff14; }
|
||||
.int-sec:hover { color: #ff69b4; }
|
||||
.climate:hover { color: #ff4500; }
|
||||
.eco-corp:hover { color: #00fff2; }
|
||||
.popl-up:hover { color: #0066ff; }
|
||||
|
||||
.glob-war {
|
||||
color: #FF4136;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.int-sec {
|
||||
color: #0074D9;
|
||||
background-color: darkblue;
|
||||
}
|
||||
|
||||
.climate {
|
||||
color: #2ECC40;
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
.eco-corp {
|
||||
color: #FFDC00;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.popl-up {
|
||||
color: #FF851B;
|
||||
background-color: orange;
|
||||
}
|
||||
|
||||
|
||||
.background {
|
||||
display: flex;
|
||||
justify-content: center; /* Centrar horizontalmente */
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: hidden; /* Oculta cualquier posible desplazamiento horizontal */
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.background a {
|
||||
display: block;
|
||||
flex: 1; /* Asegura que cada imagen se expanda uniformemente para ocupar todo el espacio disponible */
|
||||
height: 100%;
|
||||
transition: transform 1.5s ease;
|
||||
}
|
||||
|
||||
.background img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 1.5s ease;
|
||||
margin: 0; /* Elimina cualquier margen alrededor de las imágenes */
|
||||
}
|
||||
|
||||
.background img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
|
||||
#sidebar.active {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 250px;
|
||||
height: 100vh;
|
||||
background-image: url("/images/flujos7.jpg");
|
||||
background-size: cover;
|
||||
color: #39ff14;
|
||||
padding: 30px;
|
||||
box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
|
||||
transform: translateX(-90%);
|
||||
transition: transform 0.3s ease-out;
|
||||
overflow: auto;
|
||||
font-size: 18px;
|
||||
z-index: 3;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar h2 {
|
||||
color: #39ff14;
|
||||
font-size: 1.2em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: -1px 0 black, 0 3px black, 3px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar:hover {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
position: absolute;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
background: #007BFF;
|
||||
color: #39ff14;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
transition: background 0.3s ease;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#sidebarToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#sidebar form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
#sidebar label {
|
||||
color: #39ff14;
|
||||
font-size: 0.9em;
|
||||
font-weight: bold;
|
||||
text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black;
|
||||
}
|
||||
|
||||
#sidebar input {
|
||||
padding: 10px;
|
||||
border: 2px solid #39ff14;
|
||||
background: black;
|
||||
color: #39ff14;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.2);
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
#sidebar input:hover {
|
||||
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"] {
|
||||
color: #39ff14;
|
||||
background: #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#sidebar input[type="submit"]:hover {
|
||||
background: #ff6600;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
background-color: #000000;
|
||||
color: #39ff14;
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #39ff14;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #2ECC40;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#canvasContainer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.button-overlay {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: calc(100% - 100px);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px; /* Incrementa el espacio entre botones */
|
||||
width: 13%; /* Reducido el ancho de las columnas de botones */
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
display: block;
|
||||
padding: 10px 15px; /* Ajustar para reducir el tamaño del botón */
|
||||
color: #ffffff;
|
||||
font-weight: bold; /* Hacer el texto más grueso */
|
||||
text-decoration: none;
|
||||
border-radius: 30px; /* Bordes redondeados para un efecto de cilindro */
|
||||
font-size: 1em;
|
||||
border: 2px solid #ffffff;
|
||||
background-color: black; /* Fondo negro */
|
||||
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.overlay-button:hover {
|
||||
transform: scale(1.05);
|
||||
color: #ffffff;
|
||||
background-color: transparent;
|
||||
box-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
/* Media Queries for larger screens */
|
||||
@media screen and (max-width: 1920px) {
|
||||
.background a {
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 18%;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 1.1em;
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 7rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 1em;
|
||||
padding: 8px 14px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 14em;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
.background a {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 1em;
|
||||
padding: 14px 18px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 6.5rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.9em;
|
||||
padding: 7px 13px;
|
||||
}
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 6em;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1440px) {
|
||||
.background a {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.95em;
|
||||
padding: 12px 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 6rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.85em;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.85em;
|
||||
padding: 16px 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1280px) {
|
||||
.background a {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.5em;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 5.5rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.4em;
|
||||
padding: 6px 11px;
|
||||
}
|
||||
.nav-links {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 5em;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
.background a {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.35em;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.75em;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.75em;
|
||||
padding: 12px 20px;
|
||||
}
|
||||
}
|
||||
/* Para teléfonos de 768px de ancho en portrait */
|
||||
@media screen and (max-width: 768px) and (orientation: portrait) {
|
||||
.background a {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 90%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.6rem;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 2px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
gap: 2em; /* Reduce el espacio entre los enlaces del nav */
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.8rem;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Para teléfonos de 576px de ancho en portrait */
|
||||
@media screen and (max-width: 576px) and (orientation: portrait) {
|
||||
.background a {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 95%;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 5px 7px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 4px 7px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
gap: 1.5em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.4rem;
|
||||
padding: 7px 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Para teléfonos de 411px de ancho en portrait */
|
||||
@media screen and (max-width: 411px) and (orientation: portrait) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 100%;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.4rem;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.6rem;
|
||||
padding: 6px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Para teléfonos de 375px de ancho en portrait */
|
||||
@media screen and (max-width: 375px) and (orientation: portrait) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 100%;
|
||||
gap: 3px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
gap: 0.75em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.5rem;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Para teléfonos de 320px de ancho en portrait */
|
||||
@media screen and (max-width: 320px) and (orientation: portrait) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 100%;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.4rem;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* For devices with smaller screens (e.g., 600px - 800px width) */
|
||||
@media screen and (min-width: 600px) and (max-width: 800px) and (max-height: 400px) and (orientation: landscape) {
|
||||
.background {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.button-overlay {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 15%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 2px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 2px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.3rem; /* Reduced font size */
|
||||
padding: 15px 30px; /* Adjusted padding */
|
||||
}
|
||||
}
|
||||
|
||||
/* For medium-sized devices (e.g., 800px - 1000px width) */
|
||||
@media screen and (min-width: 800px) and (max-width: 1000px) and (max-height: 450px) and (orientation: landscape) {
|
||||
.background {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.button-overlay {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 16%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 3px 3px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 3px 3px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.3rem; /* Reduced font size */
|
||||
padding: 15px 30px; /* Adjusted padding */
|
||||
}
|
||||
}
|
||||
|
||||
/* For larger devices (e.g., 1000px - 1200px width) */
|
||||
@media screen and (min-width: 1000px) and (max-width: 1200px) and (max-height: 500px) and (orientation: landscape) {
|
||||
.background {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.button-overlay {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 17%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.4rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.3rem; /* Reduced font size */
|
||||
padding: 15px 30px; /* Adjusted padding */
|
||||
}
|
||||
}
|
||||
|
||||
/* For even larger devices (e.g., 1200px - 1500px width) */
|
||||
@media screen and (min-width: 1200px) and (max-width: 1500px) and (max-height: 700px) and (orientation: landscape) {
|
||||
.background {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.button-overlay {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 18%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.45rem;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.3rem; /* Reduced font size */
|
||||
padding: 15px 30px; /* Adjusted padding */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 800px) and (orientation: landscape) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 20%;
|
||||
gap: 5px;
|
||||
margin-top: 40px; /* Push buttons down to avoid navbar */
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.35rem;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.35rem;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
}
|
||||
|
||||
/* For devices with width around 700px */
|
||||
@media screen and (max-width: 700px) and (orientation: landscape) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 25%;
|
||||
gap: 5px;
|
||||
margin-top: 50px; /* Further adjustment */
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.3rem;
|
||||
padding: 2px 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/* For smaller devices with width around 600px */
|
||||
@media screen and (max-width: 600px) and (orientation: landscape) {
|
||||
.background a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 30%;
|
||||
gap: 5px;
|
||||
margin-top: 60px; /* Ensures the buttons are well below the navbar */
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.4rem;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.5rem;
|
||||
padding: 3px 5px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.5rem;
|
||||
padding: 3px 5px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Landscape mode for screens up to 480px wide */
|
||||
@media screen and (max-width: 480px) and (orientation: landscape) {
|
||||
.button-overlay {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 5px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.button-column {
|
||||
width: 28%;
|
||||
gap: 2px;
|
||||
margin-top:150px;
|
||||
}
|
||||
|
||||
.overlay-button {
|
||||
font-size: 0.45rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.small-button {
|
||||
font-size: 0.45rem;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
font-size: 0.45rem;
|
||||
padding: 3px 4px;
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||