Высокопроизводительная библиотека для создания интерактивных fluid-симуляций в React-приложениях с использованием WebGL.
Основано на проекте Pavel Dobryakov’s WebGL Fluid Simulation.
Высокопроизводительная библиотека для создания интерактивных fluid симуляций в React приложениях с использованием WebGL.
npm install react-webgl-fluidimport React from 'react';
import { useFluidSimulation } from 'react-webgl-fluid';
function FluidCanvas() {
const { canvasRef } = useFluidSimulation({
BLOOM: true,
SUNRAYS: true,
COLORFUL: true,
});
return <canvas ref={canvasRef} style={{ width: '100%', height: '100vh' }} />;
}
export default FluidCanvas;Основной React хук для создания fluid симуляции.
const {
canvasRef,
simulation,
splat,
randomSplats,
updateConfig,
start,
stop,
pause,
resume,
captureScreenshot,
} = useFluidSimulation(config, enableEventListeners);config(optional): Объект конфигурации симуляцииenableEventListeners(optional, default:true): Включить автоматическую обработку событий мыши и касаний
canvasRef: React ref для canvas элементаsimulation: Экземпляр FluidSimulation для прямого управленияsplat: Функция для создания всплеска в определенной точкеrandomSplats: Функция для создания случайных всплесковupdateConfig: Функция для обновления конфигурацииstart/stop/pause/resume: Функции управления анимациейcaptureScreenshot: Функция для создания скриншота
interface SimulationConfig {
// 🎯 ОСНОВНЫЕ НАСТРОЙКИ ДЛЯ ВИХРЕЙ, РАЗМЕРА И СКОРОСТИ
CURL?: number; // Размер вихрей (0-50, больше = больше вихрей)
SPLAT_RADIUS?: number; // Размер начальной точки (0.01-1.0)
DENSITY_DISSIPATION?: number; // Скорость исчезновения дыма (0-1, меньше = дольше)
VELOCITY_DISSIPATION?: number; // Скорость распространения (0-1, меньше = быстрее)
// Разрешение и качество
SIM_RESOLUTION?: number; // Разрешение симуляции (32-256)
DYE_RESOLUTION?: number; // Разрешение красителя (128-1024)
// Физика
PRESSURE?: number; // Давление жидкости (0-1)
PRESSURE_ITERATIONS?: number; // Точность расчетов (5-50)
SPLAT_FORCE?: number; // Сила всплеска (1000-10000)
// Визуальные эффекты
SHADING?: boolean; // Затенение
COLORFUL?: boolean; // Цветные всплески
COLOR_UPDATE_SPEED?: number; // Скорость смены цветов (1-20)
BLOOM?: boolean; // Эффект свечения
SUNRAYS?: boolean; // Эффект солнечных лучей
TRANSPARENT?: boolean; // Прозрачный фон
}| Параметр | Что контролирует | Диапазон | Эффект |
|---|---|---|---|
CURL |
Размер вихрей | 0-50 | Больше = крупнее вихри |
SPLAT_RADIUS |
Размер начальной точки | 0.01-1.0 | Больше = крупнее всплеск |
DENSITY_DISSIPATION |
Скорость исчезновения дыма | 0-1 | Меньше = дольше держится |
VELOCITY_DISSIPATION |
Скорость распространения | 0-1 | Меньше = быстрее движется |
SPLAT_FORCE |
Сила всплеска | 1000-10000 | Больше = сильнее толчок |
import { useFluidSimulation } from 'react-webgl-fluid';
function BasicFluid() {
const { canvasRef } = useFluidSimulation();
return <canvas ref={canvasRef} width={800} height={600} />;
}function CustomFluid() {
const { canvasRef, updateConfig } = useFluidSimulation({
BLOOM: true,
BLOOM_INTENSITY: 0.5,
SUNRAYS: false,
COLORFUL: true,
SPLAT_RADIUS: 0.3,
});
const handleConfigChange = () => {
updateConfig({
BLOOM_INTENSITY: 1.0,
CURL: 40,
});
};
return (
<div>
<canvas ref={canvasRef} width={800} height={600} />
<button onClick={handleConfigChange}>Изменить настройки</button>
</div>
);
}function InteractiveFluid() {
const { canvasRef, splat, randomSplats } = useFluidSimulation();
const handleClick = (e: React.MouseEvent) => {
const rect = e.currentTarget.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = 1 - (e.clientY - rect.top) / rect.height;
splat(x, y, 1000, 1000, { r: 1, g: 0, b: 0 });
};
return (
<div>
<canvas ref={canvasRef} width={800} height={600} onClick={handleClick} />
<button onClick={() => randomSplats(5)}>Случайные всплески</button>
</div>
);
}function ControlledFluid() {
const { canvasRef, start, stop, pause, resume, captureScreenshot } = useFluidSimulation();
const handleScreenshot = () => {
const dataUrl = captureScreenshot();
if (dataUrl) {
const link = document.createElement('a');
link.download = 'fluid-screenshot.png';
link.href = dataUrl;
link.click();
}
};
return (
<div>
<canvas ref={canvasRef} width={800} height={600} />
<div>
<button onClick={start}>Старт</button>
<button onClick={stop}>Стоп</button>
<button onClick={pause}>Пауза</button>
<button onClick={resume}>Продолжить</button>
<button onClick={handleScreenshot}>Скриншот</button>
</div>
</div>
);
}function HoverFluid() {
const { canvasRef, updateConfig } = useFluidSimulation({
SIM_RESOLUTION: 128,
DYE_RESOLUTION: 512,
DENSITY_DISSIPATION: 0.97,
VELOCITY_DISSIPATION: 0.98,
PRESSURE_ITERATIONS: 10,
CURL: 5,
SPLAT_RADIUS: 0.2,
SHADING: true,
COLORFUL: true,
BACK_COLOR: { r: 15, g: 15, b: 15 },
BLOOM: false, // Отключить для лучшей производительности
TRIGGER_ON_HOVER: true, // Включить hover эффект
HOVER_FORCE_MULTIPLIER: 1, // Базовый множитель (настраивайте от 0.1 до 10)
});
const toggleHover = (enabled: boolean) => {
updateConfig({ TRIGGER_ON_HOVER: enabled });
};
return (
<div>
<canvas
ref={canvasRef}
width={800}
height={600}
style={{ cursor: 'none' }} // Скрыть курсор для лучшего эффекта
/>
<button onClick={() => toggleHover(false)}>Переключить в режим клика</button>
</div>
);
}// Крупные медленные вихри
function LargeVorticesFluid() {
const { canvasRef } = useFluidSimulation({
CURL: 30, // Крупные вихри
SPLAT_RADIUS: 0.5, // Большая начальная точка
DENSITY_DISSIPATION: 0.99, // Дым держится очень долго
VELOCITY_DISSIPATION: 0.95, // Медленное затухание движения
SPLAT_FORCE: 3000, // Умеренная сила
});
return <canvas ref={canvasRef} width={800} height={600} />;
}
// Мелкие быстрые вихри
function SmallFastFluid() {
const { canvasRef } = useFluidSimulation({
CURL: 5, // Мелкие вихри
SPLAT_RADIUS: 0.1, // Маленькая точка
DENSITY_DISSIPATION: 0.9, // Быстро исчезает
VELOCITY_DISSIPATION: 0.8, // Быстро затухает
SPLAT_FORCE: 8000, // Сильный толчок
});
return <canvas ref={canvasRef} width={800} height={600} />;
}function CustomForceFluid() {
const { canvasRef } = useFluidSimulation({
TRIGGER_ON_HOVER: true,
HOVER_FORCE_MULTIPLIER: 3, // Слабый hover эффект
CLICK_FORCE_MULTIPLIER: 2, // Усиленные клики
TOUCH_FORCE_MULTIPLIER: 10, // Очень сильные касания
});
return <canvas ref={canvasRef} width={800} height={600} />;
}function ManualFluid() {
const { canvasRef, splat } = useFluidSimulation({}, false);
// Ваша собственная логика обработки событий
const handleMouseMove = (e: React.MouseEvent) => {
// Кастомная логика
};
return <canvas ref={canvasRef} width={800} height={600} onMouseMove={handleMouseMove} />;
}{
SIM_RESOLUTION: 128, // Средняя детализация
DYE_RESOLUTION: 512, // Экономия памяти
BLOOM: false, // Отключить для производительности
SUNRAYS: false, // Отключить для производительности
}- Уменьшите
SIM_RESOLUTIONиDYE_RESOLUTIONна слабых устройствах - Отключите
BLOOMиSUNRAYSдля лучшей производительности - Используйте
PRESSURE_ITERATIONS: 10-15вместо 20 для ускорения
- React 16.8+
- Современные браузеры с поддержкой WebGL
- TypeScript поддержка из коробки
MIT
Основано на WebGL Fluid Simulation от Pavel Dobryakov.