сенсорное управление: повторять действие до касания - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь добавить сенсорное управление в сцену three.js.Я хочу переместить камеру в любом направлении, к которому прикасается пользователь.Он отлично работает с клавиатурой, потому что вы можете нажать и удерживать кнопку, и камера будет двигаться непрерывно.Но когда я пытаюсь сделать то же самое, используя touchstart, вы должны постоянно нажимать на экран, чтобы двигаться, вы не можете просто удерживать палец, как на клавиатуре или мыши.

Я посмотрел на touchmove,но если вы просто нажимаете и удерживаете без движения, новых прикосновений нет.

Есть ли что-то похожее на удержание клавиатуры или мыши с помощью сенсорных событий?

1 Ответ

0 голосов
/ 05 июня 2018

Нет встроенного обратного вызова для сенсорного события, которое запускается многократно, как клавиатура.Однако вы можете просто отслеживать начало и конец касания, а затем вызывать метод перемещения через заданный интервал.

Сначала подпишитесь на правильные события и установите логическое значение для отслеживания состояния:

var isTouching = false;
window.addEventListener("touchstart", () => isTouching = true);
window.addEventListener("touchend", () => isTouching = false);

В Three.js у вас, скорее всего, уже будет цикл рендеринга (например, функция с именем animate).Проверяйте переменную состояния на каждой итерации и применяйте движение каждый раз.Вам также может понадобиться учитывать deltaTime (длительность последнего кадра), чтобы сделать частоту кадров независимой.

function animate() {
    requestAnimationFrame(animate);
    mesh.rotation.x += 0.005;
    mesh.rotation.y += 0.01;

    if (isTouching) {
        console.log("move camera");
    }

    renderer.render(scene, camera);   
}

Вот фрагмент, демонстрирующий базовый подход.Нажмите и удерживайте левую или правую половину окна вывода, чтобы переместить камеру.

var camera, scene, renderer, mesh, material, clock;
init();
animate();


var isTouching = false;
var mousePositionX;
window.addEventListener("mousedown", (e) => {
  isTouching = true;
  mousePositionX = e.clientX;
});
window.addEventListener("mouseup", (e) => isTouching = false);


function init() {
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  clock = new THREE.Clock();

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
  camera.position.z = 400;

  scene = new THREE.Scene();
  material = new THREE.MeshPhongMaterial();
  var geometry = new THREE.BoxGeometry(200, 200, 200);
  mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  var light = new THREE.AmbientLight(0x404040);
  scene.add(light);

  var directionalLight = new THREE.DirectionalLight(0xffffff);
  directionalLight.position.set(1, 1, 1).normalize();
  scene.add(directionalLight);

  window.addEventListener('resize', onWindowResize, false);
}

function animate() {
  requestAnimationFrame(animate);
  mesh.rotation.x += 0.005;
  mesh.rotation.y += 0.01;

  let deltaTime = clock.getDelta();

  if (isTouching) {
    let speed = 200; // px per second
    let movement = speed * deltaTime;

    if (mousePositionX > window.innerWidth / 2) {
      camera.translateX(-movement);
    } else {
      camera.translateX(movement);
    }
  }

  renderer.render(scene, camera);
}

function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}
body {
  padding: 0;
  margin: 0;
}

canvas {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/93/three.min.js"></script>
...