利用
OrbitControls
TransformControls
搭配
zustand 跨階成組件 狀態管理
lamina 控制面板
import React, { createContext, useContext, Suspense, useEffect, useRef, useState } from 'react'
import { Canvas } from '@react-three/fiber'
import { OrbitControls, TransformControls, useCursor, Text, Html } from '@react-three/drei'
// import create from 'zustand'
import { Popconfirm } from 'antd'
import 'antd/dist/antd.css'
import { useTargetStore } from '../store/Store'
export function NFTBox({ children, ...props }) {
const setTarget = useTargetStore((state) => state.setTarget)
const [hovered, setHovered] = useState(false)
useCursor(hovered)
const [position, setPosition] = useState([3, 3, 60])
const [rotation, setRotation] = useState([0, 0, 0])
const [scale, setScale] = useState([1, 1, 1])
const [select, setSelect] = useState(false)
// 相似於 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用瀏覽器 API 更新文件標題
// document.title = `You clicked ${count} times`;
if (props.position) {
setPosition(props.position)
}
if (props.rotation) {
setRotation(props.rotation)
}
if (props.scale) {
setScale(props.scale)
}
// console.log(props.position)
}, [props])
return (
<group {...props} position={position} rotation={rotation} scale={scale}>
<mesh
visible={hovered}
// position={[0, 0, 0]}
// rotate={props.rotate}
onClick={(e) => {
e.stopPropagation() //It functions just like the dom does, except there is raycasting involved. In order to prevent a mouse event from "propagating" downward, you must "stopPropagation()".
// e.stopImmediatePropagation()
// console.log('滑鼠右鍵', e.delta)
// console.log('滑鼠右鍵', e)
if (e.button === 2) {
//如果button=1(滑鼠左鍵),button=2(滑鼠右鍵),button=0(滑鼠中間鍵)
}
setTarget(e.object.parent)
// console.log(e.object.parent)
// setTarget(e.object)
// console.log(e.object)
setSelect(!select)
}}
// onClick={(e) => console.log('click')}
onContextMenu={(e) => console.log('context menu')}
onDoubleClick={(e) => console.log('double click')}
onWheel={(e) => console.log('wheel spins')}
onPointerUp={(e) => console.log('up')}
onPointerDown={(e) => console.log('down')}
// onPointerOver={(e) => console.log('over')}
// onPointerOut={(e) => console.log('out')}
onPointerEnter={(e) => console.log('enter')} // see note 1
onPointerLeave={(e) => console.log('leave')} // see note 1
// onPointerMove={(e) => console.log('move')}
// onPointerMissed={() => console.log('missed')}
// onUpdate={(self) => console.log('props have been updated')}
// onPointerDown={(e) => {
// // Only the mesh closest to the camera will be processed
// e.stopPropagation()
// // You may optionally capture the target
// e.target.setPointerCapture(e.pointerId)
// // console.log('onPointerDown')
// }}
// onPointerUp={(e) => {
// e.stopPropagation()
// // Optionally release capture
// e.target.releasePointerCapture(e.pointerId)
// // console.log('onPointerUp')
// }}
// // onDoubleClick={setSelect(false)}
onPointerOver={(e) => {
// Only the mesh closest to the camera will be processed
e.stopPropagation()
// You may optionally capture the target
e.target.setPointerCapture(e.pointerId)
setHovered(true)
}}
onPointerOut={(e) => {
e.stopPropagation()
// Optionally release capture
e.target.releasePointerCapture(e.pointerId)
setHovered(false)
}}
scale={10}>
<boxGeometry />
{/* <meshPhongMaterial color="blue" opacity={0.1} transparent /> */}
<meshStandardMaterial transparent={true} opacity={0.5} color="orange" />
{hovered && (
<Html distanceFactor={0.25} position={[-0.5, 1, 0.5]}>
<div className="tooltip">|{props.name}</div>
</Html>
)}
{/* {select && (
<Html distanceFactor={0.25} position={[-0.65, 1.7, 0.5]}>
<div className="tooltip">
Setting
<br />
OK NO
</div>
</Html>
)} */}
</mesh>
{children}
</group>
)
}
//TODO不傳透
//https://blog.csdn.net/weixin_41077029/article/details/108616264?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1.topblog&utm_relevant_index=1
export function GUCBox(props) {
const setTarget = useTargetStore((state) => state.setTarget)
const [hovered, setHovered] = useState(false)
useCursor(hovered)
const [position, setPosition] = useState([3, 3, 60])
const [rotation, setRotation] = useState([0, 0, 0])
const [scale, setScale] = useState([1, 1, 1])
const [select, setSelect] = useState(false)
// 相似於 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用瀏覽器 API 更新文件標題
// document.title = `You clicked ${count} times`;
if (props.position) {
setPosition(props.position)
}
if (props.rotation) {
setRotation(props.rotation)
}
if (props.scale) {
setScale(props.scale)
}
console.log(props.position)
}, [props])
return (
<group {...props} position={position} rotation={rotation} scale={scale}>
<mesh
// position={[0, 0, 0]}
// rotate={props.rotate}
scale={5}
onClick={(e) => {
setTarget(e.object)
setSelect(true)
}}
onDoubleClick={setSelect(false)}
onPointerOver={() => setHovered(true)}
onPointerOut={() => setHovered(false)}>
<boxGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</group>
)
}
// function OpConfirm() {
// return (
// <Html center>
// <Popconfirm title="Are you sure you want to leave?" onConfirm={true} okText="Yes" cancelText="No">
// <a href="#">{'name'}</a>
// </Popconfirm>
// </Html>
// )
// }
function Dodecahedron({ time, ...props }) {
return (
<mesh {...props}>
<dodecahedronGeometry />
<meshStandardMaterial roughness={0.75} emissive="#404057" />
<Html distanceFactor={10}>
<div class="content">
hello <br />
world
</div>
</Html>
</mesh>
)
}