HTML для графики и анимации
Графика и анимация в HTML
Использование Canvas, SVG и CSS анимаций для создания визуальных эффектов.
1. Интерактивный Canvas
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML Графика и Анимация</title>
<style>
body {
margin: 0;
padding: 20px;
background: linear-gradient(45deg, #1a2a6c, #b21f1f, #fdbb2d);
background-size: 400% 400%;
animation: gradientBG 15s ease infinite;
font-family: Arial, sans-serif;
color: white;
min-height: 100vh;
}
@keyframes gradientBG {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.section {
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 30px;
margin-bottom: 30px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
h1, h2 {
text-align: center;
margin-bottom: 30px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
.canvas-container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 30px;
}
canvas {
background: rgba(0, 0, 0, 0.3);
border-radius: 10px;
border: 2px solid rgba(255, 255, 255, 0.3);
cursor: crosshair;
}
.controls {
display: flex;
gap: 10px;
margin-bottom: 15px;
flex-wrap: wrap;
}
button {
background: rgba(255, 255, 255, 0.2);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
button:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
.svg-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-top: 30px;
}
.svg-item {
background: rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 10px;
text-align: center;
}
.animation-demo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 30px;
}
.animated-box {
width: 100%;
height: 150px;
background: linear-gradient(45deg, #ff6b6b, #ffa726);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 18px;
}
/* Анимации */
.bounce { animation: bounce 2s infinite; }
.pulse { animation: pulse 2s infinite; }
.rotate { animation: rotate 3s linear infinite; }
.slide { animation: slide 4s ease-in-out infinite; }
@keyframes bounce {
0%, 20%, 50%, 80%, 100% { transform: translateY(0); }
40% { transform: translateY(-30px); }
60% { transform: translateY(-15px); }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes slide {
0%, 100% { transform: translateX(0); }
50% { transform: translateX(50px); }
}
</style>
</head>
<body>
<div class="container">
<h1>? HTML Графика и Анимация</h1>
<!-- Canvas Section -->
<section class="section">
<h2>?️ Интерактивный Canvas</h2>
<div class="canvas-container">
<div>
<h3>Рисовалка</h3>
<div class="controls">
<button onclick="clearCanvas()">Очистить</button>
<button onclick="changeColor("#ff6b6b")" style="background: #ff6b6b;">Красный</button>
<button onclick="changeColor("#4ecdc4")" style="background: #4ecdc4;">Бирюзовый</button>
<button onclick="changeColor("#45b7d1")" style="background: #45b7d1;">Синий</button>
<button onclick="changeBrushSize(2)">Тонкая</button>
<button onclick="changeBrushSize(10)">Толстая</button>
</div>
<canvas id="drawingCanvas" width="500" height="400"></canvas>
</div>
<div>
<h3>Анимация частиц</h3>
<div class="controls">
<button onclick="toggleParticles()" id="toggleParticles">Старт</button>
<button onclick="changeParticleCount(50)">Мало</button>
<button onclick="changeParticleCount(200)">Средне</button>
<button onclick="changeParticleCount(500)">Много</button>
</div>
<canvas id="particleCanvas" width="500" height="400"></canvas>
</div>
</div>
</section>
<!-- SVG Section -->
<section class="section">
<h2>? SVG Графика</h2>
<div class="svg-section">
<div class="svg-item">
<svg width="150" height="150" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="#ff6b6b" />
<circle cx="50" cy="50" r="30" fill="#4ecdc4" />
<circle cx="50" cy="50" r="20" fill="#45b7d1" />
<circle cx="50" cy="50" r="10" fill="#96ceb4" />
</svg>
<p>Концентрические круги</p>
</div>
<div class="svg-item">
<svg width="150" height="150" viewBox="0 0 100 100">
<polygon points="50,10 90,90 10,90" fill="#ffa726" />
<polygon points="50,30 70,70 30,70" fill="#ffca28" />
<polygon points="50,50 60,60 40,60" fill="#ffee58" />
</svg>
<p>Вложенные треугольники</p>
</div>
<div class="svg-item">
<svg width="150" height="150" viewBox="0 0 100 100">
<rect x="10" y="10" width="80" height="80" rx="15" fill="#ab47bc" />
<rect x="20" y="20" width="60" height="60" rx="10" fill="#ce93d8" />
<rect x="30" y="30" width="40" height="40" rx="5" fill="#e1bee7" />
</svg>
<p>Скругленные прямоугольники</p>
</div>
<div class="svg-item">
<svg width="150" height="150" viewBox="0 0 100 100">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#ff4081;stop-opacity:1" />
<stop offset="100%" style="stop-color:#7b1fa2;stop-opacity:1" />
</linearGradient>
</defs>
<ellipse cx="50" cy="50" rx="45" ry="30" fill="url(#grad1)" />
<text x="50" y="55" text-anchor="middle" fill="white" font-size="12">Эллипс</text>
</svg>
<p>Градиентный эллипс</p>
</div>
</div>
</section>
<!-- CSS Animations Section -->
<section class="section">
<h2>✨ CSS Анимации</h2>
<div class="animation-demo">
<div>
<div class="animated-box bounce">BOUNCE</div>
<p style="text-align: center; margin-top: 10px;">Прыгающая анимация</p>
</div>
<div>
<div class="animated-box pulse">PULSE</div>
<p style="text-align: center; margin-top: 10px;">Пульсирующая анимация</p>
</div>
<div>
<div class="animated-box rotate">ROTATE</div>
<p style="text-align: center; margin-top: 10px;">Вращающаяся анимация</p>
</div>
<div>
<div class="animated-box slide">SLIDE</div>
<p style="text-align: center; margin-top: 10px;">Скользящая анимация</p>
</div>
</div>
</section>
</div>
<script>
// Canvas Drawing
const drawingCanvas = document.getElementById("drawingCanvas");
const ctx = drawingCanvas.getContext("2d");
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let hue = 0;
let brushSize = 5;
let direction = true;
drawingCanvas.addEventListener("mousedown", startDrawing);
drawingCanvas.addEventListener("mousemove", draw);
drawingCanvas.addEventListener("mouseup", stopDrawing);
drawingCanvas.addEventListener("mouseout", stopDrawing);
function startDrawing(e) {
isDrawing = true;
[lastX, lastY] = [e.offsetX, e.offsetY];
}
function draw(e) {
if (!isDrawing) return;
ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`;
ctx.lineJoin = "round";
ctx.lineCap = "round";
ctx.lineWidth = brushSize;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
[lastX, lastY] = [e.offsetX, e.offsetY];
hue++;
if (hue >= 360) hue = 0;
if (brushSize >= 50 || brushSize <= 1) direction = !direction;
if (direction) brushSize++;
else brushSize--;
}
function stopDrawing() {
isDrawing = false;
}
function clearCanvas() {
ctx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height);
}
function changeColor(color) {
ctx.strokeStyle = color;
}
function changeBrushSize(size) {
brushSize = size;
}
// Particle System
const particleCanvas = document.getElementById("particleCanvas");
const pctx = particleCanvas.getContext("2d");
let particles = [];
let animationId = null;
let particleCount = 100;
class Particle {
constructor() {
this.x = Math.random() * particleCanvas.width;
this.y = Math.random() * particleCanvas.height;
this.size = Math.random() * 5 + 1;
this.speedX = Math.random() * 3 - 1.5;
this.speedY = Math.random() * 3 - 1.5;
this.color = `hsl(${Math.random() * 360}, 50%, 50%)`;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
if (this.x > particleCanvas.width) this.x = 0;
else if (this.x < 0) this.x = particleCanvas.width;
if (this.y > particleCanvas.height) this.y = 0;
else if (this.y < 0) this.y = particleCanvas.height;
}
draw() {
pctx.fillStyle = this.color;
pctx.beginPath();
pctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
pctx.fill();
}
}
function initParticles() {
particles = [];
for (let i = 0; i < particleCount; i++) {
particles.push(new Particle());
}
}
function animateParticles() {
pctx.clearRect(0, 0, particleCanvas.width, particleCanvas.height);
for (let particle of particles) {
particle.update();
particle.draw();
}
// Соединение частиц линиями
pctx.strokeStyle = "rgba(255, 255, 255, 0.1)";
pctx.lineWidth = 1;
for (let i = 0; i < particles.length; i++) {
for (let j = i; 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 < 100) {
pctx.beginPath();
pctx.moveTo(particles[i].x, particles[i].y);
pctx.lineTo(particles[j].x, particles[j].y);
pctx.stroke();
}
}
}
animationId = requestAnimationFrame(animateParticles);
}
function toggleParticles() {
const button = document.getElementById("toggleParticles");
if (animationId) {
cancelAnimationFrame(animationId);
animationId = null;
button.textContent = "Старт";
} else {
animateParticles();
button.textContent = "Стоп";
}
}
function changeParticleCount(count) {
particleCount = count;
initParticles();
if (animationId) {
cancelAnimationFrame(animationId);
animateParticles();
}
}
// Инициализация
initParticles();
</script>
</body>
</html>