added mouse click
This commit is contained in:
parent
bd5fa12a1e
commit
0a750606ac
|
|
@ -1,10 +1,9 @@
|
||||||
import { useEffect, useRef } from "react";
|
import { useEffect, useRef } from "react";
|
||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { useInteraction, type InteractionMouseMoveEventArgs } from "../helpers/hooks/useInteration";
|
import { useInteraction, type InteractionMouseEventArgs } from "../helpers/hooks/useInteration";
|
||||||
import { db } from "../backend/db";
|
import { db } from "../backend/db";
|
||||||
import { HitTestFactory, type HitTest } from "../helpers/hitTest";
|
import { HitTestFactory, type HitTest } from "../helpers/hitTest";
|
||||||
import { model } from "../model/model";
|
import { model } from "../model/model";
|
||||||
import { Point3dHelper } from "../helpers/point3dHelper";
|
|
||||||
import { SceneHelper } from "../helpers/sceneHelper";
|
import { SceneHelper } from "../helpers/sceneHelper";
|
||||||
|
|
||||||
export type ThreeViewEventArgs = {
|
export type ThreeViewEventArgs = {
|
||||||
|
|
@ -17,14 +16,15 @@ export type ThreeViewTickEventArgs = ThreeViewEventArgs & {
|
||||||
absoluteTime: number,
|
absoluteTime: number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ThreeViewMouseMoveEventArgs = ThreeViewEventArgs & {
|
export type ThreeViewMouseEventArgs = ThreeViewEventArgs & {
|
||||||
hitTest: HitTest,
|
hitTest: HitTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ThreeViewProps = {
|
export type ThreeViewProps = {
|
||||||
sceneHelper: SceneHelper,
|
sceneHelper: SceneHelper,
|
||||||
onTick?: (event: ThreeViewTickEventArgs) => void,
|
onTick?: (event: ThreeViewTickEventArgs) => void,
|
||||||
onMouseMove?: (event: ThreeViewMouseMoveEventArgs) => void,
|
onClick?: (event: ThreeViewMouseEventArgs) => void,
|
||||||
|
onMouseMove?: (event: ThreeViewMouseEventArgs) => void,
|
||||||
onDispose: (event: ThreeViewEventArgs) => void,
|
onDispose: (event: ThreeViewEventArgs) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,7 +67,8 @@ export const ThreeView = function (props: ThreeViewProps) {
|
||||||
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
||||||
const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
|
const cameraRef = useRef<THREE.PerspectiveCamera | null>(null);
|
||||||
|
|
||||||
let handleHover: (e: InteractionMouseMoveEventArgs) => void;
|
let handleClick: (e: InteractionMouseEventArgs) => void;
|
||||||
|
let handleHover: (e: InteractionMouseEventArgs) => void;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
@ -100,7 +101,7 @@ export const ThreeView = function (props: ThreeViewProps) {
|
||||||
};
|
};
|
||||||
window.addEventListener("resize", handleWindowResize);
|
window.addEventListener("resize", handleWindowResize);
|
||||||
|
|
||||||
handleHover = (e: InteractionMouseMoveEventArgs) => {
|
handleHover = (e: InteractionMouseEventArgs) => {
|
||||||
const hitTest = HitTestFactory.hitTest(
|
const hitTest = HitTestFactory.hitTest(
|
||||||
props.sceneHelper,
|
props.sceneHelper,
|
||||||
new THREE.Vector2(e.position.x, e.position.y),
|
new THREE.Vector2(e.position.x, e.position.y),
|
||||||
|
|
@ -114,6 +115,20 @@ export const ThreeView = function (props: ThreeViewProps) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handleClick = (e: InteractionMouseEventArgs) => {
|
||||||
|
const hitTest = HitTestFactory.hitTest(
|
||||||
|
props.sceneHelper,
|
||||||
|
new THREE.Vector2(e.position.x, e.position.y),
|
||||||
|
camera,
|
||||||
|
{ tolerancePixels: 3, cameraPixelSize: e.pixelSize }
|
||||||
|
);
|
||||||
|
props.onClick?.({
|
||||||
|
camera,
|
||||||
|
scene,
|
||||||
|
hitTest,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
// --- Animation loop ---
|
// --- Animation loop ---
|
||||||
let lastTime = performance.now();
|
let lastTime = performance.now();
|
||||||
let animId: number;
|
let animId: number;
|
||||||
|
|
@ -153,6 +168,7 @@ export const ThreeView = function (props: ThreeViewProps) {
|
||||||
|
|
||||||
useInteraction(canvasRef, cameraRef, {
|
useInteraction(canvasRef, cameraRef, {
|
||||||
onMouseMove: (e) => handleHover?.(e),
|
onMouseMove: (e) => handleHover?.(e),
|
||||||
|
onMouseClick: (e) => handleClick?.(e),
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
import { useState } from "react";
|
|
||||||
import { useSceneHelper } from "../helpers/hooks/useSceneHelper";
|
import { useSceneHelper } from "../helpers/hooks/useSceneHelper";
|
||||||
import { Point3dHelper } from "../helpers/point3dHelper";
|
|
||||||
import { state } from "../state/root";
|
import { state } from "../state/root";
|
||||||
import { ThreeView, type ThreeViewEventArgs, type ThreeViewMouseMoveEventArgs } from "./ThreeVIew";
|
import { ThreeView, type ThreeViewEventArgs, type ThreeViewMouseEventArgs } from "./ThreeVIew";
|
||||||
|
|
||||||
export const Viewport = function () {
|
export const Viewport = function () {
|
||||||
|
|
||||||
const sceneHelper = useSceneHelper();
|
const sceneHelper = useSceneHelper();
|
||||||
|
|
||||||
function handleMouseMove(e: ThreeViewMouseMoveEventArgs) {
|
function handleMouseMove(e: ThreeViewMouseEventArgs) {
|
||||||
state.setHitTest(e.hitTest);
|
state.setHitTest(e.hitTest);
|
||||||
|
|
||||||
sceneHelper.clearPoints();
|
sceneHelper.clearPoints();
|
||||||
|
|
@ -33,10 +31,15 @@ export const Viewport = function () {
|
||||||
// throw new Error("Function not implemented.");
|
// throw new Error("Function not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleClick(e: ThreeViewMouseEventArgs): void {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<ThreeView
|
<ThreeView
|
||||||
sceneHelper={sceneHelper}
|
sceneHelper={sceneHelper}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
|
onClick={handleClick}
|
||||||
onDispose={handleDispose}
|
onDispose={handleDispose}
|
||||||
/>
|
/>
|
||||||
</>);
|
</>);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import { useEffect, type RefObject } from "react";
|
import { useEffect, type RefObject } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
|
||||||
export type InteractionMouseMoveEventArgs = {
|
const CLICK_THRESHOLD = 2; // px
|
||||||
|
|
||||||
|
export type InteractionMouseEventArgs = {
|
||||||
position: { x: number, y: number },
|
position: { x: number, y: number },
|
||||||
pixelSize: { x: number, y: number },
|
pixelSize: { x: number, y: number },
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UseInteractionOptions = {
|
export type UseInteractionOptions = {
|
||||||
onMouseMove?: (e: InteractionMouseMoveEventArgs) => void,
|
onMouseClick?: (e: InteractionMouseEventArgs) => void,
|
||||||
|
onMouseMove?: (e: InteractionMouseEventArgs) => void,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useInteraction(
|
export function useInteraction(
|
||||||
|
|
@ -29,6 +32,7 @@ export function useInteraction(
|
||||||
// --- Orbit Controls (manual implementation, no OrbitControls import needed) ---
|
// --- Orbit Controls (manual implementation, no OrbitControls import needed) ---
|
||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let isRightDrag = false;
|
let isRightDrag = false;
|
||||||
|
let startX = 0, startY = 0;
|
||||||
let lastX = 0, lastY = 0;
|
let lastX = 0, lastY = 0;
|
||||||
let theta = 0.8, phi = 0.9, radius = 8;
|
let theta = 0.8, phi = 0.9, radius = 8;
|
||||||
let targetX = 0, targetY = 0;
|
let targetX = 0, targetY = 0;
|
||||||
|
|
@ -44,12 +48,24 @@ export function useInteraction(
|
||||||
const onMouseDown = (e: MouseEvent) => {
|
const onMouseDown = (e: MouseEvent) => {
|
||||||
isDragging = true;
|
isDragging = true;
|
||||||
isRightDrag = e.button === 2;
|
isRightDrag = e.button === 2;
|
||||||
|
startX = e.clientX;
|
||||||
|
startY = e.clientY;
|
||||||
lastX = e.clientX;
|
lastX = e.clientX;
|
||||||
lastY = e.clientY;
|
lastY = e.clientY;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
const onMouseUp = () => { isDragging = false; };
|
const onMouseUp = (e: MouseEvent) => {
|
||||||
|
isDragging = false;
|
||||||
|
if ((e.clientX - startX < CLICK_THRESHOLD) && (e.clientY - startY < CLICK_THRESHOLD)) {
|
||||||
|
const rect = target.getBoundingClientRect();
|
||||||
|
const position = {
|
||||||
|
x: ((e.clientX - rect.left) / rect.width) * 2 - 1,
|
||||||
|
y: -((e.clientY - rect.top) / rect.height) * 2 + 1,
|
||||||
|
};
|
||||||
|
options.onMouseClick?.({ position, pixelSize: { x: 2 / rect.width, y: 2 / rect.height } });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const onMouseMove = (e: MouseEvent) => {
|
const onMouseMove = (e: MouseEvent) => {
|
||||||
if (!isDragging) return;
|
if (!isDragging) return;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue