他们之前正在工作,但我试图添加基于反应的页面链接,这似乎破坏了悬停效果,现在我无法让它们再次正常运行。它们在单击时执行正确的悬停动画,并且在我调整页面大小后完美工作。在我调整大小之前,它也不会显示悬停在它们上方的“可点击”鼠标指针以及页面上的另一个按钮。这里有什么问题吗?
编辑:它似乎可以在 Chrome 中的新页面上工作,但不能在打开了许多其他选项卡的选项卡中工作 - 这就是调整大小悬停事件发生时的情况。
我的应用程序页面:
import React from "react";
import Home from "./pages/Home";
import "./Styles/index.css";
const App: React.FC = () => {
return (
<div className="app">
<Home />
</div>
);
};
export default App;
我的主页:
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./Styles/index.css";
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);
我的主页:
import React from "react";
import TopBar from "../components/TopBar";
import IntroSection from "../components/IntroSection";
import "../Styles/DefaultPage.css";
const Home: React.FC = () => {
return (
<div className="home-screen">
<TopBar />
<IntroSection />
</div>
);
};
export default Home;
我的顶栏:
import React, { useEffect, useState } from "react";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
import "../Styles/TopBar.css";
gsap.registerPlugin(ScrollTrigger);
const TopBar: React.FC = () => {
const [darkMode, setDarkMode] = useState(false);
useEffect(() => {
// Add button swing animation
const navButtons = document.querySelectorAll(".nav-button");
console.log("useEffect fired - styles should be applied now");
navButtons.forEach((button) => {
const btn = button as HTMLElement;
btn.addEventListener("mouseenter", () => {
btn.style.animation = "none"; // Remove existing animation
btn.offsetHeight; // Trigger reflow
btn.style.animation = "swing 2s ease-in-out forwards"; // Reapply animation
});
btn.style.display = "none";
btn.offsetHeight; // Trigger reflow
btn.style.display = ""; // Reset display
});
return () => {
navButtons.forEach((button) => {
const btn = button as HTMLElement;
btn.removeEventListener("mouseenter", () => {});
});
};
}, []);
const toggleDarkMode = () => {
setDarkMode((prevMode) => !prevMode);
document.body.classList.toggle("dark-mode");
};
return (
<div className="top-bar">
<div className="nav-buttons">
<button className="nav-button">HOME</button>
<button className="nav-button">DEV & DESIGN</button>
<button className="nav-button">ACTING</button>
<button className="nav-button">FILMMAKING</button>
</div>
<div className="dark-mode-toggle-container">
<button className="dark-mode-toggle" onClick={toggleDarkMode}>
{darkMode ? "Light Mode" : "Dark Mode"}
</button>
</div>
</div>
);
};
export default TopBar;
顶部栏CSS:
.top-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background-color: white;
z-index: 10;
display: flex;
justify-content: space-between;
align-items: center;
}
/* Navigation buttons container */
.nav-buttons {
display: flex;
padding-left: 20px;
gap: 20px; /* Space between buttons */
height: 100%;
padding-right: 20px;
}
/* Individual navigation button styling */
.nav-button {
background: none;
border: none;
font-family: inherit;
font-size: 1rem;
cursor: pointer;
color: #333;
padding: 10px;
transform-origin: top left;
transition: transform 0.1s ease, color 0.3s ease;
align-items: center;
}
/* Color change on hover */
.nav-button:hover {
animation: wiggle 0.5s ease-in-out; /* Use the same animation keyframes */
color: #555;
}
/* Swing animation class to add animation on hover */
.swing-animation {
animation: swing 2s ease-in-out forwards;
}
/* Dark mode toggle button styling */
.dark-mode-toggle {
background: none;
border: 2px solid #333;
font-family: inherit;
font-size: 1rem;
cursor: pointer;
padding: 8px 12px;
border-radius: 4px;
transition: background-color 0.3s ease, color 0.3s ease;
}
.dark-mode-toggle-container {
display: flex;
align-items: center;
gap: 10px;
padding-right: 20px;
}
.dark-mode-toggle:hover {
background-color: #333;
color: #fff;
}
/* Dark mode styles */
body.dark-mode {
background-color: #333;
color: #fff;
}
body.dark-mode .top-bar {
background-color: #000; /* Solid black for dark mode */
}
body.dark-mode .nav-button {
color: #ccc;
}
body.dark-mode .dark-mode-toggle {
color: #fff;
}
@keyframes wiggle {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(3deg);
}
50% {
transform: rotate(-3deg);
}
75% {
transform: rotate(2deg);
}
100% {
transform: rotate(0deg);
}
}
/* Swinging animation */
@keyframes swing {
0% {
transform: rotate(0deg);
}
10% {
transform: rotate(15deg);
}
20% {
transform: rotate(-10deg);
}
30% {
transform: rotate(7deg);
}
40% {
transform: rotate(-5deg);
}
50% {
transform: rotate(3deg);
}
60% {
transform: rotate(-2deg);
}
70% {
transform: rotate(1deg);
}
80% {
transform: rotate(-0.5deg);
}
90% {
transform: rotate(0.2deg);
}
100% {
transform: rotate(0deg);
}
}
我当前的网站测试版本:https://mattekranz.com/
这个问题似乎是 React 的渲染怪癖和动画处理的结合。因此,我会尝试组合解决方案:
您在 JavaScript 中使用内联动画样式,这可能会干扰 CSS 悬停效果。相反,使用 CSS 类:
btn.addEventListener("mouseenter", () => {
btn.classList.remove("swing-animation");
void btn.offsetWidth; // Reflow to restart animation
btn.classList.add("swing-animation");
});
btn.addEventListener("mouseleave", () => btn.classList.remove("swing-animation"));
调整大小后按钮会起作用,因为浏览器会重新计算布局。我会重述 React 如何处理这些操作。强制执行此操作
useEffect
:
useEffect(() => {
const navButtons = document.querySelectorAll(".nav-button");
navButtons.forEach((btn) => btn.offsetHeight); // reflow
}, []);
如果在较少的选项卡上效果更好,则浏览器可能会限制资源。添加硬件加速:
* {
will-change: transform, opacity;
}
Obv,如果指针光标缺失,请在 CSS 中显式添加:
.nav-button {
cursor: pointer !important;
}
更一般地说,我会在没有 GSAP 的情况下运行动画来隔离问题