All components

Novatrix Background

Novatrix Background is a React and Tailwind CSS background component from Eldora UI, licensed MIT. Copy it and paste it into your project.

Eldora UI MIT backgrounds

What it is

Novatrix Background is a React and Tailwind CSS background component from Eldora UI, licensed MIT. Copy it and paste it into your project.

How to use it

Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.

Open in the catalogue

Five free copies a month. No card.

Needs

npm i react ogl

Licence

This component comes from Eldora UI and is redistributed under the MIT licence, which permits commercial use. The copyright notice travels with the code.

Novatrix Background

registry/eldoraui/novatrix-background.tsx
"use client"

import { useEffect, useRef } from "react"
import { Color, Mesh, Program, Renderer, Triangle } from "ogl"

const vertexShader = `
attribute vec2 uv;
attribute vec2 position;

varying vec2 vUv;

void main() {
  vUv = uv;
  gl_Position = vec4(position, 0, 1);
}
`

const fragmentShader = `
precision highp float;

uniform float uTime;
uniform vec3 uColor;
uniform vec3 uResolution;
uniform vec2 uMouse;
uniform float uAmplitude;
uniform float uSpeed;

varying vec2 vUv;

void main() {
  float mr = min(uResolution.x, uResolution.y);
  vec2 uv = (vUv.xy * 2.0 - 1.0) * uResolution.xy / mr;

  uv += (uMouse - vec2(0.5)) * uAmplitude;

  float d = -uTime * 0.5 * uSpeed;
  float a = 0.0;
  for (float i = 0.0; i < 8.0; ++i) {
    a += cos(i - d - a * uv.x);
    d += sin(uv.y * i + a);
  }
  d += uTime * 0.5 * uSpeed;
  vec3 col = vec3(cos(uv * vec2(d, a)) * 0.6 + 0.4, cos(a + d) * 0.5 + 0.5);
  col = cos(col * cos(vec3(d, a, 2.5)) * 0.5 + 0.5) * uColor;
  gl_FragColor = vec4(col, 1.0);
}
`

interface NovatrixProps {
  color?: [number, number, number]
  speed?: number
  amplitude?: number
  mouseReact?: boolean
}

export default function Novatrix({
  color = [1, 1, 1],
  speed = 1.0,
  amplitude = 0.1,
  mouseReact = false,
  ...rest
}: NovatrixProps) {
  const ctnDom = useRef<HTMLDivElement>(null)
  const mousePos = useRef({ x: 0.5, y: 0.5 })

  useEffect(() => {
    if (!ctnDom.current) return
    const ctn = ctnDom.current
    const renderer = new Renderer()
    const gl = renderer.gl
    gl.clearColor(1, 1, 1, 1)

    // eslint-disable-next-line prefer-const
    let program: Program

    function resize() {
      const scale = 1
      renderer.setSize(ctn.offsetWidth * scale, ctn.offsetHeight * scale)
      if (program) {
        program.uniforms.uResolution.value = new Color(
          gl.canvas.width,
          gl.canvas.height,
          gl.canvas.width / gl.canvas.height
        )
      }
    }
    window.addEventListener("resize", resize, false)
    resize()

    const geometry = new Triangle(gl)
    program = new Program(gl, {
      vertex: vertexShader,
      fragment: fragmentShader,
      uniforms: {
        uTime: { value: 0 },
        uColor: { value: new Color(...color) },
        uResolution: {
          value: new Color(
            gl.canvas.width,
            gl.canvas.height,
            gl.canvas.width / gl.canvas.height
          ),
        },
        uMouse: {
          value: new Float32Array([mousePos.current.x, mousePos.current.y]),
        },
        uAmplitude: { value: amplitude },
        uSpeed: { value: speed },
      },
    })

    const mesh = new Mesh(gl, { geometry, program })
    let animateId: number

    function update(t: number) {
      animateId = requestAnimationFrame(update)
      program.uniforms.uTime.value = t * 0.001
      renderer.render({ scene: mesh })
    }
    animateId = requestAnimationFrame(update)
    ctn.appendChild(gl.canvas)

    function handleMouseMove(e: MouseEvent) {
      const rect = ctn.getBoundingClientRect()
      const x = (e.clientX - rect.left) / rect.width
      const y = 1.0 - (e.clientY - rect.top) / rect.height
      mousePos.current = { x, y }
      program.uniforms.uMouse.value[0] = x
      program.uniforms.uMouse.value[1] = y
    }
    if (mouseReact) {
      ctn.addEventListener("mousemove", handleMouseMove)
    }

    return () => {
      cancelAnimationFrame(animateId)
      window.removeEventListener("resize", resize)
      if (mouseReact) {
        ctn.removeEventListener("mousemove", handleMouseMove)
      }
      ctn.removeChild(gl.canvas)
      gl.getExtension("WEBGL_lose_context")?.loseContext()
    }
  }, [color, speed, amplitude, mouseReact])

  return <div ref={ctnDom} className="h-full w-full" {...rest} />
}

Similar components