React Fiber 和 Drei clickHandler 运行两次 (Next.js)

React Fiber and Drei clickHandler runs two times (Next.js)

提问人:Hristo hristov 提问时间:11/11/2023 更新时间:11/11/2023 访问量:6

问:

在我开始之前,我想指出我正在研究Nextjs。我目前有一个体验组件,我一直在其中摆弄和测试不同的想法。我传递了一系列潜在的博客,并尝试动态生成它们。当我将 onClick 事件处理程序添加到博客时,问题就来了。当我单击 Blog 组件时,它确实运行了处理程序,但它运行了两次。处理程序所做的只是通过轻微旋转将组件移动到一个方向。我目前有主要的Page.js和两个组件,这就是一切。我确实有一些 glb 文件和模型,但它们与问题无关。

页面.js

"use client"
import { Experience } from '@/Components/Experience/Experience'
import { Backdrop, OrbitControls, PerspectiveCamera, ScrollControls, useHelper, } from '@react-three/drei';
import { Canvas } from '@react-three/fiber';
import { useEffect, useRef } from 'react';
import * as THREE from "three";

export default function Home() {
  const items = [1, 2, 3, 4, 5, 6, 7, 8];

  return (
    <section id="base">
      <Canvas shadows >
        <ScrollControls
          pages={items ? items.length * 0.36 : 0}
          horizontal
          damping={1}
        >
          {items ?
            <Experience blogs={items} />
            :
            null}

        </ScrollControls>

      </Canvas>
    </section>
  )
}

经验:

"use client";
import {
  OrbitControls,
  ScrollControls,
  useTexture,
  Decal,
  useHelper,
  PerspectiveCamera,
  Backdrop,
  useScroll,
  Scroll,
} from "@react-three/drei";
import { Blog } from "../Blog/Blog";

import { useFrame, useLoader, useThree } from "@react-three/fiber";
import { TextureLoader } from "three";
import { useLayoutEffect, useRef, useState } from "react";
import { PointLightHelper } from "three";
import { useEffect } from "react";

import gsap from "gsap";

import * as THREE from "three";
import { Page } from "../Page/Page";

const Light = () => {
  const ref = useRef();
  useHelper(ref, PointLightHelper, 1);

  return (
    <rectAreaLight
      width={20}
      height={20}
      ref={ref}
      position={[-5, 10, 20]}
      intensity={0.7}
      rotation={[0, 0, 0]}
    />
  );
};

export const Experience = ({ blogs }) => {
  const [map] = useLoader(TextureLoader, ["/react.jpg"]);
  const [moveIndex, setMoveIndex] = useState(0);
  const cameraRef = useRef();
  const scroll = useScroll();
  const tl = useRef();
  const axesRef = useRef();
  const blogsRef = blogs.map((blog) => useRef(null));


  const chosenhandler = (index) => {
    console.log(blogsRef[index].current);
    if (blogsRef[index].current.name == "active") {
      blogsRef[index].current.name = "";
      gsap.to(
        blogsRef[index].current.position,
        {
          duration: 2,
          z: blogsRef[index].current.position.z + 1,
          ease: "power4.out",
        },
        0
      );
      gsap.to(
        blogsRef[index].current.rotation,
        {
          duration: 2,
          _y: blogsRef[index].current.position._y - 0.3,
          ease: "power4.out",
        },
        0
      );
    } else {
      blogsRef[index].current.name = "active";
      gsap.to(
        blogsRef[index].current.position,
        {
          duration: 2,
          z: blogsRef[index].current.position.z - 1,
          ease: "power4.out",
        },
        0
      );
      gsap.to(
        blogsRef[index].current.rotation,
        {
          duration: 2,
          _y: blogsRef[index].current.position._y + 0.3,
          ease: "power4.out",
        },
        0
      );
    }
  };

  const blogGeneration = blogs.map((blog, index) => {
    const distance = 7 * index;
    const positioning = distance + index;
    console.log("blog" + index);
    return (
      <Blog
        scroll={scroll}
        position={[positioning, 3, -0.2 * index + 1]}
        rotation={[0, -1.5, 0]}
        key={"blog" + index}
        innerRef={blogsRef[index]}
        onClick={(e) => chosenhandler(index)}
      />
    );
  });

  return (
    <>
      <axesHelper ref={axesRef} />
      <ambientLight intensity={0.5} />
      <Light />
      <PerspectiveCamera
        ref={cameraRef}
        makeDefault={true}
        position={[0.1, 7.2, 8]}
        fov={70}
        rotation={[0, 0.3, 0]}
      />
      <Backdrop
        scale={[400, 120, 10]}
        rotation={[0, 0.1, 0]}
        position={[10, 0, -20]}
        floor={10} // Stretches the floor segment, 0.25 by default
        segments={20} // Mesh-resolution, 20 by default
      >
        <meshStandardMaterial color="#fff" />
      </Backdrop>
      <Scroll>{blogGeneration}</Scroll>
    </>
  );
};

博客:

/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx [email protected] models/project-prep.glb 
*/

import React, { useEffect, useRef, useState } from "react";
import { Decal, Float, useGLTF, useHelper, useScroll } from "@react-three/drei";
import { useFrame, useLoader } from "@react-three/fiber";
import { DoubleSide, PointLightHelper, TextureLoader } from "three";
import gsap from "gsap";

import * as THREE from "three";

export function Blog(props) {
  const [map] = useLoader(TextureLoader, ["/react.jpg"]);
  const { nodes, materials } = useGLTF("models/Blog.glb");

  const data = useScroll();

  const Light = () => {
    const ref = useRef();

    return (
      <rectAreaLight
        width={5}
        height={5}
        ref={ref}

        position={[3, 4.2, 0]}
        intensity={3}
        rotation={[0, 1.3, 0]}
      />
    );
  };

  const [hovered, setHovered] = useState(false);

  useEffect(() => {
    document.body.style.cursor = hovered ? "pointer" : "auto";
  }, [hovered]);

  return (
    <group
      {...props}
      dispose={null}
      ref={props.innerRef}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <Float
        speed={5} 
        rotationIntensity={0.1} 
        floatIntensity={0.2} 
        floatingRange={[0.1, 1]} 
      >
        {hovered ? <Light /> : null}
        <mesh
          geometry={nodes.Cube.geometry}
          material={materials.Material}
          position={[0, 4.2, 0]}
          scale={[0.25, 2.5, 3]}
        >
          <Decal
            position={[1.15, 0, 0.1]}
            rotation={[0, 1, 0]}
            scale={[1.6, 1.87, 1.6]}
          >
            <meshStandardMaterial
              side={DoubleSide}
              map={map}
              polygonOffset
              polygonOffsetFactor={-1}
            />
          </Decal>
        </mesh>
      </Float>
    </group>
  );
}

useGLTF.preload("models/blog.glb");

我尝试关闭严格模式,但它并没有做太多事情。我玩了很多,但没有成功。我尝试改变我的方法,但这是不可能的。

下一个.js 事件处理 GSAP 反应-三-德雷 反应-纤维

评论

0赞 Hristo hristov 11/12/2023
我意识到,如果我将事件添加到贴花中,在博客中,它会运行一次,这让我相信我可能没有将其正确附加到父组/网格上。由于这是在Blender中创建的自定义对象,我应该如何正确设置事件?

答: 暂无答案