7
7
<div class =" absolute inset-0 z-0 pointer-events-none overflow-hidden" >
8
8
<div class =" falling-blocks-container" >
9
9
<div
10
- v-for =" i in 20 "
10
+ v-for =" i in blockCount "
11
11
:key =" i"
12
12
class =" falling-block"
13
- :style =" generateBlockStyle()"
13
+ :style =" generateBlockStyle(i )"
14
14
></div >
15
15
<!-- JSON symbol blocks -->
16
16
<div
17
- v-for =" i in 10 "
17
+ v-for =" i in jsonSymbolCount "
18
18
:key =" `json-${i}`"
19
19
class =" falling-json-symbol"
20
- :style =" generateJsonSymbolStyle()"
20
+ :style =" generateJsonSymbolStyle(i )"
21
21
>
22
22
{{ getRandomJsonSymbol() }}
23
23
</div >
@@ -695,41 +695,107 @@ for await (const [value, path] of jsonPathReader(reader, [
695
695
</template >
696
696
697
697
<script setup>
698
- import { onMounted , ref } from " vue"
699
698
import Logo from " ../components/Logo.vue"
700
699
import CodeBlock from " ../components/CodeBlock.vue"
700
+ import { ref , computed , onMounted , onBeforeUnmount } from " vue"
701
+
702
+ // Reactive state for screen width
703
+ const windowWidth = ref (
704
+ typeof window !== " undefined" ? window .innerWidth : 1024
705
+ )
706
+
707
+ // Compute the number of elements based on screen width
708
+ const blockCount = computed (() => {
709
+ const maxBlocks = 60
710
+ const minBlocks = 30
711
+
712
+ if (windowWidth .value >= 1024 ) {
713
+ return maxBlocks
714
+ } else if (windowWidth .value <= 320 ) {
715
+ return minBlocks
716
+ } else {
717
+ // Linear interpolation between min and max based on screen width
718
+ const ratio = (windowWidth .value - 320 ) / (1024 - 320 )
719
+ return Math .round (minBlocks + ratio * (maxBlocks - minBlocks))
720
+ }
721
+ })
722
+
723
+ const jsonSymbolCount = computed (() => {
724
+ const maxSymbols = 15
725
+ const minSymbols = 8
726
+
727
+ if (windowWidth .value >= 1024 ) {
728
+ return maxSymbols
729
+ } else if (windowWidth .value <= 320 ) {
730
+ return minSymbols
731
+ } else {
732
+ // Linear interpolation between min and max based on screen width
733
+ const ratio = (windowWidth .value - 320 ) / (1024 - 320 )
734
+ return Math .round (minSymbols + ratio * (maxSymbols - minSymbols))
735
+ }
736
+ })
737
+
738
+ // Window resize handler
739
+ const handleResize = () => {
740
+ windowWidth .value = window .innerWidth
741
+ }
742
+
743
+ // Set up and clean up the resize listener
744
+ onMounted (() => {
745
+ window .addEventListener (" resize" , handleResize)
746
+ })
747
+
748
+ onBeforeUnmount (() => {
749
+ window .removeEventListener (" resize" , handleResize)
750
+ })
701
751
702
752
// Function to get a random JSON symbol
703
753
const getRandomJsonSymbol = () => {
704
- const symbols = [" {" , " }" , " [" , " ]" , " :" , " , " , ' " ' , " . " ]
754
+ const symbols = [" {" , " }" , " [" , " ]" , " :" ]
705
755
return symbols[Math .floor (Math .random () * symbols .length )]
706
756
}
707
757
708
758
// Function to generate styles for JSON symbol blocks
709
- const generateJsonSymbolStyle = () => {
759
+ const generateJsonSymbolStyle = (index ) => {
710
760
const left = Math .floor (Math .random () * 100 ) // Position across the screen
711
- const delay = Math .random () * 5 // Random delay
712
- const duration = Math .random () * 15 + 15 // Animation duration between 15-30s
761
+
762
+ // Calculate evenly distributed delays based on index
763
+ // This creates a consistent stream of elements
764
+ const maxDelay = 30 // Maximum delay in seconds
765
+ const totalItems = jsonSymbolCount .value
766
+ const delay = ((index / totalItems) * maxDelay) % maxDelay // Distribute delays evenly
767
+
768
+ // Varied durations between 15-25s
769
+ const duration = Math .random () * 10 + 15
770
+
713
771
const size = Math .floor (Math .random () * 20 ) + 20 // Size between 20px and 40px
714
- const opacity = Math .random () * 0.1 + 0.05 // Low opacity between 0.05-0.15
772
+ const originalOpacity = Math .random () * 0.1 + 0.05 // Low opacity between 0.05-0.15
715
773
716
774
return {
717
775
left: ` ${ left} %` ,
718
776
animationDelay: ` ${ delay} s` ,
719
777
animationDuration: ` ${ duration} s` ,
720
- opacity: opacity,
778
+ " --original- opacity" : originalOpacity, // Set as CSS variable
721
779
fontSize: ` ${ size} px` ,
722
780
transform: ` rotate(${ Math .floor (Math .random () * 20 - 10 )} deg)` , // Slight rotation
723
781
}
724
782
}
725
783
726
784
// Function to generate random styles for falling blocks
727
- const generateBlockStyle = () => {
785
+ const generateBlockStyle = (index ) => {
728
786
const size = Math .floor (Math .random () * 40 ) + 10 // Size between 10px and 50px
729
787
const left = Math .floor (Math .random () * 100 ) // Position across the screen
730
- const delay = Math .random () * 5 // Random delay
731
- const duration = Math .random () * 10 + 10 // Animation duration between 10-20s
732
- const opacity = Math .random () * 0.08 + 0.02 // Low opacity between 0.02-0.1
788
+
789
+ // Calculate evenly distributed delays based on index
790
+ // This creates a consistent stream of elements
791
+ const maxDelay = 40 // Maximum delay in seconds
792
+ const totalItems = blockCount .value
793
+ const delay = ((index / totalItems) * maxDelay) % maxDelay // Distribute delays evenly
794
+
795
+ // Varied durations between 10-20s
796
+ const duration = Math .random () * 10 + 10
797
+
798
+ const originalOpacity = Math .random () * 0.08 + 0.02 // Low opacity between 0.02-0.1
733
799
734
800
// Choose random shape type
735
801
const shapeTypes = [" square" , " rectangle" , " circle" , " diamond" ]
@@ -742,7 +808,7 @@ const generateBlockStyle = () => {
742
808
left: ` ${ left} %` ,
743
809
animationDelay: ` ${ delay} s` ,
744
810
animationDuration: ` ${ duration} s` ,
745
- opacity: opacity,
811
+ " --original- opacity" : originalOpacity, // Set as CSS variable
746
812
transform: ` rotate(${ Math .floor (Math .random () * 360 )} deg)` ,
747
813
}
748
814
@@ -761,42 +827,6 @@ const generateBlockStyle = () => {
761
827
762
828
return styles
763
829
}
764
-
765
- // Create a grid pattern background effect for code blocks
766
- const createBackgroundGridPattern = () => {
767
- if (process .client ) {
768
- setTimeout (() => {
769
- const codeWindows = document .querySelectorAll (" .code-window-content" )
770
- codeWindows .forEach ((codeWindow ) => {
771
- if (! codeWindow .querySelector (" .bg-grid-pattern" )) {
772
- const gridPattern = document .createElement (" div" )
773
- gridPattern .classList .add (" bg-grid-pattern" )
774
- gridPattern .style .position = " absolute"
775
- gridPattern .style .inset = " 0"
776
- gridPattern .style .opacity = " 0.05"
777
- gridPattern .style .pointerEvents = " none"
778
- gridPattern .style .backgroundSize = " 20px 20px"
779
- gridPattern .style .backgroundImage =
780
- " linear-gradient(to right, rgba(255, 255, 255, 0.1) 1px, transparent 1px), linear-gradient(to bottom, rgba(255, 255, 255, 0.1) 1px, transparent 1px)"
781
- codeWindow .appendChild (gridPattern)
782
- }
783
- })
784
- }, 100 )
785
- }
786
- }
787
-
788
- // Create a scroll to top function
789
- const scrollToTop = () => {
790
- window .scrollTo ({
791
- top: 0 ,
792
- behavior: " smooth" ,
793
- })
794
- }
795
-
796
- // Initialize any client-side effects
797
- onMounted (() => {
798
- createBackgroundGridPattern ()
799
- })
800
830
</script >
801
831
802
832
<style scoped>
@@ -974,6 +1004,7 @@ onMounted(() => {
974
1004
border-radius : 4px ;
975
1005
animation : fall linear infinite ;
976
1006
z-index : 0 ;
1007
+ will-change : transform;
977
1008
}
978
1009
979
1010
.falling-json-symbol {
@@ -985,14 +1016,25 @@ onMounted(() => {
985
1016
animation : fall linear infinite ;
986
1017
z-index : 0 ;
987
1018
text-shadow : 0 0 5px rgba (59 , 130 , 246 , 0.15 );
1019
+ will-change : transform;
988
1020
}
989
1021
990
1022
@keyframes fall {
991
1023
0% {
992
- transform : translateY (-100px ) rotate (0deg );
1024
+ transform : translateY (-20px ) rotate (0deg );
1025
+ opacity : 0 ;
1026
+ }
1027
+ 2% {
1028
+ /* Quick fade in to the pre-set randomized opacity */
1029
+ opacity : var (--original-opacity , 0.05 );
1030
+ }
1031
+ 98% {
1032
+ /* Maintain the pre-set randomized opacity until near the end */
1033
+ opacity : var (--original-opacity , 0.05 );
993
1034
}
994
1035
100% {
995
- transform : translateY (100vh ) rotate (360deg );
1036
+ transform : translateY (calc (100vh + 40px )) rotate (360deg );
1037
+ opacity : 0 ;
996
1038
}
997
1039
}
998
1040
</style >
0 commit comments