DEV Community

Rain9
Rain9

Posted on

Easily enhance your website design with dynamic backgrounds!(2)

Background

In the previous article, “How to realize a high-tech official website (I)”, we explored the overall design of the website and discussed its visual presentation and user experience.

Our initial internal design leaned toward simplicity, so we began exploring ways to enhance the overall design aesthetics. This exploration led to the following implementations.

Website URL: https://infinilabs.com/

If you're interested in creating dynamic backgrounds, this article will guide you through building a visually appealing and functional enterprise website from scratch!

Technology Stack

  • Frontend Framework: Next.js
  • UI Framework: Based on Tailwind CSS
  • CSS Styles: Tailwind CSS (rapid development, built-in responsiveness, rich utility classes)

Why choose Next.js?

  1. Compatible with team tech stack: Built on React, enabling seamless collaboration.
  2. SEO and performance optimization: Supports Server-Side Rendering (SSR) and Static Site Generation (SSG).
  3. Powerful routing: Supports dynamic routing and file-based routing, making it flexible and easy to use.
  4. Built-in optimization: Image optimization, internationalization, and various performance enhancements.
  5. Dynamic content support: Ideal for dynamic scenarios like blogs and news platforms.
  6. Excellent loading experience: Provides top-notch user experience and fast page load times.

Dynamic Background Solutions

Dynamic backgrounds can significantly enhance visual appeal. Here are common solutions:

  1. CSS Animated Background: Pure CSS for animations using @keyframes with gradient colors, position shifts, etc.
  2. Dynamic Canvas Background: Using <canvas> and JavaScript for effects like particle systems and wave patterns.
  3. Dynamic Video Background: Looping videos with <video> as the background.
  4. WebGL Dynamic Background: Using WebGL libraries like Three.js for 3D effects.
  5. Dynamic Particle Background: Leveraging libraries like particles.js or tsparticles for quick particle effects.
  6. ......

How to Choose?

  1. Simple Needs: Pure CSS animations or dynamic video backgrounds.
  2. Complex Interactions: Canvas animations or WebGL effects (Three.js).
  3. Quick Implementation: Use particle libraries like particles.js or tsparticles.

Dynamic Background Code Implementation

Below is an example using WebGL to create a dynamic background component, supporting React and Tailwind CSS.

1. Create GlobalBackground.tsx:

'use client'

import dynamic from 'next/dynamic'
import { Suspense, useEffect, useState } from 'react'
import { Layout } from './Layout'

const ShaderGradient = dynamic(() => import('shadergradient').then((mod) => mod.ShaderGradient), { ssr: false })
const View = dynamic(() => import('./View').then((mod) => mod.View), {
  ssr: false,
  loading: () => (
    <div className='w-full h-full bg-cover bg-center' style={{ backgroundImage: 'url(/images/loading-bg.png)' }}>
    </div>
  ),
})

export default function GlobalBackground() {
  const defaultProps: any = {
    control: "props",
    animate: "on",
    brightness: 1.2,
    cDistance: 3.6,
    cameraZoom: 1,
    color1: "#0600B8",
    color2: "#9000E3",
    color3: "#0B004F",
    // embedMode: "off",
    envPreset: "city",
    // gizmoHelper: "hide",
    grain: "off",
    lightType: "3d",
    reflection: 0.1,
    shader: "defaults",
    type: "waterPlane",
    uSpeed: 0.2,
    uTime: 0,
    wireframe: false,
    zoomOut: false,
    toggleAxis: false,
  }

  const [suspenseWebgl, setSuspenseWebgl] = useState(false)
  useEffect(() => {
    const canvas = document.createElement("canvas");
    const gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
    if (gl) {
        console.log('The browser does support WebGL')
        setSuspenseWebgl(true)
    } else {
      console.log('The browser does not support WebGL')
    }
  }, []);
  return (<>
      {suspenseWebgl ? <Layout>
        <View className='w-full h-full'>
          <Suspense fallback={null}>
            <ShaderGradient {...defaultProps} />
          </Suspense>
        </View>
      </Layout> : null}
    </>)
}
Enter fullscreen mode Exit fullscreen mode

2. Create Layout.tsx:

'use client'

import { useRef } from 'react'
import dynamic from 'next/dynamic'
const Scene = dynamic(() => import('./Scene'), { ssr: false })

const Layout = ({ children }: any) => {
  const ref = useRef<any>()

  return (
    <div
      ref={ref}
      className='fade-in'
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '100%',
        zIndex: -1,
        overflow: 'auto',
        touchAction: 'auto',
      }}
    >
      {children}
      <Scene
        style={{
          position: 'fixed',
          top: 0,
          left: 0,
          width: '100%',
          height: '100%',
          pointerEvents: 'none',
        }}
        eventSource={ref}
        eventPrefix='client'
        pixelDensity={1}
        pointerEvents='none'
      />
    </div>
  )
}

export { Layout }
Enter fullscreen mode Exit fullscreen mode

3. Create Scene.tsx:

'use client'

import { ShaderGradientCanvas } from 'shadergradient'
import { Canvas } from '@react-three/fiber'
import { Preload } from '@react-three/drei'
import tunnel from 'tunnel-rat'

const r3f = tunnel()

export default function Scene({ ...props }) {
  // Everything defined in here will persist between route changes, only children are swapped

  return (
    <ShaderGradientCanvas {...props}>
      {/* @ts-ignore */}
      <r3f.Out />
      <Preload all />
    </ShaderGradientCanvas>
  )
}
Enter fullscreen mode Exit fullscreen mode

4. Create View.tsx:

'use client'

import { forwardRef, Suspense, useImperativeHandle, useRef } from 'react'
import { OrbitControls, PerspectiveCamera, View as ViewImpl } from '@react-three/drei'
import tunnel from 'tunnel-rat'

const r3f = tunnel()

const Three = ({ children } : any) => {
  return <r3f.In>{children}</r3f.In>
}

export const Common = ({ color }: any) => (
  <Suspense fallback={null}>
    {color && <color attach='background' args={[color]} />}
    <ambientLight intensity={0.5} />
    <pointLight position={[20, 30, 10]} intensity={1} />
    <pointLight position={[-10, -10, -10]} color='blue' />
    <PerspectiveCamera makeDefault fov={40} position={[0, 0, 6]} />
  </Suspense>
)

const View = forwardRef(({ children, orbit, ...props }: any, ref) => {
  const localRef = useRef<any>(null)
  useImperativeHandle(ref, () => localRef.current)

  return (
    <>
      <div ref={localRef} {...props} />
      <Three>
        <ViewImpl track={localRef}>
          {children}
          {orbit && <OrbitControls />}
        </ViewImpl>
      </Three>
    </>
  )
})
View.displayName = 'View'

export { View }
Enter fullscreen mode Exit fullscreen mode

5. Use the background component in app/page.tsx:

import GlobalBackground from "@/components/GlobalBackground";

export default function Home() {
  return (
    <>
      <GlobalBackground></GlobalBackground>
      <div
        className="min-h-screen bg-cover bg-center"
        style={{ backgroundImage: "url(/svg/bg_n.svg)" }}
      >
        ....
      </div>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

6. Install dependencies:

pnpm add @react-three/drei @react-three/fiber shadergradient tunnel-rat
Enter fullscreen mode Exit fullscreen mode

These steps enable you to implement a high-performance, responsive dynamic background. Adjust background types and interactions based on your specific needs to make your website more engaging!

Demo

Demo

Share

If you'd like to configure your own dynamic effects, visit shadergradient.co for customization. After setting it up, copy the generated parameters into the defaultProps of GlobalBackground.tsx to create your unique dynamic background.

References

Bonus

INFINILabs is committed to providing developers and enterprises with high-quality open-source tools, invigorating the tech ecosystem. Alongside maintaining popular domestic tools like analysis-ik and analysis-pinyin, it continues to drive the development of high-quality open-source products.

Recently open-sourced products and tools:

Find all these open-source projects on GitHub: https://github.com/infinilabs

We’d greatly appreciate a Star 🌟 for support!

Top comments (0)