Enable screen locking for rotated camera views
This commit is contained in:
parent
a675ba84ba
commit
20f5f9b000
5 changed files with 47 additions and 33 deletions
|
@ -3,9 +3,7 @@
|
|||
A Click & Drag component for [A-Frame](https://aframe.io).
|
||||
|
||||
Entities with the `click-drag` component can be click and dragged around the 3D
|
||||
scene. Even works whle the camera is moving!
|
||||
|
||||
_Note: entities are not positioned correctly when the camera is rotated._
|
||||
scene. Even works whle the camera is moving or rotating!
|
||||
|
||||
### Events
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<a-sky color="#ECECEC"></a-sky>
|
||||
|
||||
<a-entity position="0 0 3.8">
|
||||
<a-camera look-controls-enabled="false"></a-camera>
|
||||
<a-camera look-controls-enabled="false" keyboard-controls="fpsMode: true"></a-camera>
|
||||
</a-entity>
|
||||
</a-scene>
|
||||
</body>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<a-sky color="#ECECEC"></a-sky>
|
||||
|
||||
<a-entity position="0 0 3.8">
|
||||
<a-camera look-controls-enabled="false"></a-camera>
|
||||
<a-camera look-controls-enabled="false" keyboard-controls="fpsMode: true"></a-camera>
|
||||
</a-entity>
|
||||
<script>
|
||||
var draggable = document.querySelector('[click-drag]');
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<a-sky color="#ECECEC"></a-sky>
|
||||
|
||||
<a-entity position="0 0 3.8">
|
||||
<a-camera look-controls-enabled="false"></a-camera>
|
||||
<a-camera look-controls-enabled="false" keyboard-controls="fpsMode: true"></a-camera>
|
||||
</a-entity>
|
||||
<script>
|
||||
var draggable = document.querySelector('[click-drag]');
|
||||
|
|
70
src/index.js
70
src/index.js
|
@ -289,7 +289,7 @@ const {selectItem} = (function selectItemFunction() {
|
|||
};
|
||||
}());
|
||||
|
||||
function dragItem(THREE, element, offset, camera, depth, mouseInfo) {
|
||||
function dragItem(THREE, element, offset, camera, depth, mouseInfo, lockToLocalRotation) {
|
||||
|
||||
const {x: offsetX, y: offsetY, z: offsetZ} = offset;
|
||||
const threeCamera = camera.components.camera.camera;
|
||||
|
@ -300,9 +300,17 @@ function dragItem(THREE, element, offset, camera, depth, mouseInfo) {
|
|||
const elementRotationOrder = element.object3D.rotation.order;
|
||||
|
||||
const rotationQuaternion = new THREE.Quaternion();
|
||||
const rotationEuler = new THREE.Euler();
|
||||
const rotationEuler = element.object3D.rotation.clone();
|
||||
|
||||
const offsetVector = new THREE.Vector3(offset.x, offset.y, offset.z);
|
||||
let lastMouseInfo = mouseInfo;
|
||||
|
||||
const nextRotation = {
|
||||
x: THREE.Math.radToDeg(rotationEuler.x),
|
||||
y: THREE.Math.radToDeg(rotationEuler.y),
|
||||
z: THREE.Math.radToDeg(rotationEuler.z),
|
||||
};
|
||||
|
||||
function onMouseMove({clientX, clientY}) {
|
||||
|
||||
lastMouseInfo = {clientX, clientY};
|
||||
|
@ -321,33 +329,35 @@ function dragItem(THREE, element, offset, camera, depth, mouseInfo) {
|
|||
depth
|
||||
);
|
||||
|
||||
// 1. Store initial element rotation
|
||||
// 2. Store initial camera rotation
|
||||
// 3. Calculate difference in camera rotation, inverted
|
||||
// 4. Add #3 + #1
|
||||
// 5. Set element rotation to #4
|
||||
if (lockToLocalRotation) {
|
||||
|
||||
// Start by rotating backwards from the initial camera rotation
|
||||
const rotationDiff = rotationQuaternion.copy(startCameraRotationInverse)
|
||||
// Then add the current camera rotation
|
||||
.multiply(threeCamera.getWorldQuaternion());
|
||||
|
||||
// rotate the offset
|
||||
offsetVector.set(offset.x, offset.y, offset.z);
|
||||
offsetVector.applyQuaternion(rotationDiff);
|
||||
|
||||
// Start by rotating backwards from the initial camera rotation
|
||||
const rotationDiff = rotationQuaternion.copy(startCameraRotationInverse)
|
||||
// Then add the current camera rotation
|
||||
.multiply(threeCamera.getWorldQuaternion())
|
||||
// And correctly offset rotation
|
||||
.multiply(startElementRotation);
|
||||
rotationDiff.multiply(startElementRotation);
|
||||
rotationEuler.setFromQuaternion(rotationDiff, elementRotationOrder);
|
||||
|
||||
rotationEuler.setFromQuaternion(rotationDiff, elementRotationOrder);
|
||||
nextRotation.x = THREE.Math.radToDeg(rotationEuler.x);
|
||||
nextRotation.y = THREE.Math.radToDeg(rotationEuler.y);
|
||||
nextRotation.z = THREE.Math.radToDeg(rotationEuler.z);
|
||||
}
|
||||
|
||||
const nextRotation = {
|
||||
x: THREE.Math.radToDeg(rotationEuler.x),
|
||||
y: THREE.Math.radToDeg(rotationEuler.y),
|
||||
z: THREE.Math.radToDeg(rotationEuler.z),
|
||||
};
|
||||
|
||||
const nextPosition = {x: x - offsetX, y: y - offsetY, z: z - offsetZ};
|
||||
const nextPosition = {x: x - offsetVector.x, y: y - offsetVector.y, z: z - offsetVector.z};
|
||||
|
||||
element.emit(DRAG_MOVE_EVENT, {nextPosition, nextRotation, clientX, clientY});
|
||||
|
||||
element.setAttribute('position', nextPosition);
|
||||
element.setAttribute('rotation', nextRotation);
|
||||
|
||||
if (lockToLocalRotation) {
|
||||
element.setAttribute('rotation', nextRotation);
|
||||
}
|
||||
}
|
||||
|
||||
function onCameraChange({detail}) {
|
||||
|
@ -375,7 +385,7 @@ const {initialize, tearDown} = (function closeOverInitAndTearDown() {
|
|||
let removeClickListeners;
|
||||
|
||||
return {
|
||||
initialize(THREE, componentName) {
|
||||
initialize(THREE, componentName, lockToLocalRotation) {
|
||||
|
||||
// TODO: Based on a scene from the element passed in?
|
||||
const scene = document.querySelector('a-scene');
|
||||
|
@ -419,7 +429,8 @@ const {initialize, tearDown} = (function closeOverInitAndTearDown() {
|
|||
{
|
||||
clientX,
|
||||
clientY,
|
||||
}
|
||||
},
|
||||
lockToLocalRotation
|
||||
);
|
||||
|
||||
draggedElement = element;
|
||||
|
@ -536,10 +547,10 @@ const {didMount, didUnmount} = (function getDidMountAndUnmount() {
|
|||
const cache = [];
|
||||
|
||||
return {
|
||||
didMount(element, THREE, componentName) {
|
||||
didMount(element, THREE, componentName, lockToLocalRotation) {
|
||||
|
||||
if (cache.length === 0) {
|
||||
initialize(THREE, componentName);
|
||||
initialize(THREE, componentName, lockToLocalRotation);
|
||||
}
|
||||
|
||||
if (cache.indexOf(element) === -1) {
|
||||
|
@ -579,6 +590,11 @@ export default function aframeDraggableComponent(aframe, componentName = COMPONE
|
|||
*/
|
||||
aframe.registerComponent(componentName, {
|
||||
schema: {
|
||||
/*
|
||||
* @param {bool} [lockToLocalRotation=true] - When dragging the component,
|
||||
* should it be screen locked (true), or should its rotation be left alone
|
||||
* (false).
|
||||
*/
|
||||
lockToLocalRotation: {default: true},
|
||||
},
|
||||
|
||||
|
@ -586,7 +602,7 @@ export default function aframeDraggableComponent(aframe, componentName = COMPONE
|
|||
* Called once when component is attached. Generally for initial setup.
|
||||
*/
|
||||
init() {
|
||||
didMount(this, THREE, componentName);
|
||||
didMount(this, THREE, componentName, this.data.lockToLocalRotation);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -618,7 +634,7 @@ export default function aframeDraggableComponent(aframe, componentName = COMPONE
|
|||
* Use to continue or add any dynamic or background behavior such as events.
|
||||
*/
|
||||
play() {
|
||||
didMount(this, THREE, componentName);
|
||||
didMount(this, THREE, componentName, this.data.lockToLocalRotation);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue