@@ -27,6 +27,155 @@ var isMobile = false;
2727var mobileLineIndex = 0 ;
2828var mobileLineHeight = 200 ;
2929
30+ // Fixed positions for desktop lyrics (based on lyrics length)
31+ var fixedPositions = [ ] ;
32+ var usedFixedPositions = [ ] ;
33+ var isDesktop = true ;
34+
35+ function createFixedPositions ( ) {
36+ var width = $ ( window ) . width ( ) ;
37+ var height = $ ( window ) . height ( ) ;
38+ var margin = 100 ; // Increased margin for better spacing
39+
40+ // Create a square grid based on lyrics length
41+ var gridSize = Math . ceil ( Math . sqrt ( lyrics . length ) ) ;
42+
43+ // Calculate spacing to fit the grid on screen with proper margins
44+ var availableWidth = width - ( 2 * margin ) ;
45+ var availableHeight = height - ( 2 * margin ) ;
46+ var spacingX = gridSize > 1 ? availableWidth / ( gridSize - 1 ) : availableWidth / 2 ;
47+ var spacingY = gridSize > 1 ? availableHeight / ( gridSize - 1 ) : availableHeight / 2 ;
48+
49+ fixedPositions = [ ] ;
50+
51+ // Create grid positions
52+ for ( var r = 0 ; r < gridSize ; r ++ ) {
53+ for ( var c = 0 ; c < gridSize ; c ++ ) {
54+ var x = margin + ( c * spacingX ) ;
55+ var y = margin + ( r * spacingY ) ;
56+
57+ // Ensure positions stay well within bounds
58+ x = Math . max ( margin + 50 , Math . min ( width - margin - 50 , x ) ) ;
59+ y = Math . max ( margin + 50 , Math . min ( height - margin - 50 , y ) ) ;
60+
61+ // Calculate cell dimensions for font sizing
62+ var cellWidth = Math . min ( spacingX * 0.8 , availableWidth / gridSize * 0.8 ) ;
63+ var cellHeight = Math . min ( spacingY * 0.8 , availableHeight / gridSize * 0.8 ) ;
64+
65+ fixedPositions . push ( {
66+ x : x ,
67+ y : y ,
68+ row : r ,
69+ col : c ,
70+ cellWidth : cellWidth ,
71+ cellHeight : cellHeight
72+ } ) ;
73+ }
74+ }
75+
76+ usedFixedPositions = [ ] ;
77+ }
78+
79+ function calculateOptimalFontSize ( text , cellWidth , cellHeight ) {
80+ // Estimate character width (rough approximation)
81+ var avgCharWidth = 0.6 ; // Average character width as fraction of font size
82+ var maxCharsPerLine = Math . floor ( cellWidth / ( avgCharWidth * 16 ) ) ; // 16px base font
83+
84+ // Calculate how many lines the text will need
85+ var words = text . split ( ' ' ) ;
86+ var lines = 1 ;
87+ var currentLineLength = 0 ;
88+
89+ for ( var i = 0 ; i < words . length ; i ++ ) {
90+ var wordLength = words [ i ] . length ;
91+ if ( currentLineLength + wordLength + 1 > maxCharsPerLine && currentLineLength > 0 ) {
92+ lines ++ ;
93+ currentLineLength = wordLength ;
94+ } else {
95+ currentLineLength += wordLength + ( i > 0 ? 1 : 0 ) ;
96+ }
97+ }
98+
99+ // Calculate font size based on available height and number of lines
100+ var maxFontSize = Math . floor ( cellHeight / lines * 0.8 ) ; // 0.8 for padding
101+ var minFontSize = 12 ; // Minimum readable font size
102+ var optimalFontSize = Math . max ( minFontSize , Math . min ( maxFontSize , 24 ) ) ; // Cap at 24px
103+
104+ return optimalFontSize ;
105+ }
106+
107+ function getFixedPosition ( ) {
108+ if ( usedFixedPositions . length >= fixedPositions . length ) {
109+ // All positions used, reset
110+ usedFixedPositions = [ ] ;
111+ }
112+
113+ // Get used rows and columns
114+ var usedRows = usedFixedPositions . map ( function ( pos ) { return pos . row ; } ) ;
115+ var usedCols = usedFixedPositions . map ( function ( pos ) { return pos . col ; } ) ;
116+
117+ // Find positions that don't share a row or column with any used position
118+ var availablePositions = fixedPositions . filter ( function ( pos ) {
119+ return ! usedRows . includes ( pos . row ) && ! usedCols . includes ( pos . col ) ;
120+ } ) ;
121+
122+ if ( availablePositions . length === 0 ) {
123+ // If no positions available with unique row/column, fall back to any unused position
124+ var fallbackPositions = fixedPositions . filter ( function ( pos ) {
125+ return ! usedFixedPositions . some ( function ( used ) {
126+ return used . x === pos . x && used . y === pos . y ;
127+ } ) ;
128+ } ) ;
129+
130+ if ( fallbackPositions . length === 0 ) {
131+ // All positions used, reset and return first position
132+ usedFixedPositions = [ ] ;
133+ return fixedPositions [ 0 ] ;
134+ }
135+
136+ var randomIndex = Math . floor ( Math . random ( ) * fallbackPositions . length ) ;
137+ var selectedPosition = fallbackPositions [ randomIndex ] ;
138+
139+ // Add randomness to fallback positions too
140+ var randomOffsetX = ( Math . random ( ) - 0.5 ) * 60 ; // -30 to +30
141+ var randomOffsetY = ( Math . random ( ) - 0.5 ) * 40 ; // -20 to +20
142+
143+ var randomizedPosition = {
144+ x : selectedPosition . x + randomOffsetX ,
145+ y : selectedPosition . y + randomOffsetY ,
146+ row : selectedPosition . row ,
147+ col : selectedPosition . col ,
148+ cellWidth : selectedPosition . cellWidth ,
149+ cellHeight : selectedPosition . cellHeight
150+ } ;
151+
152+ usedFixedPositions . push ( selectedPosition ) ;
153+ return randomizedPosition ;
154+ }
155+
156+ // Randomly select from available positions that don't share row/column
157+ var randomIndex = Math . floor ( Math . random ( ) * availablePositions . length ) ;
158+ var selectedPosition = availablePositions [ randomIndex ] ;
159+
160+ // Add randomness to the position (±30px for x, ±20px for y)
161+ var randomOffsetX = ( Math . random ( ) - 0.5 ) * 60 ; // -30 to +30
162+ var randomOffsetY = ( Math . random ( ) - 0.5 ) * 40 ; // -20 to +20
163+
164+ // Create a new position object with random offsets
165+ var randomizedPosition = {
166+ x : selectedPosition . x + randomOffsetX ,
167+ y : selectedPosition . y + randomOffsetY ,
168+ row : selectedPosition . row ,
169+ col : selectedPosition . col ,
170+ cellWidth : selectedPosition . cellWidth ,
171+ cellHeight : selectedPosition . cellHeight
172+ } ;
173+
174+ usedFixedPositions . push ( selectedPosition ) ;
175+
176+ return randomizedPosition ;
177+ }
178+
30179function getNextLyric ( ) {
31180 if ( currentLyricIndex >= lyrics . length ) {
32181 // All lyrics have been shown, don't show any more
@@ -51,6 +200,7 @@ function clearAllLyrics() {
51200 pathIndex = 0 ;
52201 usedPositions = [ ] ;
53202 mobileLineIndex = 0 ;
203+ usedFixedPositions = [ ] ; // Reset fixed positions
54204}
55205
56206function detectMobile ( ) {
@@ -59,8 +209,9 @@ function detectMobile() {
59209 var userAgentMatch = / A n d r o i d | w e b O S | i P h o n e | i P a d | i P o d | B l a c k B e r r y | I E M o b i l e | O p e r a M i n i / i. test ( navigator . userAgent ) ;
60210
61211 isMobile = mediaQueryMatch || userAgentMatch ;
212+ isDesktop = ! isMobile ; // Update desktop flag
62213
63- console . log ( 'Mobile detection - Screen width:' , screenWidth , 'Media query match:' , mediaQueryMatch , 'User agent match:' , userAgentMatch , 'isMobile:' , isMobile ) ;
214+ console . log ( 'Mobile detection - Screen width:' , screenWidth , 'Media query match:' , mediaQueryMatch , 'User agent match:' , userAgentMatch , 'isMobile:' , isMobile , 'isDesktop:' , isDesktop ) ;
64215
65216 return isMobile ;
66217}
@@ -178,6 +329,15 @@ function generateSpiralPath() {
178329}
179330
180331function getNextPosition ( ) {
332+ // Use fixed positions for desktop, spiral for mobile
333+ if ( isDesktop && ! isMobile ) {
334+ if ( fixedPositions . length === 0 ) {
335+ createFixedPositions ( ) ;
336+ }
337+ return getFixedPosition ( ) ;
338+ }
339+
340+ // Mobile positioning (keep existing logic)
181341 if ( pathPositions . length === 0 ) {
182342 pathPositions = generateSpiralPath ( ) ;
183343 }
@@ -481,11 +641,18 @@ function toggleSVG(cell, two, shape) {
481641 } else {
482642 console . log ( 'Using desktop positioning' ) ;
483643 position = getNextPosition ( ) ;
644+
645+ // Calculate optimal font size for this lyric
646+ var fontSize = 16 ; // Default font size
647+ if ( position . cellWidth && position . cellHeight ) {
648+ fontSize = calculateOptimalFontSize ( lyricData . text , position . cellWidth , position . cellHeight ) ;
649+ }
650+
484651 // Adjust position to ensure text stays within bounds
485652 position = adjustPositionForText ( position , lyricData . text ) ;
486653
487654 var lyricLine = $ ( `
488- <div class="lyric-line" style="left: ${ position . x } px; top: ${ position . y } px;">
655+ <div class="lyric-line" style="left: ${ position . x } px; top: ${ position . y } px; font-size: ${ fontSize } px; max-width: ${ position . cellWidth || 200 } px; text-align: center; ">
489656 ${ lyricData . text }
490657 </div>
491658 ` ) ;
0 commit comments