I’m working on a 3D project where I have several spheres of different sizes, and I’m using DragControls to allow users to drag and move the spheres around the screen. However, I’ve noticed some issues with the dragging behavior that I’m hoping to get some help with.
First, DragControls seems to work properly on regular sized spheres such as Venus, Earth, Mars, Uranus, and Neptune. However, on larger spheres, the dragging only works if I set my mouse on their edges. I would like to make the dragging of the larger spheres easier, but I don’t want to change the radius of each sphere.
Second, I have a smaller sphere (Mercury) with a radius of 0.383, and DragControls doesn’t seem to register the drag event at all for this sphere.
I’ve tried using bigger/more segments on the spheres, grouping the body and mesh of the sphere into a THREE.Object3D(), and tweaking the draggingThreshold, but none of these approaches have worked.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html,
body {
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
}
</style>
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module">
import * as THREE from 'https://cdn.skypack.dev/[email protected]/build/three.module.js';
import * as CANNON from 'https://cdn.skypack.dev/cannon-es@latest/dist/cannon-es.js';
import { DragControls } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/controls/DragControls.js';
let planets = []
// Set up the scene
const scene = new THREE.Scene();
const camera = new THREE.OrthographicCamera(
window.innerWidth / -21, // left
window.innerWidth / 21, // right
window.innerHeight / 21, // top
window.innerHeight / -21, // bottom
-130, // near
14000 // far
);
camera.position.set(0, 0, 5);
camera.lookAt(scene.position);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set up Cannon.js
const world = new CANNON.World();
world.gravity.set(0, 0, 0);
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, 5);
scene.add(light);
// Function to create planet
function createPlanet(radius, mass, position, color) {
const shape = new CANNON.Sphere(radius);
const body = new CANNON.Body({ mass: mass, linearDamping: 0.5, angularDamping: 0.5 });
body.addShape(shape);
world.addBody(body);
const geometry = new THREE.SphereGeometry(radius, 32, 32);
const material = new THREE.MeshLambertMaterial({ color: color });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(position);
scene.add(mesh);
planets.push({mesh: mesh, body: body})
return { shape, body, mesh };
}
console.log(planets)
// Create planets
const sun = createPlanet(109, 0, new THREE.Vector3(-125, 0, 0), 0xffff00);
const mercury = createPlanet(0.383, 0, new THREE.Vector3(-15.5, 0, 15), '#A9A9A9');
const venus = createPlanet(0.72, 0, new THREE.Vector3(-13.2, 0, 0), 0xffa500);
const earth = createPlanet(1, 0, new THREE.Vector3(-10.4, 0, 0), 'blue');
const mars = createPlanet(0.532, 0, new THREE.Vector3(-7, 0, 0), 'red');
const jupiter = createPlanet(11.21, 0, new THREE.Vector3(7, 0, 0), 'orange');
const saturn = createPlanet(9.45, 0, new THREE.Vector3(30, 0, 0), 'pink');
const uranus = createPlanet(4.01, 0, new THREE.Vector3(45.8, 0, 0), 'green');
const neptune = createPlanet(3.88, 0, new THREE.Vector3(55.9, 0, 0), 'orange');
let dragControls = new DragControls(planets.map(planet => planet.mesh), camera, renderer.domElement);
dragControls.draggingThreshold = 0.1;
function render() {
requestAnimationFrame(render);
// Update physics
world.step(1 / 60);
renderer.render(scene, camera);
}
// Start the render loop
render();
</script>
</body>
</html>
Can anyone suggest how I can make the dragging for the smaller sphere work and make the dragging of the larger spheres easier without changing the radius of each sphere? Any help would be greatly appreciated. Thanks in advance!