hero matrix engine update

This commit is contained in:
2026-04-26 11:42:21 +07:00
parent 9df999af94
commit 166d0e7f08
3 changed files with 489 additions and 276 deletions
+61 -63
View File
@@ -3,7 +3,7 @@
import React, { useRef, useEffect, useState } from "react";
import { useTheme } from "next-themes";
const ENGINE_VERSION = "2.0.1";
const ENGINE_VERSION = "2.0.2";
interface NetrunnerMatrixProps {
isSecure?: boolean;
@@ -151,80 +151,78 @@ export const NetrunnerMatrix: React.FC<NetrunnerMatrixProps> = ({
});
}
}, [isSecure, isDarkMode, mounted]);
useEffect(() => {
if (!mounted) return;
if (!mounted || !workerRef.current) return;
const handleEvents = (e: any) => {
if (!workerRef.current || !canvasRef.current) return;
// --- 1. Гироскоп (Наклон телефона) ---
const handleOrientation = (e: DeviceOrientationEvent) => {
let gamma = e.gamma || 0; // Наклон влево/вправо (-90 до 90)
const isInteractive = e.target.closest(
'button, a, input, [role="button"], [role="switch"], .data-\\[state\\]',
);
// Ограничиваем угол для комфорта
if (gamma > 45) gamma = 45;
if (gamma < -45) gamma = -45;
const isDown = e.type === "pointerdown" || e.type === "touchstart";
const isUp =
e.type === "pointerup" ||
e.type === "touchend" ||
e.type === "pointercancel";
// Нормализуем от -1.0 до 1.0
const tiltX = gamma / 45.0;
if (isInteractive && isDown) return;
const type = isDown ? "DRAW_START" : isUp ? "DRAW_END" : "MOUSE_MOVE";
let clientX: number | null = null;
let clientY: number | null = null;
if (e.touches && e.touches.length > 0) {
clientX = e.touches[0].clientX;
clientY = e.touches[0].clientY;
} else if (e.clientX !== undefined) {
clientX = e.clientX;
clientY = e.clientY;
}
if (clientX === null || clientY === null) {
if (isUp) workerRef.current.postMessage({ type });
return;
}
const rect = canvasRef.current.getBoundingClientRect();
const scaleX = dimensionsRef.current.width / rect.width;
const scaleY = dimensionsRef.current.height / rect.height;
workerRef.current.postMessage({
type,
payload: {
x: (clientX - rect.left) * scaleX,
y: (clientY - rect.top) * scaleY,
},
workerRef.current?.postMessage({
type: "TILT",
payload: { x: tiltX, y: 0 },
});
};
const options = { passive: true };
if (window.PointerEvent) {
window.addEventListener("pointerdown", handleEvents, options as any);
window.addEventListener("pointermove", handleEvents, options as any);
window.addEventListener("pointerup", handleEvents, options as any);
window.addEventListener("pointercancel", handleEvents, options as any);
// Запрос прав для iOS 13+ (если нужно, можно вынести в кнопку включения VPN)
if (
typeof (DeviceOrientationEvent as any).requestPermission === "function"
) {
// Это должно вызываться по клику пользователя, здесь оставлено для примера
// (DeviceOrientationEvent as any).requestPermission().then(...)
} else {
window.addEventListener("touchstart", handleEvents, options);
window.addEventListener("touchmove", handleEvents, options);
window.addEventListener("touchend", handleEvents, options);
window.addEventListener("deviceorientation", handleOrientation);
}
return () => {
if (window.PointerEvent) {
window.removeEventListener("pointerdown", handleEvents);
window.removeEventListener("pointermove", handleEvents);
window.removeEventListener("pointerup", handleEvents);
window.removeEventListener("pointercancel", handleEvents);
} else {
window.removeEventListener("touchstart", handleEvents);
window.removeEventListener("touchmove", handleEvents);
window.removeEventListener("touchend", handleEvents);
// --- 2. Ударные волны и Кинетический свайп ---
const handleEvents = (e: any) => {
const isDown = e.type === "pointerdown" || e.type === "touchstart";
const isMove = e.type === "pointermove" || e.type === "touchmove";
let clientX = e.touches ? e.touches[0].clientX : e.clientX;
let clientY = e.touches ? e.touches[0].clientY : e.clientY;
if (clientX === undefined) return;
const rect = canvasRef.current!.getBoundingClientRect();
const scaleX = dimensionsRef.current.width / rect.width;
const scaleY = dimensionsRef.current.height / rect.height;
const px = (clientX - rect.left) * scaleX;
const py = (clientY - rect.top) * scaleY;
// Ударная волна при клике/тапе
if (isDown) {
workerRef.current?.postMessage({
type: "SHOCKWAVE",
payload: { x: px, y: py },
});
}
// Магнитный свайп
if (isMove) {
workerRef.current?.postMessage({
type: "KINETIC_SWIPE",
payload: { x: px, y: py },
});
}
};
window.addEventListener("pointerdown", handleEvents, { passive: true });
window.addEventListener("pointermove", handleEvents, { passive: true });
window.addEventListener("touchstart", handleEvents, { passive: true });
window.addEventListener("touchmove", handleEvents, { passive: true });
return () => {
window.removeEventListener("deviceorientation", handleOrientation);
window.removeEventListener("pointerdown", handleEvents);
// ... удаляем остальные листенеры ...
};
}, [mounted]);