Skip to content

Commit

Permalink
feat: Add particle effects to the world page
Browse files Browse the repository at this point in the history
  • Loading branch information
ChisatoNishikigi73 committed Sep 29, 2024
1 parent c9dad2c commit 3cb7797
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 47 deletions.
Binary file added public/images/rhodes_island.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion src/_types/ArknightsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,13 @@ export type ArknightsConfig = {
data: SwiperData[]
}
},
WORLD: {
items: {
title: string
subTitle: string
imageUrl: string
description: string
}[]
}
}
}
}
2 changes: 1 addition & 1 deletion src/components/ParticleFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ const ParticleFactory: React.FC<ParticleSystemProps> = ({
scale: initialScale,
brightnessThreshold: initialBrightnessThreshold,
alphaThreshold: initialAlphaThreshold,
debug = true,
debug = false,
}) => {
const [activeLogo, setActiveLogo] = useState<LogoImg | null>(null);
const [logoImgs, setLogoImgs] = useState<LogoImg[]>([]);
Expand Down
118 changes: 73 additions & 45 deletions src/pages/_views/03-World.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { directions } from "../../components/store/lineDecoratorStore.ts";
import { IconArrow } from "../../components/SvgIcons.tsx";
import PortraitBottomGradientMask from "../../components/PortraitBottomGradientMask";
import config from "../../../arknights.config.tsx";
import ParticleFactory from '../../components/ParticleFactory.tsx';

const items = config.rootPage.WORLD.items;

Expand Down Expand Up @@ -156,7 +157,7 @@ function List({ onItemSelect }: { onItemSelect: (index: number) => void }) {
const handleMouseLeave = () => {
setActiveImage(null);
isFirstMove.current = true;
};
};

useEffect(() => {
const animatePosition = () => {
Expand Down Expand Up @@ -214,30 +215,32 @@ function List({ onItemSelect }: { onItemSelect: (index: number) => void }) {
}, []);

return (
<div
ref={listRef}
className={`w-[39.875rem] absolute top-[20.3703703704%] left-[9rem] transition-all duration-500 ${isExiting ? '-translate-x-full opacity-0' : ''} z-10`}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
>
{memoizedItems}
{activeImage && (
<img
src={activeImage}
alt="Active item"
className="absolute pointer-events-none transition-opacity duration-300 ease-out"
style={{
width: '1024px',
height: '1024px',
objectFit: 'cover',
left: `${imagePosition.x}px`,
top: `${imagePosition.y}px`,
opacity: 1,
zIndex: -1,
filter: 'blur(0.2px)',
}}
/>
)}
<div className="flex">
<div
ref={listRef}
className={`w-[39.875rem] absolute top-[20.3703703704%] left-[9rem] transition-all duration-500 ${isExiting ? '-translate-x-full opacity-0' : ''} z-10`}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
>
{memoizedItems}
{activeImage && (
<img
src={activeImage}
alt="Active item"
className="absolute pointer-events-none transition-opacity duration-300 ease-out"
style={{
width: '1024px',
height: '1024px',
objectFit: 'cover',
left: `${imagePosition.x}px`,
top: `${imagePosition.y}px`,
opacity: 1,
zIndex: -1,
filter: 'blur(0.2px)',
}}
/>
)}
</div>
</div>
);
}
Expand Down Expand Up @@ -405,6 +408,23 @@ export default function World() {
const world = useRef<HTMLDivElement>(null)
const [selectedItemIndex, setSelectedItemIndex] = useState<number | null>(null);
const [active, setActive] = useState(false);
const [windowSize, setWindowSize] = useState({ width: 0, height: 0 });
const [isWorldReady, setIsWorldReady] = useState(false);

useEffect(() => {
const handleResize = () => {
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
};

// 初始设置
handleResize();

// 添加事件监听器
window.addEventListener('resize', handleResize);

// 清理函数
return () => window.removeEventListener('resize', handleResize);
}, []);

useEffect(() => {
const isActive = $viewIndex === 3 && $readyToTouch;
Expand All @@ -414,6 +434,19 @@ export default function World() {
setActive(isActive);
}, [$viewIndex, $readyToTouch])

useEffect(() => {
if (active && windowSize.width > 0 && windowSize.height > 0) {
// 给一个小延迟,确保其他元素都已经渲染完成
const timer = setTimeout(() => {
setIsWorldReady(true);
}, 100);

return () => clearTimeout(timer);
} else {
setIsWorldReady(false); // 确保在非活动状态下停止粒子系统
}
}, [active, windowSize]);

const handleItemSelect = useCallback((index: number) => {
setSelectedItemIndex(index);
}, []);
Expand Down Expand Up @@ -453,27 +486,22 @@ export default function World() {
onNext={handleNext}
/>
)}
<div
className="h-[.95em] text-[#242424] text-[7rem] font-oswaldMedium whitespace-nowrap tracking-tighter absolute bottom-[11.25rem] left-[9rem] portrait:left-[4.25rem] portrait:bottom-[18.2908545727%] flex items-end translate-y-full overflow-hidden transition-opacity opacity-0 z-[2]">
WORLD
</div>
<div
className="w-full h-2 pr-[17.25rem] portrait:pr-[5.75rem] absolute left-0 bottom-[11.25rem] portrait:bottom-[18.2908545727%] flex translate-y-full transition-[opacity,visibility] duration-[600ms] z-[2]">
<div className="w-full h-full relative flex flex-auto">
{items.map((_: any, index: React.Key | null | undefined) => (
<a
key={index}
href="#"
className={`min-w-0 w-full h-full ${selectedItemIndex === index ? 'bg-ark-blue' : 'bg-[#5a5a5a] hover:bg-[#ababab]'} flex-1 transition-colors duration-300 cursor-pointer`}
onClick={(e) => {
e.preventDefault();
handleItemSelect(index as number);
}}
aria-label={`选择项目 ${index as number + 1}`}
/>
))}

{/* 粒子系统 */}
{isWorldReady && (
<div className="absolute right-0 top-1/2 transform -translate-y-1/2 z-[1]">
<ParticleFactory
activeLabel="island"
width={windowSize.width}
height={windowSize.height}
isGrayscale={false}
scale={1.7}
particleAreaX={windowSize.width / 2 + 60}
particleAreaY={windowSize.height / 2 - 150}
/>
</div>
</div>
)}

<PortraitBottomGradientMask />
</div>
)
Expand Down

0 comments on commit 3cb7797

Please sign in to comment.