Direct touch

다이렉트 터치

Reaching out and physically "poking" a floating button with a fingertip — unlike pinch, the hand has to be at the same location as the content.

Also known as: Direct interactionPoke
···
js
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(48, 1, 0.1, 20);
camera.position.set(0, 0.2, 4.4);
camera.lookAt(0, 0, 0);
scene.add(new THREE.HemisphereLight(0xbcd0ff, 0x101018, 1.5));
const key = new THREE.DirectionalLight(0xffffff, 1.1); key.position.set(2, 3, 3); scene.add(key);
const btn = new THREE.Mesh(new THREE.CylinderGeometry(0.7, 0.7, 0.22, 40), new THREE.MeshStandardMaterial({ color: 0x5b5bf7, roughness: 0.4 }));
btn.rotation.x = Math.PI / 2;
scene.add(btn);
const tip = new THREE.Mesh(new THREE.SphereGeometry(0.14, 24, 24), new THREE.MeshStandardMaterial({ color: 0xffd7a8 }));
scene.add(tip);
function resize() { renderer.setSize(innerWidth, innerHeight); camera.aspect = innerWidth / innerHeight; camera.updateProjectionMatrix(); }
addEventListener('resize', resize); resize();
const BASE_Z = 0.11, PRESS_Z = -0.05;
renderer.setAnimationLoop((t) => {
  const p = (Math.sin(t * 0.0013) + 1) / 2;
  const finZ = 2.4 - p * 2.28;
  tip.position.set(0, 0, finZ);
  const pressed = finZ < BASE_Z + 0.05;
  btn.position.z += ((pressed ? PRESS_Z : BASE_Z) - btn.position.z) * 0.35;
  btn.material.color.set(pressed ? 0x8a8aff : 0x5b5bf7);
  renderer.render(scene, camera);
});

If hand-tracking pinch is "pick with your eyes far away, keep your hand comfortable," direct touch is the opposite. When a button sits within arm's reach (the comfort zone), the user physically extends a finger to that location and presses the surface to confirm. It feels closest to tapping a phone screen.

This mode tracks how deep the fingertip crosses into the virtual surface (a touch threshold) and gives feedback — visionOS substitutes a subtle audio/visual cue for actual touch — the moment the press registers. It needs less learning than pinch and feels more intuitive, but holding an arm up repeatedly gets tiring over time (the "gorilla arm" problem).

The demo moves a fingertip forward until it reaches the button's surface, at which point the button presses in. Unlike the pinch demo, notice the finger actually travels to the same location as the button.

When to use

Use it for close-range UI within reach — small panels, keyboards. Layouts that keep the arm raised cause fatigue, so consider pinch for controls used for long stretches.