@@ -51,150 +51,90 @@ const config = {
5151} ;
5252
5353class InteractiveGrid {
54- constructor ( svgElement ) {
55- this . svg = svgElement ;
56- this . lines = [ ] ;
57- this . mousePos = { x : 0 , y : 0 } ;
58- this . isThrottled = false ;
54+ constructor ( gridElement ) {
55+ this . grid = gridElement ;
56+ this . cells = [ ] ;
57+ this . rows = 7 ;
58+ this . cols = 12 ;
5959 this . setupGrid ( ) ;
6060 this . setupEventListeners ( ) ;
6161 }
6262
6363 setupGrid ( ) {
64- const rect = this . svg . getBoundingClientRect ( ) ;
65- const aspectRatio = rect . width / rect . height ;
66- this . svg . setAttribute ( 'viewBox' , `0 0 ${ 1000 * aspectRatio } 1000` ) ;
67-
68- const segments = 60 ; // 减少分段数量以提高性能
69-
70- // 水平线
71- for ( let i = 0 ; i <= config . gridHeight ; i ++ ) {
72- const y = ( i * 1000 ) / config . gridHeight ;
73- for ( let j = 0 ; j < segments ; j ++ ) {
74- const x1 = ( j * 1000 * aspectRatio ) / segments ;
75- const x2 = ( ( j + 1 ) * 1000 * aspectRatio ) / segments ;
76- const line = document . createElementNS ( "http://www.w3.org/2000/svg" , "line" ) ;
77- line . setAttribute ( "x1" , x1 . toString ( ) ) ;
78- line . setAttribute ( "y1" , y . toString ( ) ) ;
79- line . setAttribute ( "x2" , x2 . toString ( ) ) ;
80- line . setAttribute ( "y2" , y . toString ( ) ) ;
81- line . setAttribute ( "data-original-y" , y . toString ( ) ) ;
82- line . setAttribute ( "data-center-x" , ( ( x1 + x2 ) / 2 ) . toString ( ) ) ;
83-
84- // 添加边缘渐变效果并存储基础透明度
85- const edgeFactorY = Math . min ( i / 2 , ( config . gridHeight - i ) / 2 ) ;
86- const opacity = Math . min ( edgeFactorY , 1 ) * 0.15 ;
87- line . setAttribute ( "data-base-opacity" , opacity . toString ( ) ) ;
88- line . style . stroke = `rgba(255, 255, 255, ${ opacity } )` ;
89-
90- this . svg . appendChild ( line ) ;
91- this . lines . push ( line ) ;
92- }
93- }
94-
95- // 垂直线
96- for ( let i = 0 ; i <= config . gridWidth ; i ++ ) {
97- const x = ( i * 1000 * aspectRatio ) / config . gridWidth ;
98- for ( let j = 0 ; j < segments ; j ++ ) {
99- const y1 = ( j * 1000 ) / segments ;
100- const y2 = ( ( j + 1 ) * 1000 ) / segments ;
101- const line = document . createElementNS ( "http://www.w3.org/2000/svg" , "line" ) ;
102- line . setAttribute ( "x1" , x . toString ( ) ) ;
103- line . setAttribute ( "y1" , y1 . toString ( ) ) ;
104- line . setAttribute ( "x2" , x . toString ( ) ) ;
105- line . setAttribute ( "y2" , y2 . toString ( ) ) ;
106- line . setAttribute ( "data-original-x" , x . toString ( ) ) ;
107- line . setAttribute ( "data-center-y" , ( ( y1 + y2 ) / 2 ) . toString ( ) ) ;
108-
109- // 添加边缘渐变效果并存储基础透明度
110- const edgeFactorX = Math . min ( i / 2 , ( config . gridWidth - i ) / 2 ) ;
111- const opacity = Math . min ( edgeFactorX , 1 ) * 0.15 ;
112- line . setAttribute ( "data-base-opacity" , opacity . toString ( ) ) ;
113- line . style . stroke = `rgba(255, 255, 255, ${ opacity } )` ;
114-
115- this . svg . appendChild ( line ) ;
116- this . lines . push ( line ) ;
64+ // 创建格子
65+ for ( let row = 0 ; row < this . rows ; row ++ ) {
66+ for ( let col = 0 ; col < this . cols ; col ++ ) {
67+ const div = document . createElement ( "div" ) ;
68+ div . classList . add ( "grid-cell" ) ;
69+ div . dataset . row = row ;
70+ div . dataset . col = col ;
71+ this . grid . appendChild ( div ) ;
72+ this . cells . push ( div ) ;
11773 }
11874 }
11975 }
12076
12177 setupEventListeners ( ) {
122- this . svg . addEventListener ( 'mousemove' , ( e ) => {
123- if ( this . isThrottled ) return ;
124- this . isThrottled = true ;
125-
126- setTimeout ( ( ) => {
127- this . isThrottled = false ;
128- } , config . throttleDelay ) ;
129-
130- const rect = this . svg . getBoundingClientRect ( ) ;
131- const aspectRatio = rect . width / rect . height ;
132- const scaleX = ( 1000 * aspectRatio ) / rect . width ;
133- const scaleY = 1000 / rect . height ;
134-
135- this . mousePos = {
136- x : ( e . clientX - rect . left ) * scaleX ,
137- y : ( e . clientY - rect . top ) * scaleY
138- } ;
139-
140- this . updateGrid ( ) ;
78+ this . cells . forEach ( ( cell ) => {
79+ cell . addEventListener ( "mouseenter" , ( ) => {
80+ const row = parseInt ( cell . dataset . row ) ;
81+ const col = parseInt ( cell . dataset . col ) ;
82+ this . highlight ( row , col ) ;
83+ } ) ;
14184 } ) ;
14285
143- this . svg . addEventListener ( ' mouseleave' , ( ) => {
86+ this . grid . addEventListener ( " mouseleave" , ( ) => {
14487 this . resetGrid ( ) ;
14588 } ) ;
14689 }
14790
148- updateGrid ( ) {
149- const smoothstep = ( min , max , value ) => {
150- const x = Math . max ( 0 , Math . min ( 1 , ( value - min ) / ( max - min ) ) ) ;
151- return x * x * ( 3 - 2 * x ) ;
152- } ;
153-
154- this . lines . forEach ( line => {
155- let distance ;
156- const baseOpacity = parseFloat ( line . getAttribute ( 'data-base-opacity' ) || "0.15" ) ;
157-
158- if ( line . hasAttribute ( 'data-original-y' ) ) {
159- const centerX = parseFloat ( line . getAttribute ( 'data-center-x' ) ) ;
160- const centerY = parseFloat ( line . getAttribute ( 'data-original-y' ) ) ;
161- distance = Math . sqrt ( Math . pow ( centerX - this . mousePos . x , 2 ) + Math . pow ( centerY - this . mousePos . y , 2 ) ) ;
162- } else {
163- const centerX = parseFloat ( line . getAttribute ( 'data-original-x' ) ) ;
164- const centerY = parseFloat ( line . getAttribute ( 'data-center-y' ) ) ;
165- distance = Math . sqrt ( Math . pow ( centerX - this . mousePos . x , 2 ) + Math . pow ( centerY - this . mousePos . y , 2 ) ) ;
166- }
167-
168- if ( distance < config . mouseInfluenceRadius ) {
169- const intensity = smoothstep ( 0 , config . mouseInfluenceRadius , config . mouseInfluenceRadius - distance ) ;
170- const glowStrength = intensity * 10 ;
171- line . style . filter = `drop-shadow(0 0 ${ glowStrength } px rgba(255, 255, 255, 0.9))` ;
172- line . style . stroke = `rgba(255, 255, 255, ${ intensity } )` ; // Glow overrides base opacity
173- line . setAttribute ( 'data-intensity' , intensity . toString ( ) ) ;
91+ // 高亮边框函数
92+ highlight ( row , col ) {
93+ const radius = 1.5 ;
94+ this . cells . forEach ( ( cell ) => {
95+ const r = parseInt ( cell . dataset . row ) ;
96+ const c = parseInt ( cell . dataset . col ) ;
97+ const dist = Math . hypot ( r - row , c - col ) ;
98+
99+ if ( dist <= radius ) {
100+ const intensity = 1 - dist / radius ;
101+ const glow = Math . floor ( 200 + 55 * intensity ) ;
102+ const color = `rgb(${ glow } , ${ glow } , ${ glow } )` ;
103+
104+ if ( window . gsap ) {
105+ gsap . to ( cell , {
106+ borderColor : color ,
107+ boxShadow : `0 0 ${ 10 * intensity } px ${ color } ` ,
108+ duration : 0.2
109+ } ) ;
110+ }
174111 } else {
175- const currentIntensity = parseFloat ( line . getAttribute ( 'data-intensity' ) || "0" ) ;
176- const newIntensity = Math . max ( 0 , currentIntensity - 0.05 ) ; // Slower fade out
177- line . setAttribute ( 'data-intensity' , newIntensity . toString ( ) ) ;
178-
179- if ( newIntensity > 0 ) {
180- const glowStrength = newIntensity * 10 ;
181- line . style . filter = `drop-shadow(0 0 ${ glowStrength } px rgba(255, 255, 255, 0.9))` ;
182- line . style . stroke = `rgba(255, 255, 255, ${ Math . max ( baseOpacity , newIntensity ) } )` ;
112+ if ( window . gsap ) {
113+ gsap . to ( cell , {
114+ borderColor : "rgba(255, 255, 255, 0.1)" ,
115+ boxShadow : "none" ,
116+ duration : 0.5
117+ } ) ;
183118 } else {
184- line . style . filter = 'none' ;
185- line . style . stroke = `rgba(255, 255, 255, ${ baseOpacity } )` ;
186- line . removeAttribute ( 'data-intensity' ) ; // Clean up attribute
119+ cell . style . borderColor = "rgba(255, 255, 255, 0.1)" ;
120+ cell . style . boxShadow = "none" ;
187121 }
188122 }
189123 } ) ;
190124 }
191125
192126 resetGrid ( ) {
193- this . lines . forEach ( line => {
194- const baseOpacity = parseFloat ( line . getAttribute ( 'data-base-opacity' ) || "0.15" ) ;
195- line . style . filter = 'none' ;
196- line . style . stroke = `rgba(255, 255, 255, ${ baseOpacity } )` ;
197- line . removeAttribute ( 'data-intensity' ) ;
127+ this . cells . forEach ( ( cell ) => {
128+ if ( window . gsap ) {
129+ gsap . to ( cell , {
130+ borderColor : "rgba(255, 255, 255, 0.1)" ,
131+ boxShadow : "none" ,
132+ duration : 0.5
133+ } ) ;
134+ } else {
135+ cell . style . borderColor = "rgba(255, 255, 255, 0.1)" ;
136+ cell . style . boxShadow = "none" ;
137+ }
198138 } ) ;
199139 }
200140}
@@ -505,9 +445,9 @@ document.addEventListener('DOMContentLoaded', () => {
505445 } ) ;
506446 }
507447
508- const svgElement = document . querySelector ( '. grid-overlay ') ;
509- if ( svgElement ) {
510- new InteractiveGrid ( svgElement ) ;
448+ const gridElement = document . getElementById ( ' grid') ;
449+ if ( gridElement ) {
450+ new InteractiveGrid ( gridElement ) ;
511451 }
512452
513453 // 第四页面的行星星星效果
0 commit comments