Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified LICENSE
100755 → 100644
Empty file.
1 change: 1 addition & 0 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ An A-Frame component to move cursor along object's surface.
| -------- | ----------- | ------------- |
| target | selector(#id) of a cursor | null |
| offset | distance cursor hovers over intersection point | 0.05 (meters, or 5cm) |
| interval | minimum amount of time between cursor position updates | 0 (ms) |

## Usage

Expand Down
Empty file modified dist/.gitkeep
100755 → 100644
Empty file.
170 changes: 94 additions & 76 deletions dist/aframe-crawling-cursor.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,82 +44,100 @@
/* 0 */
/***/ (function(module, exports) {

/* global AFRAME */

if (typeof AFRAME === 'undefined') {
throw new Error('Component attempted to register before AFRAME was available.');
}

/**
* Crawling Cursor component for A-Frame.
*/
AFRAME.registerComponent('crawling-cursor', {
dependencies: ['raycaster'],
schema: {
target: {
type: "selector"
},
offset: {
// How far above the intersection point does the cursor hover? (Default 5cm)
type: "number",
default: 0.05,
}
},

multiple: false,

init: function() {
var el = this.el;
var data = this.data;

if (data.target === null) {
var cursor = document.querySelector("a-cursor");

if (cursor === null) {
console.warn("Please put a-cursor in a document");
return;
}

data.target = cursor;
}

el.addEventListener("raycaster-intersection", function(e) {

var intersection = getNearestIntersection(e.detail.intersections);
if (!intersection) { return; }

// a matrix which represents item's movement, rotation and scale on global world
var mat = intersection.object.matrixWorld;
// remove parallel movement from the matrix
mat.setPosition(new THREE.Vector3(0, 0, 0));

// change local normal into global normal
var global_normal = intersection.face.normal.clone().applyMatrix4(mat).normalize();

// look at target coordinate = intersection coordinate + global normal vector
var lookAtTarget = new THREE.Vector3().addVectors(intersection.point, global_normal);
data.target.object3D.lookAt(lookAtTarget);

// cursor coordinate = intersection coordinate + normal vector * offset
var cursorPosition = new THREE.Vector3().addVectors(intersection.point, global_normal.multiplyScalar(data.offset));
data.target.setAttribute("position", cursorPosition);

function getNearestIntersection(intersections) {
for (var i = 0, l = intersections.length; i < l; i++) {

// ignore cursor itself to avoid flicker && ignore "ignore-ray" class
if (data.target === intersections[i].object.el || intersections[i].object.el.classList.contains("ignore-ray")) { continue; }
return intersections[i];
}
return null;
}
});

setInterval(function() {
el.components.raycaster.refreshObjects();
}, 100)
}
});
/* global AFRAME */

if (typeof AFRAME === 'undefined') {
throw new Error('Component attempted to register before AFRAME was available.');
}

/**
* Crawling Cursor component for A-Frame.
*/
AFRAME.registerComponent('crawling-cursor',
{
dependencies: ['raycaster'],
schema:
{
target: { type: "selector" },
// How far above the intersection point does the cursor hover? (Default 5cm)
offset: { type: "number", default: 0.05, },
// The minimum amount of time that must pass before the cursor may be redrawn, in ms.
interval: { type: "int", default: 0, }

},
multiple: false,
init: function()
{
// Keep track of the number of intersecting objects
this.intersecting = 0;
// Keep track of the time of the previous update
this.lastUpdate = 0;

// Init the cursor if not explicitly specified
if (this.data.target === null)
{
this.data.target = document.querySelector("a-cursor");
if (this.data.target === null)
{
console.warn("Please put a-cursor in a document");
}
}

// Function to reposition the cursor
this.positionCursor = function(intersection)
{
if (intersection !== null && intersection.face != null)
{
// a matrix which represents item's movement, rotation and scale on global world
var mat = intersection.object.matrixWorld;
// remove parallel movement from the matrix
mat.setPosition(new THREE.Vector3(0, 0, 0));

// change local normal into global normal
var global_normal = intersection.face.normal.clone().applyMatrix4(mat).normalize();

// look at target coordinate = intersection coordinate + global normal vector
var lookAtTarget = new THREE.Vector3().addVectors(intersection.point, global_normal);
this.data.target.object3D.lookAt(lookAtTarget);

// cursor coordinate = intersection coordinate + normal vector * offset
var cursorPosition = new THREE.Vector3().addVectors(intersection.point, global_normal.multiplyScalar(this.data.offset));
this.data.target.setAttribute("position", cursorPosition);
}
}

// Create event listeners to catch intersections
this.intersectListener = e =>
{
this.intersecting = this.el.components.raycaster.intersectedEls.length;
this.data.target.object3D.visible = this.intersecting > 0;
};
this.el.addEventListener("raycaster-intersection", this.intersectListener);
this.el.addEventListener("raycaster-intersection-cleared", this.intersectListener);
},
tick: function(time, delta)
{
// Only position the cursor if intersecting at least 1
if (this.intersecting > 0 && time - this.lastUpdate > this.data.interval)
{
this.lastUpdate = time;
this.positionCursor(this.el.components.raycaster.getIntersection
(
this.el
.components
.raycaster
.intersectedEls
.find(el => this.data.target !== el && !el.classList.contains("ignore-ray"))
));
}
},
remove: function ()
{
// Remove event listeners
this.el.removeEventListener("raycaster-intersection", this.intersectListener);
this.el.removeEventListener("raycaster-intersection-cleared", this.intersectListener);
}
});

/***/ })
/******/ ]);
2 changes: 1 addition & 1 deletion dist/aframe-crawling-cursor.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file modified examples/basic/index.html
100755 → 100644
Empty file.
Empty file modified examples/index.html
100755 → 100644
Empty file.
Empty file modified examples/main.js
100755 → 100644
Empty file.
Empty file modified gh-pages/basic/index.html
100755 → 100644
Empty file.
Empty file modified gh-pages/index.html
100755 → 100644
Empty file.
Empty file modified gh-pages/main.js
100755 → 100644
Empty file.
2 changes: 1 addition & 1 deletion index.js
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ AFRAME.registerComponent('crawling-cursor',
// Function to reposition the cursor
this.positionCursor = function(intersection)
{
if (intersection !== null)
if (intersection !== null && intersection.face != null)
{
// a matrix which represents item's movement, rotation and scale on global world
var mat = intersection.object.matrixWorld;
Expand Down
4 changes: 2 additions & 2 deletions package.json
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aframe-crawling-cursor",
"version": "1.0.9",
"version": "1.1.0",
"description": "A A-Frame component to move cursor along objects' surface.",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -33,7 +33,7 @@
},
"homepage": "https://github.com/jujunjun110/aframe-crawling-cursor#readme",
"devDependencies": {
"aframe": "^0.7.0",
"aframe": "^1.0.0",
"browserify": "^13.0.0",
"browserify-css": "^0.9.1",
"budo": "^8.2.2",
Expand Down
Empty file modified scripts/unboil.js
100755 → 100644
Empty file.