Views

Starter pack

अब तक हमने कई 3D दृश्य बनाए हैं, लेकिन हमने केवल एक बार में एक ही दृश्य को देखा है और पूरे पेज पर कब्जा कर लिया है।

इस पाठ में हम सीखेंगे कि कैसे एक ही HTML पेज में कई 3D दृश्य एकीकृत करें, जैसे आप अपनी वेबसाइट पर छवियाँ, वीडियो या कोई अन्य HTML तत्व जोड़ सकते हैं।

आरंभिक प्रोजेक्ट

इस पाठ के लिए हम एक काल्पनिक 3D वेब विकास एजेंसी के लिए एक लैंडिंग पेज बनाएंगे।

स्टार्टर पैक में एक सरल और उपयोग के लिए तैयार रेस्पॉन्सिव पेज शामिल है जिसमें निम्नलिखित अनुभाग शामिल हैं: होम, सेवाएँ, टीम, पोर्टफोलियो, और संपर्क।

यह एक मानक HTML पेज है जिसमें खोज इंजन और एक्सेसिबिलिटी के लिए इंडेक्सेबल कंटेंट है, जिसे हम 3D सामग्री के साथ सुधारेंगे और चित्रित करेंगे।

बिना 3D सामग्री के लैंडिंग पेज

View

हमारे पेज में कई 3D दृश्य बनाने और रेंडर करने के लिए हम Drei लाइब्रेरी के View component का उपयोग करेंगे।

इसका उपयोग करके, हम केवल एक Canvas कंपोनेंट का उपयोग कर सकते हैं और इसके भीतर कई स्वतंत्र दृश्य (views) रेंडर कर सकते हैं। यह बहुत उपयोगी है क्योंकि यह हमें केवल एक WebGL संदर्भ का उपयोग करने की अनुमति देता है और प्रदर्शन मुद्दों से बचाता है।

ये views एक लक्षित HTML तत्व से बंधे होते हैं और स्पर्श, माउस, स्क्रॉल और रीसाइज़ घटनाओं पर ठीक से प्रतिक्रिया करते हुए स्वतंत्र रूप से स्थिति और आकार में सेट किए जा सकते हैं।

कैनवास

हमारी पेज को 3D कंटेंट के लिए तैयार करने के लिए, main एलिमेंट के शीर्ष पर हमारे सामान्य Canvas कॉम्पोनेंट को बनाते हैं।

HomePage.jsx:

// ...
import { Canvas } from "react-three-fiber";

export const HomePage = () => {
  // ...

  return (
    <main>
      <Canvas
        className="canvas"
        camera={{ position: [0, 0, 1.5], fov: 30 }}
      ></Canvas>
      {/* ... */}
    </main>
  );
};

canvas क्लास का उपयोग कैनवास को स्टाइल करने और इसे पूरी पेज में फैलाने के लिए किया जाता है। यह पहले से ही index.css फाइल में परिभाषित है।

ट्रैकिंग

स्टार्टर प्रोजेक्ट में 3D सीन कॉम्पोनेंट्स शामिल हैं जिन्हें हम पेज के विभिन्न सेक्शनों को दर्शाने के लिए इस्तेमाल करेंगे।

चलिए होम सेक्शन के लिए एक को जोड़ते हैं:

import { Hero3D } from "./Hero3D";

export const HomePage = () => {
  // ...
  return (
    <main>
      <Canvas className="canvas" camera={{ position: [0, 0, 1.5], fov: 30 }}>
        <Hero3D />
      </Canvas>
      {/* ... */}
    </main>
  );
};

ऐसा करके, हम देख सकते हैं कि 3D सीन हमेशा पेज के शीर्ष पर रेंडर होती है और पूरी पेज को घेर लेती है।

इसे होम सेक्शन में शामिल करने के लिए, इसे एक View में लपेटते हैं। एकमात्र आवश्यक प्रॉप track है जो HTML एलिमेंट का संदर्भ है जिसे व्यू के कंटेनर के रूप में उपयोग किया जाएगा।

चलो शुरू करते हैं Home सेक्शन के संदर्भ को बनाकर (यह Hero नाम का कॉम्पोनेंट है):

import { useEffect, useRef, useState } from "react";
// ...
export const HomePage = () => {
  const heroContainer = useRef();
  //...

  return (
    <main>
      {/* ... */}
      <Hero ref={heroContainer} />
      {/* ... */}
    </main>
  );
};

फिर, चलिए हमारे View कॉम्पोनेंट को बनाते हैं और track प्रॉप पास करते हैं:

import { View } from "@react-three/drei";
// ...
export const HomePage = () => {
  const heroContainer = useRef();
  //...

  return (
    <main>
      <Canvas className="canvas" camera={{ position: [0, 0, 1.5], fov: 30 }}>
        <View track={heroContainer}>
          <Hero3D />
        </View>
      </Canvas>
      {/* ... */}
    </main>
  );
};

अब हमारी Hero 3D सीन Home सेक्शन के अंदर रेंडर होती है, सही ढंग से स्क्रोल और रीसाइज़ घटनाओं का पालन करती है।

चलो इस प्रक्रिया को अन्य सेक्शनों के लिए दोहराते हैं। हम प्रत्येक HTML कंटेनर के लिए एक संदर्भ बनाएंगे जो 3D सीन प्राप्त करने के लिए तैयार होंगे।

सेवाएं:

// ...
export const HomePage = () => {
  const servicesContainer = useRef();
  // ...
  return (
    <main>
      {/* ... */}
      <section className="services" id="services">
        <h2 className="services__title">हमारी सेवाएं</h2>
        <div className="services__slider">
          <div
            className="services__slider__display"
            ref={servicesContainer}
          ></div>
          {/* ... */}
        </div>
      </section>
      {/* ... */}
    </main>
  );
};

टीम सदस्य:

// ...
export const HomePage = () => {
  const johnDoeContainer = useRef();
  const juliaDoeContainer = useRef();
  const lindaDoeContainer = useRef();
  // ...
  return (
    <main>
      {/* ... */}
      <section className="team" id="team">
        <h2 className="team__title">हमारी टीम</h2>
        <p className="team__subtitle">
          हम 3D वेब और मोबाइल डेवलपर्स, डिजाइनर्स और आर्टिस्ट्स की एक टीम हैं।
          हमारा लक्ष्य आपके व्यवसाय को अलग बनाने के लिए बेहतरीन 3D अनुभव बनाना है।
        </p>
        <div className="team__member">
          <div className="team__member__body">
            <p className="team__member__body__name">जॉन डो</p>
            <p className="team__member__body__title">CEO</p>
            <p className="team__member__body__description">
              ‟Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam
              voluptatum, quas, voluptate, voluptas quae quod quibusdam
              voluptatibus quia quos molestiae natus?”
            </p>
          </div>
          <div
            className="team__member__display team__member__display--blue"
            ref={johnDoeContainer}
          ></div>
        </div>
        <div className="team__member team__member--reverse">
          <div className="team__member__body">
            <p className="team__member__body__name">जूलिया डो</p>
            <p className="team__member__body__title">लीड डेवलपर</p>
            <p className="team__member__body__description">
              ‟Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam
              voluptatum, quas, voluptate, voluptas quae quod quibusdam
              voluptatibus quia quos molestiae natus?”
            </p>
          </div>
          <div
            className="team__member__display team__member__display--pink"
            ref={juliaDoeContainer}
          ></div>
        </div>
        <div className="team__member">
          <div className="team__member__body">
            <p className="team__member__body__name">लिंडा डो</p>
            <p className="team__member__body__title">3D आर्टिस्ट</p>
            <p className="team__member__body__description">
              ‟Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam
              voluptatum, quas, voluptate, voluptas quae quod quibusdam
              voluptatibus quia quos molestiae natus?”
            </p>
          </div>
          <div
            className="team__member__display team__member__display--orange"
            ref={lindaDoeContainer}
          ></div>
        </div>
      </section>
      {/* ... */}
    </main>
  );
};

पोर्टफोलियो:

// ...
export const HomePage = () => {
  const portfolioContainer = useRef();
  // ...
  return (
    <main>
      {/* ... */}
      <section className="portfolio" id="portfolio">
        <h2 className="portfolio__title">हमारा पोर्टफोलियो</h2>
        <p className="portfolio__subtitle">
          हम अपने क्लाइंट्स के लिए अद्भुत प्रोजेक्ट्स पर काम कर चुके हैं। यहाँ कुछ हैं।
        </p>
        <div className="portfolio__display" ref={portfolioContainer}></div>
      </section>
      {/* ... */}
    </main>
  );
};

अब जब हमारे सारे कंटेनर्स तैयार हो गए हैं, चलिए हमारे Canvas कॉम्पोनेंट में विभिन्न व्यू को जोड़ते हैं।

import { Environment, View } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { useEffect, useRef, useState } from "react";
import { degToRad } from "three/src/math/MathUtils.js";
import { Hero } from "./Hero";
import { Hero3D } from "./Hero3D";
import { Portfolio3D } from "./Portfolio3D";
import { Services3D } from "./Services3D";
import { TeamMember } from "./TeamMember";

export const HomePage = () => {
  // ...
  return (
    <main>
      <Canvas className="canvas" camera={{ position: [0, 0, 1.5], fov: 30 }}>
        <View track={heroContainer}>
          <Hero3D />
        </View>
        <View track={servicesContainer}>
          <Services3D currentService={currentService} />
        </View>
        <View track={johnDoeContainer}>
          <TeamMember
            model="Suit"
            position-y={-1.5}
            rotation-y={-degToRad(20)}
          />
          <Environment preset="sunset" />
        </View>
        <View track={juliaDoeContainer}>
          <TeamMember
            model="Formal"
            position-y={-1.5}
            rotation-y={degToRad(20)}
          />
          <Environment preset="sunset" />
        </View>
        <View track={lindaDoeContainer}>
          <TeamMember
            model="Casual"
            position-y={-1.5}
            rotation-y={degToRad(-20)}
          />
          <Environment preset="sunset" />
        </View>
        <View track={portfolioContainer}>
          <Portfolio3D />
        </View>
      </Canvas>
      {/* ... */}
    </main>
  );
};

इस पाठ में हम विभिन्न 3D दृश्यों को कवर नहीं करेंगे। आपके पास उन्हें समझने के लिए आवश्यक सभी ज्ञान हैं और यदि आपको उनके काम करने के तरीके पर कोई शंका है तो आप उनके कोड को देख सकते हैं।

प्रत्येक टीम सदस्य के 3D अवतार

अब हमारी सभी 3D सीन उनके संबंधित HTML कंटेनर्स के अंदर रेंडर होती हैं।

मोबाइल मोड में प्रत्येक टीम सदस्य के 3D अवतार

यह View कॉम्पोनेंट के डिफ़ॉल्ट रिस्पॉन्सिव व्यवहार के लिए धन्यवाद से सही तरीके से मोबाइल डिवाइस पर भी काम करता है।

Container

यदि हम टेक्स्ट का चयन करने या विभिन्न सेवा कार्ड पर क्लिक करने का प्रयास करें, तो हम देख सकते हैं कि यह संभव नहीं है। ऐसा इसलिए है क्योंकि Canvas कंपोनेंट सभी इवेंट्स को कैप्चर कर रहा है।

हमें Canvas कंपोनेंट में eventSource prop जोड़ने की आवश्यकता है। इसका उपयोग माउस और टच इवेंट्स को ट्रैक करने के लिए किया जाता है और View कंपोनेंट के सही तरीके से काम करने के लिए आवश्यक है।

आइए ref को main एलिमेंट के लिए बनाते हैं और इसे Canvas कंपोनेंट में पास करते हैं।

// ...
export const HomePage = () => {
  const container = useRef();

  return (
    <main ref={container}>
      <Canvas
        eventSource={container}
        // ...
      ></Canvas>
      {/* ... */}
    </main>
  );
};

अब, इवेंट्स का वितरण सही तरीके से View कंपोनेंट द्वारा संभाला जाता है और हम विभिन्न HTML एलिमेंट्स के साथ इंटरैक्ट कर सकते हैं।

आगे बढ़ते हुए

हमारा प्रोजेक्ट समाप्त हो गया है, लेकिन चलिए कुछ मुद्दों पर चर्चा करते हैं जो आप अपने स्वयं के प्रोजेक्ट्स में View कंपोनेंट का उपयोग करते समय सामना कर सकते हैं।

पृष्ठभूमि और Z-Index

इस परियोजना में, होम सेक्शन एकमात्र ऐसा है जो HTML और 3D सामग्री दोनों के लिए समान कंटेनर साझा करता है।

स्मार्टफोन और उसकी छाया HTML सामग्री के पीछे प्रदर्शित होते हैं। इसे करने के लिए, hero क्लास की z-index 1 है और position को relative सेट किया गया है।

index.css में, चलिए उन्हें अस्थायी रूप से टिप्पणी करें और देखें कि क्या होता है:

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  /* position: relative;
  z-index: 1; */
  padding: 0 1rem;
}

स्मार्टफोन और उसकी छाया HTML सामग्री के ऊपर प्रदर्शित होती है

हम अपना मुख्य शीर्षक अब नहीं देख सकते क्योंकि 3D सामग्री HTML सामग्री के ऊपर प्रदर्शित हो रही है।

HTML सामग्री के z-index और position को समायोजित करने के अलावा एक और समाधान है। हम Hero3D घटक से सफेद पृष्ठभूमि और धुंध को हटा सकते हैं और हमारे पास वही परिणाम होगा।

यह वास्तव में आपके परियोजना और इच्छित परिणाम पर निर्भर करता है। निर्णय लेने के लिए आपको निम्नलिखित प्रश्न पूछने की आवश्यकता है:

  • यदि 3D तत्व और HTML तत्व एक दूसरे पर प्रवृति लेते हैं, तो उनमें से कौन सा ऊपर प्रदर्शित होना चाहिए?
  • मैं अपने सेक्शन के लिए किस प्रकार की पृष्ठभूमि चाहता हूँ? एक ठोस रंग, एक ग्रेडिएंट, एक छवि, एक वीडियो, या एक 3D दृश्य?

Camera controls

यदि आप विभिन्न views पर OrbitControls या CameraControls जैसे camera controls का उपयोग करने का प्रयास करते हैं, तो आप देखेंगे कि यह प्रत्येक 3D scene के लिए कैमरा को स्थानांतरित करेगा।

यह इसलिए है क्योंकि वर्तमान में आपके सभी views के लिए केवल एक साझा कैमरा है। इसे ठीक करने के लिए, आपको प्रत्येक view के लिए एक कैमरा बनाना होगा।

कैसे करें यह सीखने के लिए Camera lesson देखें।

इसे वांछित view के भीतर बनाने और कैमरा में makeDefault prop जोड़ने के लिए सावधान रहें।

Following scroll

View component एक बेहतरीन उपकरण है जो एकल पृष्ठ में कई 3D scenes प्रस्तुत करने के लिए है, लेकिन इसमें एक मुख्य खामी है।

क्योंकि View component वास्तव में अपने container के भीतर नहीं है बल्कि इसे ट्रैक कर रहा है, यह स्क्रॉल को पूरी तरह से अनुसरण नहीं कर सकता है।

इसीलिए जब तेजी से स्क्रॉलिंग करते हैं, तो 3D सामग्री और HTML सामग्री के बीच कुछ गैप्स देखी जा सकती हैं:

ध्यान दें कि स्क्रॉल करते समय अवतार कंटेनर से थोड़ा बाहर जा सकता है।

अधिकांश प्रोजेक्ट्स में यह समस्या नहीं होनी चाहिए, लेकिन अगर आप इसे परफेक्ट बनाना चाहते हैं, तो View components की बजाय कई Canvas components का उपयोग करने पर विचार करें।

Conclusion

अब आप परफेक्ट हाइब्रिड HTML/3D पेजेज़ बना सकते हैं। यह अद्भुत और अनूठे अनुभव बनाने के लिए दोनों दुनियाओं का सबसे अच्छा संयोजन है, जबकि आपकी सामग्री को सर्च इंजनों द्वारा इंडेक्स और एक्सेसिबल बनाए रखता है।

End of lesson preview

To get access to the entire lesson, you need to purchase the course.