jsdemo / index.html
dron008's picture
Add 2 files
38df2e5 verified
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Интерактивная графическая демонстрация</title>
<style>
body {
margin: 0;
overflow: hidden;
background: linear-gradient(135deg, #1a1a2e, #16213e);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-family: 'Arial', sans-serif;
color: rgba(255, 255, 255, 0.8);
}
canvas {
display: block;
position: fixed;
top: 0;
left: 0;
z-index: 1;
}
.info {
position: absolute;
bottom: 20px;
left: 20px;
z-index: 2;
background-color: rgba(0, 0, 0, 0.5);
padding: 15px;
border-radius: 10px;
max-width: 300px;
}
h1 {
margin: 0 0 10px 0;
font-size: 18px;
color: #fff;
}
p {
margin: 5px 0;
font-size: 14px;
line-height: 1.4;
}
.controls {
position: absolute;
top: 20px;
right: 20px;
z-index: 2;
display: flex;
flex-direction: column;
gap: 10px;
}
button {
background: rgba(0, 0, 0, 0.5);
color: white;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 5px;
padding: 8px 12px;
cursor: pointer;
transition: all 0.3s ease;
}
button:hover {
background: rgba(255, 255, 255, 0.1);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<div class="info">
<h1>Интерактивная частичная система</h1>
<p>Двигайте мышью, чтобы влиять на частицы. Нажмите для создания взрыва.</p>
<p>Частицы реагируют на гравитацию, трение и друг на друга.</p>
</div>
<div class="controls">
<button id="explode">Создать взрыв</button>
<button id="changeColor">Изменить цвет</button>
<button id="toggleLines">Переключить соединения</button>
</div>
<script>
// Основной код Canvas
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Устанавливаем размер canvas равным размеру окна
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// Настройки системы частиц
const settings = {
particleCount: 150,
particleSize: 3,
lineDistance: 100,
showLines: true,
gravity: 0.05,
friction: 0.98,
mouseInfluence: 20,
colors: [
'#ff3366', '#00ffcc', '#ffcc00', '#33ccff', '#cc33ff',
'#ff9933', '#66ff33', '#3399ff', '#ff33cc', '#33ff99'
],
currentColorIndex: 0,
maxVelocity: 5
};
// Функция для генерации случайного числа в диапазоне
function random(min, max) {
return Math.random() * (max - min) + min;
}
// Класс частицы
class Particle {
constructor(x, y) {
this.x = x || random(0, canvas.width);
this.y = y || random(0, canvas.height);
this.velocityX = random(-1, 1);
this.velocityY = random(-1, 1);
this.size = random(1, settings.particleSize);
this.baseSize = this.size;
this.color = settings.colors[
Math.floor(random(0, settings.colors.length))
];
this.hue = Math.floor(random(0, 360));
this.life = 0;
this.maxLife = random(200, 1000);
}
// Обновление позиции частицы
update(mouseX, mouseY) {
// Расчет расстояния до курсора мыши
const dx = mouseX - this.x;
const dy = mouseY - this.y;
const distance = Math.sqrt(dx * dx + dy * dy);
// Влияние мыши на частицу
if (distance < 100) {
const angle = Math.atan2(dy, dx);
const force = (100 - distance) / settings.mouseInfluence;
this.velocityX += Math.cos(angle) * force;
this.velocityY += Math.sin(angle) * force;
}
// Ограничение максимальной скорости
const speed = Math.sqrt(this.velocityX * this.velocityX + this.velocityY * this.velocityY);
if (speed > settings.maxVelocity) {
this.velocityX = (this.velocityX / speed) * settings.maxVelocity;
this.velocityY = (this.velocityY / speed) * settings.maxVelocity;
}
// Гравитация
this.velocityY += settings.gravity;
// Трение
this.velocityX *= settings.friction;
this.velocityY *= settings.friction;
// Обновление позиции
this.x += this.velocityX;
this.y += this.velocityY;
// Столкновение со стенами
if (this.x < 0 || this.x > canvas.width) {
this.velocityX *= -0.8;
this.x = this.x < 0 ? 0 : canvas.width;
}
if (this.y < 0 || this.y > canvas.height) {
this.velocityY *= -0.8;
this.y = this.y < 0 ? 0 : canvas.height;
}
// Пульсация размера
this.life++;
if (this.life > this.maxLife) this.life = 0;
const pulse = Math.sin(this.life * 0.05) * 0.5 + 1;
this.size = this.baseSize * pulse;
// Изменение цвета со временем
this.hue = (this.hue + 0.2) % 360;
}
// Отрисовка частицы
draw() {
ctx.fillStyle = `hsla(${this.hue}, 100%, 50%, 0.8)`;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
// Добавляем свечение
ctx.shadowBlur = 15;
ctx.shadowColor = `hsla(${this.hue}, 100%, 50%, 0.6)`;
}
}
// Создаем частицы
let particles = [];
for (let i = 0; i < settings.particleCount; i++) {
particles.push(new Particle());
}
// Позиция мыши
let mouseX = canvas.width / 2;
let mouseY = canvas.height / 2;
// Следим за движением мыши
canvas.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = e.clientY;
});
// Нажатие мыши создает взрыв
canvas.addEventListener('mousedown', createExplosion);
// Кнопка "Создать взрыв"
document.getElementById('explode').addEventListener('click', createExplosion);
// Кнопка "Изменить цвет"
document.getElementById('changeColor').addEventListener('click', () => {
settings.currentColorIndex = (settings.currentColorIndex + 1) % settings.colors.length;
});
// Кнопка "Переключить соединения"
document.getElementById('toggleLines').addEventListener('click', () => {
settings.showLines = !settings.showLines;
});
// Функция создания взрыва
function createExplosion() {
for (let i = 0; i < particles.length; i++) {
const angle = random(0, Math.PI * 2);
const force = random(5, 15);
particles[i].velocityX = Math.cos(angle) * force;
particles[i].velocityY = Math.sin(angle) * force;
}
}
// Анимационная петля
function animate() {
// Очищаем canvas с полупрозрачным фоном для эффекта шлейфа
ctx.fillStyle = 'rgba(10, 10, 20, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Обновляем и рисуем частицы
particles.forEach(particle => particle.update(mouseX, mouseY));
// Отрисовываем линии между близкими частицами
if (settings.showLines) {
drawConnections();
}
// Рисуем частицы
particles.forEach(particle => particle.draw());
// Сбрасываем тени
ctx.shadowBlur = 0;
requestAnimationFrame(animate);
}
// Рисуем соединения между частицами
function drawConnections() {
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x;
const dy = particles[i].y - particles[j].y;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance < settings.lineDistance) {
const opacity = 1 - (distance / settings.lineDistance);
ctx.strokeStyle = `rgba(200, 200, 255, ${opacity * 0.2})`;
ctx.lineWidth = opacity * 1.5;
ctx.beginPath();
ctx.moveTo(particles[i].x, particles[i].y);
ctx.lineTo(particles[j].x, particles[j].y);
ctx.stroke();
}
}
}
}
// Обработка изменения размера окна
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
// Запуск анимации
animate();
// Добавляем всплывающие частицы при загрузке
setTimeout(createExplosion, 500);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: absolute; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">This website has been generated by <a href="https://enzostvs-deepsite.hf.space" style="color: #fff;" target="_blank" >DeepSite</a> <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;"></p></body>
</html>