My foundations in Javascript aren't the strongest and I'm curious how others would go about the current challenge I've created for myself.
I'm playing around with paper.js
The following code creates this
The eye reacts to mouse events in the same way as the eyes here (learned from that code) — www.arc.id.au/XEyes.html
Here's what I have:
// Eye position center
eCntrX = 100
eCntrY = 100
var topLid = new Path()
topLid.add(new Point(eCntrX - 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY - 28))
topLid.add(new Point(eCntrX + 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY + 28))
topLid.strokeWidth = '6'
topLid.strokeColor = '#000'
topLid.closed = true
topLid.smooth()
var iris = new Path.Circle(eCntrX, eCntrY, 24)
iris.fillColor = '#6CE0FF'
iris.strokeWidth = '6'
iris.strokeColor = '#000'
var pupil = new Path.Circle(eCntrX, eCntrY, 15)
pupil.fillColor = '#000'
var glint = new Path.Circle(eCntrX, eCntrY, 5)
glint.fillColor = '#fff'
glint.position = new Point(eCntrX + 6, eCntrY - 6)
var ball = new Group([iris, pupil, glint])
function onMouseMove(event) {
// Cursor position
var csrX = event.point.x
var csrY = event.point.y
// Ball position
var ballX = ball.position.x
var ballY = ball.position.y
// Displacement
var dx = csrX - ballX
var dy = csrY - ballY
//Radius
var r = 5
//Pythagerous thereom calcs. R
var R = Math.sqrt(dx*dx+dy*dy)
x = dx*r/R
y = dy*r/R
ball.position = new Point(eCntrX + x, eCntrY + y)
// console.log('x:' + x + 'y:' + y)
}
I'm looking to fill the whole page with eyes. My end goals is to create something like this:
My question is, what is the best way to go about creating multiple eyes that are interactive.
I've been playing around with 'for', but the onMouseMove function only applies to the last Eye created.
Have also been looking at paperjs item.clone — paperjs.org/reference/item#clone
Or is it a matter of me creating unique variables for each eye?
Here's the code with the for as requested:
for(var i = 0; i < 10; i++){
// Eye position center
// 100, 300, 500, 600
eCntrX = 100 * i + 100
eCntrY = 100
var topLid = new Path()
topLid.add(new Point(eCntrX - 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY - 28))
topLid.add(new Point(eCntrX + 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY + 28))
topLid.strokeWidth = '6'
topLid.strokeColor = '#000'
topLid.closed = true
topLid.smooth()
var iris = new Path.Circle(eCntrX, eCntrY, 24)
iris.fillColor = '#6CE0FF'
iris.strokeWidth = '6'
iris.strokeColor = '#000'
var pupil = new Path.Circle(eCntrX, eCntrY, 15)
pupil.fillColor = '#000'
var glint = new Path.Circle(eCntrX, eCntrY, 5)
glint.fillColor = '#fff'
glint.position = new Point(eCntrX + 6, eCntrY - 6)
var ball = new Group([iris, pupil, glint])
}
function onMouseMove(event) {
// Cursor position
var csrX = event.point.x
var csrY = event.point.y
// Ball position
var ballX = ball.position.x
var ballY = ball.position.y
// Displacement
var dx = csrX - ballX
var dy = csrY - ballY
//Radius
var r = 5
//Pythagerous thereom calcs. R
var R = Math.sqrt(dx*dx+dy*dy)
x = dx*r/R
y = dy*r/R
ball.position = new Point(eCntrX + x, eCntrY + y)
console.log('x:' + x + 'y:' + y)
}
You need to create a variable that contains all of the eyes, then in your mousemove event loop through the elements in that variable and apply the logic to position each one in turn.
var eyeballs = [];
for (...) {
....
//var ball = new Group([iris, pupil, glint])
eyeballs.push(new Group([iris, pupil, glint]));
}
function onMouseMove(event) {
for (var i = 0, len = eyeballs.length; i < len; i++) {
var ball = eyeballs[i];
...
ball.position = new Point(eCntrX + x, eCntrY + y);
}
}
I'm not familiar with Paper.js, but I can at least provide you with ideas for how to construct a framework around it.
Basically, you need an eyeball factory. One that makes eyeball objects and throws them back at you. So you can hang them on your creepy eyeball wall.
The code sample below won't be totally functional, you'll have to plugin the specifics, but should be easy to follow.
var Eyeball = function(params){
// Eye position center
var eCntrX = params.x,
eCntrY = params.y;
var topLid = new Path()
topLid.add(new Point(eCntrX - 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY - 28))
topLid.add(new Point(eCntrX + 60, eCntrY))
topLid.add(new Point(eCntrX, eCntrY + 28))
topLid.strokeWidth = '6'
topLid.strokeColor = '#000'
topLid.closed = true
topLid.smooth()
var iris = new Path.Circle(eCntrX, eCntrY, 24)
iris.fillColor = '#6CE0FF'
iris.strokeWidth = '6'
iris.strokeColor = '#000'
var pupil = new Path.Circle(eCntrX, eCntrY, 15)
pupil.fillColor = '#000'
var glint = new Path.Circle(eCntrX, eCntrY, 5)
glint.fillColor = '#fff'
glint.position = new Point(eCntrX + 6, eCntrY - 6)
var ball = new Group([iris, pupil, glint]);
//listen for the current mouse coordinates and update
document.addEventListener('mousemove', function(event){
// Cursor position
var csrX = event.x,
csrY = event.y;
// Ball position
var ballX = ball.position.x
var ballY = ball.position.y
// Displacement
var dx = csrX - ballX
var dy = csrY - ballY
//Radius
var r = 5
//Pythagerous thereom calcs. R
var R = Math.sqrt(dx*dx+dy*dy)
x = dx*r/R
y = dy*r/R
ball.position = new Point(eCntrX + x, eCntrY + y)
},false);
}
var eye = new Eyeball({x:100,y:100}); //if you want/need to pass in parameters for new Eyeballs like color or shape or whatever, you can define them in this object then access them in 'params' inside the Eyeball constructor.
To make many eyeballs for your eyeball wall:
for(var i=0; i<100; i++){
var eye = new Eyeball({x: Math.floor(Math.random()*300), y: Math.floor(Math.random()*300)});
}
In your code, the onMouseMove function isn't being called anywhere. I don't know if this is a name called by Paper.js, or if there is more code you forgot to include.
If you can answer that last part for me, I'll try to update this with a complete answer.
Update
Ok, so lets take the next step and add ears to your eyeballs. This is just getting gross, by the way.
The idea is that each eyeball is an object that should be able to listen for an event.
The way paper.js does it would require you to loop through all of your eyeballs on each mouseMove event and update the positioning. This will potentially lock the user interface during each update (imagine thousands of eyeballs!) because javascript is single threaded.
What we want to do is have each eyeball object listen directly for the 'mousemove' event, from which you can get the x and y properties of the current mouse position. We do this by adding an event listener inside each eyeball. Since each event will execute within the context of its instance of Eyeball, the 'ball' variable will be unique for each one. See the updated sample code and let me know if this all works. I'd love to see a sample page with a hundred eyeballs tracking my mouse. I think...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With