Testing drag controls with a desktop based browser.

dev
Unboring SL 5 years ago
parent f781760a45
commit 103e404dd9
  1. 2
      .vscode/settings.json
  2. 4
      package.json
  3. 19
      src/components/drag-controls.js
  4. 89
      src/components/grab.js
  5. 30
      src/home.html
  6. 5
      src/index.js
  7. 282
      src/lib/DragControls.js

@ -0,0 +1,2 @@
{
}

@ -10,12 +10,13 @@
"main": "index.js",
"dependencies": {},
"scripts": {
"start": "webpack-dev-server --mode development --host 192.168.0.12",
"start": "webpack-dev-server --mode development --host 0.0.0.0",
"build": "webpack --mode production --config webpack.config.js"
},
"keywords": [],
"author": "Arturo Paracuellos",
"devDependencies": {
"aframe-aabb-collider-component": "^3.2.0",
"aframe-environment-component": "^2.0.0",
"aframe-super-hot-loader": "^1.7.0",
"aframe-super-hot-html-loader": "^2.1.0",
@ -25,7 +26,6 @@
"css-loader": "^3.4.1",
"html-require-loader": "^1.0.1",
"json-loader": "^0.5.7",
"super-hands": "^3.0.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.39.3",

@ -0,0 +1,19 @@
AFRAME.registerComponent('drag-controls', {
schema: {objects: {type: 'string', default: 'a-entity'}},
init: function () {
var objects = [];
var el = this.el;
var els;
var dragControls;
els = el.sceneEl.querySelectorAll(this.data.objects);
for (var i = 0; i < els.length; i++) {
console.log(i);
objects.push(els[i].object3D);
}
el.sceneEl.addEventListener('renderstart', function () {
dragControls = new THREE.DragControls(objects, el.sceneEl.camera, el.sceneEl.renderer.domElement);
});
}
});

@ -0,0 +1,89 @@
/* global AFRAME, THREE */
/**
* Handles events coming from the hand-controls.
* Determines if the entity is grabbed or released.
* Updates its position to move along the controller.
*/
AFRAME.registerComponent('grab', {
init: function () {
this.GRABBED_STATE = 'grabbed';
// Bind event handlers
this.onHit = this.onHit.bind(this);
this.onGripOpen = this.onGripOpen.bind(this);
this.onGripClose = this.onGripClose.bind(this);
this.currentPosition = new THREE.Vector3();
},
play: function () {
var el = this.el;
el.addEventListener('hit', this.onHit);
el.addEventListener('buttondown', this.onGripClose);
el.addEventListener('buttonup', this.onGripOpen);
},
pause: function () {
var el = this.el;
el.removeEventListener('hit', this.onHit);
el.addEventListener('buttondown', this.onGripClose);
el.addEventListener('buttonup', this.onGripOpen);
},
onGripClose: function (evt) {
if (this.grabbing) { return; }
this.grabbing = true;
this.pressedButtonId = evt.detail.id;
delete this.previousPosition;
},
onGripOpen: function (evt) {
var hitEl = this.hitEl;
if (this.pressedButtonId !== evt.detail.id) { return; }
this.grabbing = false;
if (!hitEl) { return; }
hitEl.removeState(this.GRABBED_STATE);
hitEl.emit('grabend');
this.hitEl = undefined;
},
onHit: function (evt) {
var hitEl = evt.detail.el;
// If the element is already grabbed (it could be grabbed by another controller).
// If the hand is not grabbing the element does not stick.
// If we're already grabbing something you can't grab again.
if (!hitEl || hitEl.is(this.GRABBED_STATE) || !this.grabbing || this.hitEl) { return; }
hitEl.addState(this.GRABBED_STATE);
this.hitEl = hitEl;
},
tick: function () {
var hitEl = this.hitEl;
var position;
if (!hitEl) { return; }
this.updateDelta();
position = hitEl.getAttribute('position');
hitEl.setAttribute('position', {
x: position.x + this.deltaPosition.x,
y: position.y + this.deltaPosition.y,
z: position.z + this.deltaPosition.z
});
},
updateDelta: function () {
var currentPosition = this.currentPosition;
this.el.object3D.updateMatrixWorld();
currentPosition.setFromMatrixPosition(this.el.object3D.matrixWorld);
if (!this.previousPosition) {
this.previousPosition = new THREE.Vector3();
this.previousPosition.copy(currentPosition);
}
var previousPosition = this.previousPosition;
var deltaPosition = {
x: currentPosition.x - previousPosition.x,
y: currentPosition.y - previousPosition.y,
z: currentPosition.z - previousPosition.z
};
this.previousPosition.copy(currentPosition);
this.deltaPosition = deltaPosition;
}
});

@ -1,6 +1,26 @@
<a-scene background="color: #FAFAFA" vr-mode-ui="enterVRButton: #vrButton">
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
<a-scene drag-controls="objects: .cube" background="color: #FAFAFA" vr-mode-ui="enterVRButton: #vrButton">
<a-assets>
<a-mixin id="cube"
event-set__grab="material.color: #FFEF4F"
event-set__grabend="material.color: #F2E646"
event-set__hit="material.color: #F2E646"
event-set__hitend="material.color: #EF2D5E"
event-set__mousedown="material.color: #FFEF4F"
event-set__mouseenter="material.color: #F2E646"
event-set__mouseleave="material.color: #EF2D5E"
event-set__mouseup="material.color: #F2E646"
geometry="primitive: box; height: 0.30; width: 0.30; depth: 0.30"
material="color: #EF2D5E;">
</a-mixin>
</a-assets>
<a-entity class="cube" mixin="cube" position="0.30 1.65 0"></a-entity>
<a-entity class="cube" mixin="cube" position="0 1.95 0"></a-entity>
<a-entity class="cube" mixin="cube" position="-0.30 1.65 0"></a-entity>
<a-entity environment="preset: forest;"></a-entity>
<a-entity hand-controls="left" aabb-collider="objects: .cube;" grab></a-entity>
<a-entity hand-controls="right" aabb-collider="objects: .cube;" grab></a-entity>
<a-entity position="0 1.6 2" camera look-controls wasd-controls></a-entity>
</a-scene>

@ -4,7 +4,10 @@ console.time = () => {};
console.timeEnd = () => {};
require('aframe-environment-component')
require('super-hands')
require('aframe-aabb-collider-component');
require('./lib/DragControls.js');
require('./components/grab');
require('./components/drag-controls');
require('./index.css')

@ -0,0 +1,282 @@
/*
* @author zz85 / https://github.com/zz85
* @author mrdoob / http://mrdoob.com
* Running this will allow you to drag three.js objects around the screen.
*/
THREE.DragControls = function ( _objects, _camera, _domElement ) {
if ( _objects instanceof THREE.Camera ) {
console.warn( 'THREE.DragControls: Constructor now expects ( objects, camera, domElement )' );
var temp = _objects; _objects = _camera; _camera = temp;
}
var _plane = new THREE.Plane();
var _raycaster = new THREE.Raycaster();
var _mouse = new THREE.Vector2();
var _offset = new THREE.Vector3();
var _intersection = new THREE.Vector3();
var _selected = null, _hovered = null;
//
var scope = this;
function activate() {
_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
_domElement.addEventListener( 'mouseup', onDocumentMouseCancel, false );
_domElement.addEventListener( 'mouseleave', onDocumentMouseCancel, false );
_domElement.addEventListener( 'touchmove', onDocumentTouchMove, false );
_domElement.addEventListener( 'touchstart', onDocumentTouchStart, false );
_domElement.addEventListener( 'touchend', onDocumentTouchEnd, false );
}
function deactivate() {
_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
_domElement.removeEventListener( 'mouseup', onDocumentMouseCancel, false );
_domElement.removeEventListener( 'mouseleave', onDocumentMouseCancel, false );
_domElement.removeEventListener( 'touchmove', onDocumentTouchMove, false );
_domElement.removeEventListener( 'touchstart', onDocumentTouchStart, false );
_domElement.removeEventListener( 'touchend', onDocumentTouchEnd, false );
}
function dispose() {
deactivate();
}
function onDocumentMouseMove( event ) {
event.preventDefault();
var rect = _domElement.getBoundingClientRect();
_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
_raycaster.setFromCamera( _mouse, _camera );
if ( _selected && scope.enabled ) {
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_selected.position.copy( _intersection.sub( _offset ) );
}
scope.dispatchEvent( { type: 'drag', object: _selected } );
return;
}
_raycaster.setFromCamera( _mouse, _camera );
var intersects = _raycaster.intersectObjects( _objects, true );
if ( intersects.length > 0 ) {
var object = intersects[ 0 ].object.parent;
_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), object.position );
if ( _hovered !== object ) {
scope.dispatchEvent( { type: 'hoveron', object: object } );
_domElement.style.cursor = 'pointer';
_hovered = object;
}
} else {
if ( _hovered !== null ) {
scope.dispatchEvent( { type: 'hoveroff', object: _hovered } );
_domElement.style.cursor = 'auto';
_hovered = null;
}
}
}
function onDocumentMouseDown( event ) {
event.preventDefault();
_raycaster.setFromCamera( _mouse, _camera );
var intersects = _raycaster.intersectObjects( _objects, true );
if ( intersects.length > 0 ) {
_selected = intersects[ 0 ].object.parent;
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_offset.copy( _intersection ).sub( _selected.position );
}
_domElement.style.cursor = 'move';
scope.dispatchEvent( { type: 'dragstart', object: _selected } );
}
}
function onDocumentMouseCancel( event ) {
event.preventDefault();
if ( _selected ) {
scope.dispatchEvent( { type: 'dragend', object: _selected } );
_selected = null;
}
_domElement.style.cursor = 'auto';
}
function onDocumentTouchMove( event ) {
event.preventDefault();
event = event.changedTouches[ 0 ];
var rect = _domElement.getBoundingClientRect();
_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
_raycaster.setFromCamera( _mouse, _camera );
if ( _selected && scope.enabled ) {
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_selected.position.copy( _intersection.sub( _offset ) );
}
scope.dispatchEvent( { type: 'drag', object: _selected } );
return;
}
}
function onDocumentTouchStart( event ) {
event.preventDefault();
event = event.changedTouches[ 0 ];
var rect = _domElement.getBoundingClientRect();
_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
_raycaster.setFromCamera( _mouse, _camera );
var intersects = _raycaster.intersectObjects( _objects, true );
if ( intersects.length > 0 ) {
_selected = intersects[ 0 ].object.parent;
_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _selected.position );
if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
_offset.copy( _intersection ).sub( _selected.position );
}
_domElement.style.cursor = 'move';
scope.dispatchEvent( { type: 'dragstart', object: _selected } );
}
}
function onDocumentTouchEnd( event ) {
event.preventDefault();
if ( _selected ) {
scope.dispatchEvent( { type: 'dragend', object: _selected } );
_selected = null;
}
_domElement.style.cursor = 'auto';
}
activate();
// API
this.enabled = true;
this.activate = activate;
this.deactivate = deactivate;
this.dispose = dispose;
// Backward compatibility
this.setObjects = function () {
console.error( 'THREE.DragControls: setObjects() has been removed.' );
};
this.on = function ( type, listener ) {
console.warn( 'THREE.DragControls: on() has been deprecated. Use addEventListener() instead.' );
scope.addEventListener( type, listener );
};
this.off = function ( type, listener ) {
console.warn( 'THREE.DragControls: off() has been deprecated. Use removeEventListener() instead.' );
scope.removeEventListener( type, listener );
};
this.notify = function ( type ) {
console.error( 'THREE.DragControls: notify() has been deprecated. Use dispatchEvent() instead.' );
scope.dispatchEvent( { type: type } );
};
};
THREE.DragControls.prototype = Object.create( THREE.EventDispatcher.prototype );
THREE.DragControls.prototype.constructor = THREE.DragControls;
Loading…
Cancel
Save