Замечание: Возможно, после публикации вам придётся очистить кэш своего браузера, чтобы увидеть изменения.
- Firefox / Safari: Удерживая клавишу Shift, нажмите на панели инструментов Обновить либо нажмите Ctrl+F5 или Ctrl+R (⌘+R на Mac)
- Google Chrome: Нажмите Ctrl+Shift+R (⌘+Shift+R на Mac)
- Internet Explorer / Edge: Удерживая Ctrl, нажмите Обновить либо нажмите Ctrl+F5
- Opera: Нажмите Ctrl+F5.
(function() {
'use strict';
// Проверяем, что мы не на мобильном устройстве (для производительности)
var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
var isLowPerformance = navigator.hardwareConcurrency < 4;
// Конфигурация частиц под тему сайта
var themeColors = {
primary: '#77c1d9',
secondary: '#9dd7ea',
accent: '#b8e6ff',
background: '#1a1a1f'
};
// Функция создания и настройки частиц
function initParticleSystem() {
// Проверяем, не создан ли уже контейнер
if (document.getElementById('particles-js')) {
return;
}
// Создаем стилизованный контейнер
var particlesDiv = document.createElement('div');
particlesDiv.id = 'particles-js';
particlesDiv.setAttribute('aria-hidden', 'true'); // Для доступности
// Вставляем после body, но перед основным контентом
var mwBody = document.querySelector('.mw-body');
if (mwBody) {
document.body.insertBefore(particlesDiv, mwBody);
} else {
document.body.appendChild(particlesDiv);
}
// Улучшенные стили с адаптивностью
var particleStyles = document.createElement('style');
particleStyles.id = 'particles-styles';
particleStyles.innerHTML = `
#particles-js {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1;
pointer-events: none;
opacity: 0.8;
transition: opacity 0.5s ease;
}
/* Уменьшаем эффект на маленьких экранах */
@media (max-width: 768px) {
#particles-js {
opacity: 0.3;
}
}
/* Полностью отключаем на очень маленьких экранах */
@media (max-width: 480px) {
#particles-js {
display: none;
}
}
/* Уменьшаем эффект при предпочтении пользователя */
@media (prefers-reduced-motion: reduce) {
#particles-js {
opacity: 0.2;
}
}
/* Адаптация под высокий DPI */
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
#particles-js canvas {
image-rendering: crisp-edges;
}
}
/* Плавное появление частиц */
#particles-js.loaded {
animation: particlesFadeIn 2s ease-in;
}
@keyframes particlesFadeIn {
from { opacity: 0; }
to { opacity: 0.8; }
}
`;
document.head.appendChild(particleStyles);
// Загружаем библиотеку с обработкой ошибок
loadParticlesLibrary();
}
// Улучшенная функция загрузки библиотеки
function loadParticlesLibrary() {
// Проверяем, не загружена ли уже библиотека
if (window.particlesJS) {
initParticles();
return;
}
var script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/particles.js/2.0.0/particles.min.js';
script.async = true;
script.defer = true;
script.onload = function() {
console.log('Particles.js загружена успешно');
initParticles();
};
script.onerror = function() {
console.warn('Не удалось загрузить particles.js');
// Можно добавить fallback эффект
addFallbackEffect();
};
document.head.appendChild(script);
}
// Основная функция инициализации частиц
function initParticles() {
var particleCount = getOptimalParticleCount();
var config = {
particles: {
number: {
value: particleCount,
density: {
enable: true,
value_area: 1000
}
},
color: {
value: [themeColors.primary, themeColors.secondary, themeColors.accent]
},
shape: {
type: ['circle', 'triangle'],
stroke: {
width: 0,
color: themeColors.primary
},
polygon: {
nb_sides: 6
}
},
opacity: {
value: 0.6,
random: true,
anim: {
enable: true,
speed: 0.8,
opacity_min: 0.1,
sync: false
}
},
size: {
value: 4,
random: true,
anim: {
enable: true,
speed: 2,
size_min: 0.5,
sync: false
}
},
line_linked: {
enable: true,
distance: 180,
color: themeColors.primary,
opacity: 0.3,
width: 1.5
},
move: {
enable: true,
speed: isMobile ? 2 : 4,
direction: 'none',
random: true,
straight: false,
out_mode: 'out',
bounce: false,
attract: {
enable: true,
rotateX: 600,
rotateY: 1200
}
}
},
interactivity: {
detect_on: 'window',
events: {
onhover: {
enable: !isMobile,
mode: 'grab'
},
onclick: {
enable: true,
mode: 'push'
},
resize: true
},
modes: {
grab: {
distance: 200,
line_linked: {
opacity: 0.8
}
},
bubble: {
distance: 300,
size: 8,
duration: 2,
opacity: 0.8,
speed: 3
},
repulse: {
distance: 150,
duration: 0.4
},
push: {
particles_nb: 3
},
remove: {
particles_nb: 2
}
}
},
retina_detect: true
};
// Инициализируем частицы с callback
particlesJS('particles-js', config, function() {
console.log('Particles.js: система частиц активирована');
document.getElementById('particles-js').classList.add('loaded');
});
// Добавляем контроли производительности
addPerformanceControls();
}
// Определяем оптимальное количество частиц
function getOptimalParticleCount() {
var baseCount = 60;
if (isMobile) return Math.floor(baseCount * 0.5);
if (isLowPerformance) return Math.floor(baseCount * 0.7);
if (window.innerWidth < 1200) return Math.floor(baseCount * 0.8);
return baseCount;
}
// Добавляем контроли производительности
function addPerformanceControls() {
var particleContainer = document.getElementById('particles-js');
if (!particleContainer) return;
// Уменьшаем интенсивность при переключении вкладок
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
particleContainer.style.opacity = '0.1';
} else {
particleContainer.style.opacity = '0.8';
}
});
// Адаптируем к изменению размера окна
var resizeTimeout;
window.addEventListener('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
if (window.pJSDom && window.pJSDom[0]) {
window.pJSDom[0].pJS.fn.particlesRefresh();
}
}, 300);
});
}
// Fallback эффект при неудачной загрузке
function addFallbackEffect() {
var particleContainer = document.getElementById('particles-js');
if (!particleContainer) return;
particleContainer.innerHTML = `
<div style="
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(ellipse at center,
rgba(119, 193, 217, 0.1) 0%,
rgba(26, 26, 31, 0.8) 70%);
animation: pulseGlow 4s ease-in-out infinite;
"></div>
`;
var fallbackStyle = document.createElement('style');
fallbackStyle.innerHTML = `
@keyframes pulseGlow {
0%, 100% { opacity: 0.3; }
50% { opacity: 0.6; }
}
`;
document.head.appendChild(fallbackStyle);
}
// Функция очистки (для отладки)
function cleanupParticles() {
var container = document.getElementById('particles-js');
var styles = document.getElementById('particles-styles');
if (container) container.remove();
if (styles) styles.remove();
if (window.pJSDom) {
window.pJSDom = [];
}
}
// Экспорт функций для отладки
window.particleSystem = {
init: initParticleSystem,
cleanup: cleanupParticles,
config: themeColors
};
// Инициализация после загрузки MediaWiki
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initParticleSystem);
} else {
initParticleSystem();
}
})();
// Дополнительные улучшения для интеграции с темой
mw.hook('wikipage.content').add(function($content) {
// Подстраиваем частицы под контент страницы
setTimeout(function() {
if (window.pJSDom && window.pJSDom[0]) {
window.pJSDom[0].pJS.fn.particlesRefresh();
}
}, 500);
});