diff --git a/src/components/gradient-provider.tsx b/src/components/gradient-provider.tsx
index a94a470..d0dca72 100644
--- a/src/components/gradient-provider.tsx
+++ b/src/components/gradient-provider.tsx
@@ -8,16 +8,16 @@ import { motion } from "framer-motion";
export function GradientProvider({ children }: { children: React.ReactNode }) {
return (
-
-
);
}
@@ -31,19 +31,17 @@ export function SymetricGradProvider({
gradient_class?: string;
}) {
return (
-
-
+
-
+
{children}
);
diff --git a/src/components/grain.tsx b/src/components/grain.tsx
index b46e203..ce45336 100644
--- a/src/components/grain.tsx
+++ b/src/components/grain.tsx
@@ -1,8 +1,6 @@
"use client";
-import { motion } from "framer-motion";
-// Grain.tsx
-import React, { useEffect, useRef } from "react";
+import React, { useEffect, useRef, useCallback } from "react";
type GrainOptions = {
patternWidth?: number;
@@ -18,68 +16,76 @@ export const GrainProvider = ({
}: {
grain_options?: GrainOptions;
}) => {
- const providerRef = useRef(null);
+ const canvasRef = useRef(null);
+ const animationFrameId = useRef();
- // Function to generate and apply grain effect
- const applyGrain = (ele: HTMLElement, opt: GrainOptions) => {
- const canvas = document.createElement("canvas");
- const ctx = canvas.getContext("2d");
- if (!ctx) return;
+ const createGrainPattern = (
+ ctx: CanvasRenderingContext2D,
+ opt: GrainOptions,
+ ) => {
+ const patternCanvas = document.createElement("canvas");
+ const pctx = patternCanvas.getContext("2d");
- canvas.width = opt.patternWidth ?? 100;
- canvas.height = opt.patternHeight ?? 100;
+ patternCanvas.width = opt.patternWidth ?? 200;
+ patternCanvas.height = opt.patternHeight ?? 200;
- for (let w = 0; w < canvas.width; w += opt.grainDensity ?? 1) {
- for (let h = 0; h < canvas.height; h += opt.grainDensity ?? 1) {
- const rgb = Math.floor(Math.random() * 256);
- ctx.fillStyle = `rgba(${rgb / 2}, ${rgb / 2}, ${rgb}, ${opt.grainOpacity ?? 0.1
- })`;
- ctx.fillRect(w, h, opt.grainWidth ?? 1, opt.grainHeight ?? 1);
+ if (pctx) {
+ for (let w = 0; w < patternCanvas.width; w += opt.grainDensity ?? 1) {
+ for (let h = 0; h < patternCanvas.height; h += opt.grainDensity ?? 1) {
+ const rgb = Math.floor(Math.random() * 256);
+ pctx.fillStyle = `rgba(${rgb / 2}, ${rgb / 2}, ${rgb}, ${opt.grainOpacity ?? 0.1
+ })`;
+ pctx.fillRect(w, h, opt.grainWidth ?? 1, opt.grainHeight ?? 1);
+ }
}
}
- ele.style.backgroundImage = `url(${canvas.toDataURL("image/png")})`;
+ return ctx.createPattern(patternCanvas, "repeat");
};
- useEffect(() => {
- const element = providerRef.current;
- if (!element) return;
+ const animate = useCallback(() => {
+ const canvas = canvasRef.current;
+ if (canvas) {
+ const ctx = canvas.getContext("2d");
+ if (ctx) {
+ const options: GrainOptions = {
+ patternWidth: 200,
+ patternHeight: 200,
+ grainOpacity: 0.05,
+ grainDensity: 1,
+ grainWidth: 1,
+ grainHeight: 1,
+ };
- // Define options here
- const options: GrainOptions = {
- patternWidth: 240,
- patternHeight: 300,
- grainOpacity: 0.05,
- grainDensity: 1,
- grainWidth: 2,
- grainHeight: 2,
- };
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
- // Apply grain initially
- applyGrain(element, grain_options ?? options);
+ const pattern = createGrainPattern(ctx, grain_options ?? options);
+ if (pattern) {
+ ctx.fillStyle = pattern;
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ }
- // Set interval to update grain
- const intervalId = setInterval(() => {
- applyGrain(element, grain_options ?? options);
- }, 100);
-
- // Cleanup function
- return () => clearInterval(intervalId);
+ animationFrameId.current = requestAnimationFrame(animate);
+ }
+ }
}, [grain_options]);
+ useEffect(() => {
+ animationFrameId.current = requestAnimationFrame(animate);
+ return () => {
+ if (animationFrameId.current) {
+ cancelAnimationFrame(animationFrameId.current);
+ }
+ };
+ }, [animate]);
+
return (
-
+ />
);
};
-
export default GrainProvider;