diff --git a/docs/docusaurus/src/css/custom.css b/docs/docusaurus/src/css/custom.css index 2bf87f355b..83098213ed 100644 --- a/docs/docusaurus/src/css/custom.css +++ b/docs/docusaurus/src/css/custom.css @@ -448,24 +448,33 @@ li > a.menu__link { .falling-icon { position: absolute; + top: -100px; width: 40px; height: auto; opacity: 0; - animation-name: fall; - animation-timing-function: linear; - animation-iteration-count: infinite; + animation: falling linear infinite; + will-change: transform; + user-select: none; + pointer-events: none; } -@keyframes fall { +@keyframes falling { 0% { - transform: translateY(-100px); - opacity: 0.25; + transform: translateY(-100px) ; + opacity: 0.3; } - 27% { + 31% { opacity: 0; } 100% { - transform: translateY(100vh); + transform: translateY(calc(100vh + 100px)); opacity: 0; } +} + +/* Адаптивность для мобильных устройств */ +@media (max-width: 768px) { + .falling-icon { + width: 30px !important; + } } \ No newline at end of file diff --git a/docs/docusaurus/src/pages/index.js b/docs/docusaurus/src/pages/index.js index 6f4b2d218a..306daa4021 100644 --- a/docs/docusaurus/src/pages/index.js +++ b/docs/docusaurus/src/pages/index.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import clsx from 'clsx'; import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; @@ -34,29 +34,67 @@ const iconList = [ '/img/APIs/SQLite.png', '/img/APIs/TCP.png', '/img/APIs/VKTeams.png', - // ... добавьте все свои иконки ]; const FallingIcons = () => { - const iconCount = 60; // количество падающих иконок + const [columns, setColumns] = useState(12); + const [iconCount, setIconCount] = useState(60); + const [iconDensity] = useState(0.6); // Плотность иконок (0.1-1.0) + + useEffect(() => { + const updateLayout = () => { + // Адаптивное количество колонок + const width = window.innerWidth; + const newColumns = width < 768 ? 6 : width < 1024 ? 9 : 12; + setColumns(newColumns); + + // Адаптивное количество иконок на основе плотности + const area = width * window.innerHeight; + const newIconCount = Math.floor(area / (2000 * (1.1 - iconDensity))); + setIconCount(Math.min(newIconCount, 100)); // Ограничиваем максимум 100 иконками + }; + + updateLayout(); + window.addEventListener('resize', updateLayout); + return () => window.removeEventListener('resize', updateLayout); + }, [iconDensity]); + + const maxIconsPerColumn = Math.ceil(iconCount / columns); const icons = []; + const columnCounts = Array(columns).fill(0); for (let i = 0; i < iconCount; i++) { const randomIcon = iconList[Math.floor(Math.random() * iconList.length)]; - const left = (i / (iconCount - 1)) * 100; // равномерное распределение по ширине - const duration = Math.random() + 20;// случайная длительность от 6 до 10 секунд - const delay = Math.random() * 20; // случайная задержка от 0 до 5 секунд + + // Выбираем колонку с наименьшим количеством иконок + let column = 0; + let minCount = columnCounts[0]; + for (let c = 1; c < columns; c++) { + if (columnCounts[c] < minCount) { + minCount = columnCounts[c]; + column = c; + } + } + columnCounts[column]++; + + // Распределяем иконки внутри колонки + const positionInColumn = columnCounts[column]; + const left = (column / columns) * 100 + (Math.random() * 100 / columns) - 5; + const duration = 15 + Math.random() * 10; + const delay = (positionInColumn / maxIconsPerColumn) * duration * 0.8; icons.push( falling icon ); diff --git a/docs/docusaurus/src/pages/index.module.css b/docs/docusaurus/src/pages/index.module.css index 68b40ecbb5..576279f92e 100644 --- a/docs/docusaurus/src/pages/index.module.css +++ b/docs/docusaurus/src/pages/index.module.css @@ -37,11 +37,9 @@ .fallingIconsContainer { position: absolute; top: 0; - left: 0; - width: 100%; + left: 5; + width: 95%; height: 100%; - overflow: hidden; - pointer-events: none; z-index: -1; }