Creating unique variables
Asked Answered
W

2

6

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 screenshot

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:

End result

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)

}
Waiter answered 13/10, 2012 at 23:57 Comment(5)
the most important part is missing.. post your for loop and eye creation.Exurb
You'll probably need a while loop for the creation of the eyes, and a for loop onMouseMove to update all the eyes.Leisaleiser
@KarolyHorvath — I've added the 'for' loop I was trying out. Was just testing it on creating a few. The problem is that only the last Eye created is interactive.Waiter
A page full of disembodied eyes. Not creepy at all.Viola
What about instead binding a mousemove event for every eye you bind it to the document and update every eye accordingly?Pappus
S
4

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);
    }
}
Steelworker answered 14/10, 2012 at 0:27 Comment(2)
Thanks Kevin. The first for works well. But onMouseMove it appears each loop is positioning the eyeball in the same place — ScreenshotWaiter
It's hard to say why that would be happening without seeing the updated code, could you post it?Steelworker
V
2

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...

Viola answered 14/10, 2012 at 0:36 Comment(2)
Thanks @Geuis. Appreciate it. 'Eyeball factory'. Makes a lot of sense think of it like this :) So onMouseMove is a paper.js tool event, here's some more info here: paperjs.org/reference/tool#onmousemoveWaiter
"Basically, you need an eyeball factory". Sounds like someone's well on the way to becoming a mad scientist :PAwful

© 2022 - 2024 — McMap. All rights reserved.