3434 radial-gradient (40% 35% at 18% 22% , rgba (55 , 213 , 211 , 0.18 ), transparent 70% ),
3535 radial-gradient (46% 42% at 80% 72% , rgba (138 , 123 , 255 , 0.16 ), transparent 70% ),
3636 radial-gradient (30% 30% at 60% 10% , rgba (255 , 180 , 87 , 0.08 ), transparent 70% );
37- filter : blur (60 px );
37+ filter : blur (40 px );
3838 animation : drift 26s ease-in-out infinite alternate;
3939 pointer-events : none;
40+ will-change : transform;
4041 }
4142 @keyframes drift {
4243 from { transform : translate3d (-2% , -1% , 0 ) scale (1 ); }
4344 to { transform : translate3d (3% , 2% , 0 ) scale (1.08 ); }
4445 }
45- /* 指针跟随微光 */
46+ /* 指针跟随微光(transform 合成驱动,left/top 重排已移除) */
4647 .cursor-glow {
47- position : fixed; width : 420px ; height : 420px ; border-radius : 50% ;
48+ position : fixed; left : 0 ; top : 0 ; width : 420px ; height : 420px ; border-radius : 50% ;
4849 background : radial-gradient (circle, rgba (138 , 123 , 255 , .10 ), transparent 60% );
4950 transform : translate (-50% , -50% ); pointer-events : none; z-index : 1 ;
5051 transition : opacity .3s ; mix-blend-mode : screen;
52+ will-change : transform;
5153 }
5254 .wrap { position : relative; z-index : 2 ; max-width : 1080px ; margin : 0 auto; padding : 30px 22px 70px ; }
5355
@@ -805,6 +807,7 @@ <h3>⚡ <span data-i18n="u_step5_t">技术说明</span></h3>
805807const vsrc = document . getElementById ( 'vsrc' ) ;
806808const vctx = vsrc . getContext ( '2d' ) ;
807809let vsrcT = 0 ;
810+ let vsrcVisible = true , vsrcRaf = 0 ; // 视口外自动停机:别让隐藏的动画烧 GPU
808811function animateVSrc ( ) {
809812 vsrcT += 0.016 ;
810813 const w = vsrc . width , h = vsrc . height ;
@@ -827,9 +830,18 @@ <h3>⚡ <span data-i18n="u_step5_t">技术说明</span></h3>
827830 }
828831 vctx . fillStyle = 'rgba(255,255,255,.95)' ; vctx . font = 'bold 44px sans-serif' ; vctx . textAlign = 'center' ;
829832 vctx . fillText ( 'MoX ⚡ GPU' , w / 2 , h / 2 + 150 ) ;
830- requestAnimationFrame ( animateVSrc ) ;
833+ vsrcRaf = ( vsrcVisible && ! document . hidden ) ? requestAnimationFrame ( animateVSrc ) : 0 ;
831834}
832- requestAnimationFrame ( animateVSrc ) ;
835+ function startVSrc ( ) { if ( ! vsrcRaf && vsrcVisible && ! document . hidden ) vsrcRaf = requestAnimationFrame ( animateVSrc ) ; }
836+ startVSrc ( ) ;
837+ new IntersectionObserver ( function ( en ) { vsrcVisible = en [ 0 ] . isIntersecting ;
838+ if ( vsrcVisible ) startVSrc ( ) ;
839+ else if ( vsrcRaf ) { cancelAnimationFrame ( vsrcRaf ) ; vsrcRaf = 0 ; }
840+ } ) . observe ( vsrc ) ;
841+ document . addEventListener ( 'visibilitychange' , function ( ) {
842+ if ( document . hidden ) { if ( vsrcRaf ) { cancelAnimationFrame ( vsrcRaf ) ; vsrcRaf = 0 ; } }
843+ else startVSrc ( ) ;
844+ } ) ;
833845( async ( ) => {
834846 const vid = document . getElementById ( 'vid' ) ;
835847 try {
@@ -859,9 +871,20 @@ <h3>⚡ <span data-i18n="u_step5_t">技术说明</span></h3>
859871 lastFrameMs = performance . now ( ) - t0 ;
860872 busy = false ;
861873 tickFps ( performance . now ( ) ) ;
862- if ( running ) rafId = requestAnimationFrame ( loop ) ;
874+ if ( running && cvVisible && ! document . hidden ) rafId = requestAnimationFrame ( loop ) ;
863875}
864876
877+ /* 视口可见性停机:demo 画布滚出屏幕就暂停 GPU 计算,滚回来自动续 */
878+ let cvVisible = true ;
879+ new IntersectionObserver ( en => {
880+ cvVisible = en [ 0 ] . isIntersecting ;
881+ if ( ! cvVisible ) { if ( rafId ) { cancelAnimationFrame ( rafId ) ; rafId = 0 ; } }
882+ else if ( running && ! rafId && ! busy && ! document . hidden ) rafId = requestAnimationFrame ( loop ) ;
883+ } , { threshold : 0.05 } ) . observe ( document . getElementById ( 'cv' ) ) ;
884+ document . addEventListener ( 'visibilitychange' , ( ) => {
885+ if ( ! document . hidden && running && cvVisible && ! rafId && ! busy ) rafId = requestAnimationFrame ( loop ) ;
886+ } ) ;
887+
865888/* =========================================================================
866889 启动
867890 ========================================================================= */
@@ -900,7 +923,15 @@ <h3>⚡ <span data-i18n="u_step5_t">技术说明</span></h3>
900923
901924/* 指针微光 */
902925const glow = document . getElementById ( 'glow' ) ;
903- addEventListener ( 'pointermove' , e => { glow . style . left = e . clientX + 'px' ; glow . style . top = e . clientY + 'px' ; } ) ;
926+ // transform 合成 + rAF 节流:指针移动零重排零重绘
927+ let glowRaf = 0 , gx = 0 , gy = 0 ;
928+ addEventListener ( 'pointermove' , e => {
929+ gx = e . clientX ; gy = e . clientY ;
930+ if ( ! glowRaf ) glowRaf = requestAnimationFrame ( ( ) => {
931+ glowRaf = 0 ;
932+ glow . style . transform = `translate(${ gx } px, ${ gy } px) translate(-50%, -50%) translateZ(0)` ;
933+ } ) ;
934+ } , { passive : true } ) ;
904935</ script >
905936</ body >
906937</ html >
0 commit comments