@@ -12,7 +12,7 @@ type BackgroundFlickeringGrid = ComponentConfig<
1212export interface FlickeringGridProps {
1313 /**
1414 * The square size of the grid (before scaling)
15- * @default 4
15+ * @default 12
1616 */
1717 squareSize? : number ;
1818 /**
@@ -48,6 +48,11 @@ export interface FlickeringGridProps {
4848 * @default 0.3
4949 */
5050 maxOpacity? : number ;
51+ /**
52+ * Apply radial fade to edges
53+ * @default true
54+ */
55+ fade? : boolean ;
5156 /**
5257 * Canvas width (defaults to container width)
5358 */
@@ -87,16 +92,18 @@ export interface FlickeringGridSlots {
8792<script setup lang="ts">
8893import { ref , computed , onMounted , onBeforeUnmount , watch } from " vue" ;
8994import { tv } from " ../../utils/tv" ;
95+ import { calculateGradientIntensity } from " ../../composables/useGradient" ;
9096import theme from " ../../themes/background-flickering-grid" ;
9197import { getThemeColor , adjustLightness , oklchToRgb } from " ../../composables/useThemeColors" ;
9298
9399const props = withDefaults (defineProps <FlickeringGridProps >(), {
94- squareSize: 4 ,
95- gridGap: 6 ,
100+ squareSize: 8 ,
101+ gridGap: 8 ,
96102 flickerChance: 0.3 ,
97- flickerSpeed: 1 ,
103+ flickerSpeed: 0.2 ,
98104 gradientDirection: " left-right" ,
99105 maxOpacity: 0.3 ,
106+ fade: true ,
100107 color: " neutral" ,
101108 variant: " subtle" ,
102109 class: " " ,
@@ -112,6 +119,15 @@ const ui = computed(() =>
112119 })
113120);
114121
122+ // Radial fade mask
123+ const maskStyle = computed (() => {
124+ if (! props .fade ) return {};
125+ return {
126+ maskImage: " radial-gradient(circle at center, black 20%, transparent 90%)" ,
127+ WebkitMaskImage: " radial-gradient(circle at center, black 20%, transparent 90%)" ,
128+ };
129+ });
130+
115131// Refs
116132const containerRef = ref <HTMLElement >();
117133const canvasRef = ref <HTMLCanvasElement >();
@@ -182,47 +198,18 @@ function rgbToString(rgb: [number, number, number], alpha = 1) {
182198 return ` rgba(${rgb [0 ]},${rgb [1 ]},${rgb [2 ]},${alpha }) ` ;
183199}
184200
185- // Gradient calculation
201+ // Gradient calculation using the reusable composable
186202function getGradientT(
187203 i : number ,
188204 j : number ,
189205 cols : number ,
190206 rows : number
191207): number {
192- switch (props .gradientDirection ) {
193- case " left-right" :
194- return i / (cols - 1 );
195- case " right-left" :
196- return 1 - i / (cols - 1 );
197- case " top-bottom" :
198- return j / (rows - 1 );
199- case " bottom-top" :
200- return 1 - j / (rows - 1 );
201- case " in-out" : {
202- const cx = (cols - 1 ) / 2 ;
203- const cy = (rows - 1 ) / 2 ;
204- const dx = i - cx ;
205- const dy = j - cy ;
206- const dist = Math .sqrt (dx * dx + dy * dy );
207- const maxDist = Math .sqrt (cx * cx + cy * cy );
208- return dist / maxDist ;
209- }
210- case " out-in" : {
211- const cx = (cols - 1 ) / 2 ;
212- const cy = (rows - 1 ) / 2 ;
213- const dx = i - cx ;
214- const dy = j - cy ;
215- const dist = Math .sqrt (dx * dx + dy * dy );
216- const maxDist = Math .sqrt (cx * cx + cy * cy );
217- return 1 - dist / maxDist ;
218- }
219- case " top-left-bottom-right" :
220- return (i + j ) / (cols + rows - 2 );
221- case " bottom-right-top-left" :
222- return 1 - (i + j ) / (cols + rows - 2 );
223- default :
224- return i / (cols - 1 );
225- }
208+ // Normalize grid coordinates to 0-1 range
209+ const x = cols > 1 ? i / (cols - 1 ) : 0.5 ;
210+ const y = rows > 1 ? j / (rows - 1 ) : 0.5 ;
211+
212+ return calculateGradientIntensity (x , y , props .gradientDirection );
226213}
227214
228215// Canvas setup
@@ -380,6 +367,7 @@ watch(
380367 ref =" canvasRef"
381368 data-slot =" canvas"
382369 :class =" ui.canvas({ class: props.ui?.canvas })"
370+ :style =" maskStyle"
383371 :width =" canvasSize.width"
384372 :height =" canvasSize.height"
385373 />
0 commit comments