Santa Ana 30
o C 46% H
San Salvador 28
o C 55% H
San Miguel 28
o C 55% H
Surf City 28
o C 55% H
// ===== Parámetros de control =====
const durDesktop = 16;
const durMobile = 10;
const easingX = "slow(0.7,0.7,false)"; const floatDesktop = { amp: 200, dur: 2.5 };
const floatMobile = { amp: 80, dur: 3.8 }; const trailConfig = {
rate: 1.0, // partículas/tick (base a 60fps, se ajusta por delta)
maxParticles: 250,
baseSize: 8,
sizeJitter: 6,
life: 0.9,
hue: 15,
saturation: 80,
lightness: 60,
alpha: 0.6
}; const shootingConfig = {
intervalMin: 1800,
intervalMax: 4200,
speedMin: 900,
speedMax: 1600,
length: 160,
thickness: 2.2,
glow: 0.35
}; // ===== Flags de sistema =====
const prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches; // ===== Contexto y MatchMedia (limpieza segura) =====
const mm = gsap.matchMedia();
const ctx = gsap.context(() => {
const el = document.querySelector(".elemento-x");
const pista = document.querySelector(".animacion");
if (!el || !pista) return; // ====== Trail (canvas) ======
const trailCanvas = document.getElementById("trailCanvas");
const trailCtx = trailCanvas?.getContext("2d");
let trailParticles = [];
const DPR = Math.max(1, Math.min(window.devicePixelRatio || 1, 2)); // limit 2 por perf // dimensiones CSS para limpiar correctamente
let trailCssW = 0, trailCssH = 0;
function sizeTrailCanvas(){
if (!trailCanvas || !trailCtx) return;
const rect = trailCanvas.getBoundingClientRect();
trailCssW = Math.max(1, Math.round(rect.width));
trailCssH = Math.max(1, Math.round(rect.height));
trailCanvas.width = trailCssW * DPR;
trailCanvas.height = trailCssH * DPR;
trailCtx.setTransform(DPR,0,0,DPR,0,0); // dibujar en unidades CSS
trailCtx.globalCompositeOperation = "lighter";
}
sizeTrailCanvas();
window.addEventListener("resize", sizeTrailCanvas, { passive: true }); function addTrailParticle(x, y, vx, vy){
if (trailParticles.length >= trailConfig.maxParticles) trailParticles.shift();
trailParticles.push({
x, y, vx, vy,
size: trailConfig.baseSize + Math.random()*trailConfig.sizeJitter,
alpha: trailConfig.alpha
});
} // Emisión basada en posición del elemento y delta de tiempo
function emitTrail(particlesToEmit){
if (!el || !pista) return;
const elRect = el.getBoundingClientRect();
const pistaRect = pista.getBoundingClientRect(); const emitX = (elRect.left - pistaRect.left) + elRect.width * 0.15;
const emitY = (elRect.top - pistaRect.top) + elRect.height* 0.58; for (let i = 0; i < particlesToEmit; i++){
const jitterX = -1.5 - Math.random()*1.5; // un poco hacia atrás
const jitterY = (Math.random()-0.5) * 1.2; // ligera dispersión
addTrailParticle(emitX, emitY, jitterX, jitterY);
}
} function renderTrail(){
if (!trailCtx) return;
// limpieza con desvanecido
trailCtx.fillStyle = "rgba(0,0,0,0.08)";
trailCtx.fillRect(0, 0, trailCssW, trailCssH); for (let i = trailParticles.length - 1; i >= 0; i--){
const p = trailParticles[i];
p.x += p.vx;
p.y += p.vy;
p.alpha *= trailConfig.life; if (p.alpha < 0.02){
trailParticles.splice(i,1);
continue;
} const grad = trailCtx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.size);
const c1 = `hsla(${trailConfig.hue}, ${trailConfig.saturation}%, ${trailConfig.lightness}%, ${p.alpha})`;
const c0 = `hsla(${trailConfig.hue}, ${trailConfig.saturation}%, ${Math.min(trailConfig.lightness+15,95)}%, ${p.alpha*0.9})`;
grad.addColorStop(0, c0);
grad.addColorStop(1, c1); trailCtx.fillStyle = grad;
trailCtx.beginPath();
trailCtx.arc(p.x, p.y, p.size, 0, Math.PI*2);
trailCtx.fill();
}
} // Ticker GSAP con deltaRatio (1 = 60fps)
let trailTicker;
let emitAccumulator = 0; // para soportar fracciones
function startTrail(){
if (!trailCanvas || !trailCtx) return;
if (prefersReduced) return; // omitir en modo reducido
if (trailTicker) return;
trailTicker = () => {
const dr = gsap.ticker.deltaRatio(); // ~1 a 60fps
const toEmit = trailConfig.rate * dr; // escala por delta
emitAccumulator += toEmit;
const emitNow = Math.floor(emitAccumulator);
if (emitNow > 0){
emitTrail(emitNow);
emitAccumulator -= emitNow;
}
renderTrail();
};
gsap.ticker.add(trailTicker);
}
function stopTrail(){
if (trailTicker){
gsap.ticker.remove(trailTicker);
trailTicker = null;
}
} // ===== Estrellas fugaces (canvas de fondo) =====
const starsCanvas = document.getElementById("starsCanvas");
const starsCtx = starsCanvas?.getContext("2d");
let starsObjects = [];
let starsReqId = null;
let starsCssW = 0, starsCssH = 0; function sizeStarsCanvas(){
if (!starsCanvas || !starsCtx) return;
starsCssW = Math.max(1, Math.round(starsCanvas.clientWidth));
starsCssH = Math.max(1, Math.round(starsCanvas.clientHeight));
starsCanvas.width = starsCssW * DPR;
starsCanvas.height = starsCssH * DPR;
starsCtx.setTransform(DPR,0,0,DPR,0,0);
}
sizeStarsCanvas();
window.addEventListener("resize", sizeStarsCanvas, { passive: true }); let shootingTimer = null;
function spawnShootingStar(){
if (!starsCanvas) return;
const w = starsCssW;
const h = starsCssH; // Origen aleatorio en el tercio superior izquierdo
const startX = -40 + Math.random()*80;
const startY = Math.random() * h * 0.35 + 10; const angle = (Math.PI/180) * (20 + Math.random()*20);
const speedMs = shootingConfig.speedMin + Math.random()*(shootingConfig.speedMax - shootingConfig.speedMin);
const pxPerSec = w / (speedMs/1000); // proporcional al ancho
const vx = Math.cos(angle) * pxPerSec;
const vy = Math.sin(angle) * pxPerSec; starsObjects.push({
x: startX, y: startY, vx, vy,
life: 1,
length: shootingConfig.length,
thickness: shootingConfig.thickness
}); // programa la siguiente
const wait = shootingConfig.intervalMin + Math.random()*(shootingConfig.intervalMax - shootingConfig.intervalMin);
shootingTimer = window.setTimeout(spawnShootingStar, wait);
} let lastTs = 0;
function renderShootingStars(ts){
if (!starsCtx) return;
const dt = lastTs ? Math.min(0.05, (ts - lastTs)/1000) : 0; // seg, cap 50ms
lastTs = ts; starsCtx.clearRect(0, 0, starsCssW, starsCssH); for (let i = starsObjects.length-1; i >= 0; i--){
const s = starsObjects[i];
s.x += s.vx * dt;
s.y += s.vy * dt;
s.life *= 0.965; if (s.life < 0.02 || s.x > starsCssW + s.length || s.y > starsCssH + s.length){
starsObjects.splice(i,1);
continue;
} const mag = Math.hypot(s.vx, s.vy) || 1;
const ux = s.vx / mag, uy = s.vy / mag;
const endX = s.x - s.length * ux;
const endY = s.y - s.length * uy; const grad = starsCtx.createLinearGradient(s.x, s.y, endX, endY);
grad.addColorStop(0, `rgba(255,255,255,${0.9 * s.life})`);
grad.addColorStop(0.3, `rgba(255,240,200,${0.6 * s.life})`);
grad.addColorStop(1, `rgba(255,255,255,0)`); starsCtx.strokeStyle = grad;
starsCtx.lineWidth = s.thickness;
starsCtx.lineCap = "round";
starsCtx.shadowColor = `rgba(255,255,255,${shootingConfig.glow})`;
starsCtx.shadowBlur = 8; starsCtx.beginPath();
starsCtx.moveTo(s.x, s.y);
starsCtx.lineTo(endX, endY);
starsCtx.stroke();
} starsReqId = requestAnimationFrame(renderShootingStars);
} function startStars(){
if (!starsCanvas || !starsCtx) return;
if (prefersReduced) return; // omitir en modo reducido
if (!starsReqId) starsReqId = requestAnimationFrame(renderShootingStars);
if (!shootingTimer) spawnShootingStar();
}
function stopStars(){
if (starsReqId){
cancelAnimationFrame(starsReqId);
starsReqId = null;
}
if (shootingTimer){
clearTimeout(shootingTimer);
shootingTimer = null;
}
starsObjects.length = 0;
lastTs = 0;
if (starsCtx) starsCtx.clearRect(0, 0, starsCssW, starsCssH);
} // ===== Animación principal (GSAP) =====
function animateSanta(durationX, ampY, durY){
if (!el) return; // Movimiento horizontal
const moveTween = gsap.to(el, {
x: "250vw",
duration: durationX,
ease: easingX,
repeat: 2
}); // Flotación
const floatTween = gsap.to(el, {
y: `-=${ampY}`,
duration: durY,
ease: "sine.inOut",
yoyo: true,
repeat: -1
}); // Arrancar trail mientras se mueve
startTrail(); // Detener trail y flotación al acabar el cruce completo
gsap.delayedCall(durationX * (moveTween.repeat() + 1), () => {
floatTween.kill();
stopTrail();
}); return { moveTween, floatTween };
} // ===== MatchMedia breakpoints =====
let currentAnim = null;
mm.add({
isDesktop: "(min-width: 992px)",
isMobile: "(max-width: 991px)"
}, (ctxMM) => {
const { isDesktop, isMobile } = ctxMM.conditions;
const dX = isDesktop ? durDesktop : durMobile;
const amp = isDesktop ? floatDesktop.amp : floatMobile.amp;
const dY = isDesktop ? floatDesktop.dur : floatMobile.dur; // En modo reducido: minimizar
if (prefersReduced){
// Posicionar sin animar, sin trail ni estrellas
gsap.set(el, { x: "0vw", y: 0 });
return () => {};
} currentAnim = animateSanta(dX, amp, dY);
startStars(); // Limpieza al cambiar media query
return () => {
if (currentAnim){
currentAnim.moveTween?.kill();
currentAnim.floatTween?.kill();
currentAnim = null;
}
stopTrail();
stopStars();
};
}); // Pausar todo al ocultar pestaña
document.addEventListener("visibilitychange", () => {
const hidden = document.hidden;
gsap.ticker.lagSmoothing( hidden ? 0 : 1000, hidden ? 0 : 16 ); // estabiliza dt
if (hidden){
gsap.globalTimeline.pause();
stopTrail();
stopStars();
} else {
gsap.globalTimeline.resume();
startTrail();
startStars();
}
}); }); // Limpieza al navegar/recargar
window.addEventListener("beforeunload", () => {
mm.revert();
ctx.revert();
});
Home - Noticias - Nacional
Sentencian a 10 años de internamiento a dos menores en Soyapango Fueron detenidos afuera de un centro comercial en 2022. La Fiscalía los acusó por agrupaciones ilícitas y el juicio contó con la declaración de un testigo.
Dos menores de edad fueron condenados a 10 años de internamiento por el delito de agrupaciones ilícitas, informó la Fiscalía General de la República. Los jóvenes formaban parte de una clica que delinque en Soyapango.
Según detalla la acusación, los menores fueron detenidos en las afueras de un centro comercial en Soyapango en noviembre de 2022. La Fiscalía señaló que las capturas se produjeron en el marco del régimen de excepción.
Ambos adolescentes fueron perfilados por un testigo como miembros de la "Cancha Santa Elena, tribu San Martín de la Pandilla 18 sureños". Además de que poseían tatujaes alusivos a la pandilla.
LEA TAMBIÉN: Hombre que fue condenado a 87 años de cárcel en 2020 fue capturado ayer
El Juzgado de Menores de Soyapango dictó la sentencia tras avalar la investigación fiscal.
Según las reformas a la Ley Penal Juvenil aprobadas en marzo de 2022 por la Asamblea Legislativa, los menores de edad que hubieren cumplido los 16 años que cometieren delitos pagarán prisión de hasta 20 años, y cuando hubieren cumplido los 12 años estarán hasta 10 años en la cárcel.
En mayo pasado, otro pandillero menor de edad fue sentenciado a 20 años de internamiento por agrupaciones ilícitas, tenencia ilegal de arma de fuego, provisión de armas y municiones y tenencia de drogas
El menor había sido sorprendido trasladando las armas en una zona rural de Ilobasco, Cabañas, en octubre de 2022.
IR A LA PORTADA