Stories

Detail Return Return

如何實現一個充滿科技感的官網(二) - Stories Detail

背景

在上一篇文章 《如何實現一個充滿科技感的官網(一)》 中,我們初步瞭解了該官網的整體設計,並與大家探討了它的視覺呈現和用户體驗。

我們前期的內部設計偏向簡潔,所以開始思考如何提升網站的整體設計感。這些嘗試便由此展開。

網站地址:https://infinilabs.com/

如果你對動態背景的實現感興趣,這篇文章將帶你深入探索,揭秘如何從零打造一個兼具美感與功能性的企業官網!

技術選型

  • 前端框架:Next.js
  • UI 框架:基於 Tailwind CSS
  • CSS 樣式:Tailwind CSS(快速開發、內置響應式、豐富工具類)

為什麼選擇 Next.js?

  1. 兼容團隊技術棧:基於 React,便於團隊協作。
  2. SEO 和性能優化:支持服務端渲染(SSR)和靜態站點生成(SSG)。
  3. 路由強大:支持動態路由和文件路由,靈活易用。
  4. 內置優化:圖片優化、國際化、多種性能提升。
  5. 動態內容支持:博客、新聞等動態場景輕鬆應對。
  6. 加載體驗佳:用户體驗和頁面加載速度表現優秀。

動態的背景方案

動態背景可以顯著提升視覺吸引力,以下是常用實現方案:

  1. CSS 動畫背景:使用純 CSS 實現動態背景,通過 @keyframes 配合漸變色、位置移動等屬性。
  2. 動態 Canvas 背景:使用 <canvas> 元素,結合 JavaScript 繪製動態效果,比如粒子系統、波浪效果等。
  3. 動態視頻背景:使用 <video> 元素播放循環視頻作為背景。
  4. WebGL 動態背景:使用 WebGL 庫(如 Three.js)渲染 3D 動態背景。
  5. 動態粒子背景:使用現有的粒子背景庫快速實現動態粒子效果。(particles.js 或 tsparticles)
  6. ......

如何選擇?

  1. 簡單需求: 純 CSS 動畫、動態視頻背景。
  2. 複雜交互:Canvas 動畫、WebGL 動畫(Three.js)。
  3. 快速實現:使用粒子背景庫(particles.js / tsparticles)。

動態背景代碼實現

以下示例通過 WebGL 創建了一個動態背景組件,支持 React 和 Tailwind CSS。

  1. 創建 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) {
      // 瀏覽器支持 WebGL
      console.log("The browser does support WebGL");
      setSuspenseWebgl(true);
    } else {
      console.log("The browser does not support WebGL");
      // 瀏覽器不支持 WebGL
    }
  }, []);
  return (
    <>
      {suspenseWebgl ? (
        <Layout>
          <View className="w-full h-full">
            <Suspense fallback={null}>
              <ShaderGradient {...defaultProps} />
            </Suspense>
          </View>
        </Layout>
      ) : null}
    </>
  );
}
  1. 創建 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 };
  1. 創建 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>
  );
}
  1. 創建 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 };
  1. 直接在 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>
    </>
  );
}
  1. 當然,代碼弄好了,要想讓代碼運行起來,還需要安裝一下依賴:
pnpm add @react-three/drei @react-three/fiber shadergradient tunnel-rat

通過這些步驟,你將能夠為網站實現高性能、響應式的動態背景效果。根據具體需求調整背景類型和交互複雜度,讓你的官網更具吸引力!

效果

具體效果,可以直接在網站上瀏覽,效果更真實。網站地址:https://infinilabs.com/

分享

如果你也想配置自己的動態效果圖,可以前往 shadergradient.co 網站進行自定義設置。完成後,將生成的配置參數複製到 GlobalBackground.tsx 文件的 defaultProps 中,即可實現屬於你自己的動態背景效果。

參考

  • https://github.com/ruucm/shadergradient
  • https://www.shadergradient.co/
  • https://infinilabs.com/

福利

INFINI Labs 一直致力於為開發者和企業提供優質的開源工具,提升整個技術生態的活力。除了維護國內最流行的分詞器 analysis-ikanalysis-pinyin,也在不斷推動更多高質量開源產品的誕生。

最近新開源的產品和工具:

  • INFINI Framework https://github.com/infinilabs/framework
  • INFINI Gateway https://github.com/infinilabs/gateway
  • INFINI Console https://github.com/infinilabs/console
  • INFINI Agent https://github.com/infinilabs/agent
  • INFINI Loadgen https://github.com/infinilabs/loadgen
  • INFINI Coco AI https://github.com/infinilabs/coco-app

以上開源軟件都可以在 Github 上面找到: https://github.com/infinilabs

希望大家都能給個免費的 Star🌟 支持一下!!!

作者:Rain9,極限科技(INFINI Labs) 高級前端開發工程師。
user avatar jiarenxia Avatar monkeynik Avatar front_yue Avatar kk_64ec9e6b37cb5 Avatar greptime Avatar zxbing0066 Avatar yan_609cc3c57e745 Avatar
Favorites 7 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.