How do I set the borders in which I want my children to move when following the cursor on a movement?

144 views Asked by At

I am making a project in which I have to add some googly eyes to a face in jQuery. I have the design in CSS and my divs in HTML I now want to add the mouse movement with Jquery. I found a very helpful answer on this site and I managed to make the pupils follow the cursor but they move all over the screen not just in the eyeballs. I searched for codes that have the same result but they are either javascript codes or the movement is made with hover in CSS. To me that looked complicated so I thought I could just ask here if anyone knows how to define the area in which I want my pupils to move. In my case I want pupilsRight/Left to move inside divs :#leftEye respectively #rightEye not all over the screen.

$(document).ready(function() {

                var leftPupil = $("<div><div>");

                $("#leftye").append(leftPupil);

                var rightPupil = $("#rightEye div div");
                $("#rightEye").append(rightPupil);
                rightPupil.show();

                $(window).on('mousemove', function(e){
                pupilleLinks.css({
                left:  e.pageX,
                top:   e.pageY
                });
                pupilleRechts.css({
                left:  e.pageX,
                top:   e.pageY
              });
           });
        });

        </script>
</head>
<b
    <div style="float:left;font-weight:bold;">Deine Spielwiese:</div>

    <div id="face">
        <div id="leftEye">Left Eye</div>
        <div id="rightEye" >Right Eye<div>
                <span></span>
                <div style="display:none;background-color:#000;width:20px;height:20px;border-radius:10px;position:absolute;bottom:10px;lef:10px;"></div>
            </div>
        </div>
        <div style="display:none;border:1px solid green;width:35px;height:35px;margin-top:70px; display: inline-block; border-radius:35px;background-color:#DFD;"></div

I did not copy all CSS part because it was pretty long. If someone has an idea how i could define the wanted movement area that would be great.

2

There are 2 answers

4
Okku On BEST ANSWER

Your code didn't work at all, so I first misunderstood what you meant. I couldn't pick up much from your broken code so I quickly rewrote it.

Markup for each eye:

<div class="eye">
    <div class="roller">
        <div class="pupil"></div>
    </div>
</div>

What you should do is:

  • calculate the distance from your mouse to your eye's center
  • limit the distance to the radius of your eye
  • calculate the angle of the line that your mouse and the center of the eye would form
  • set .pupil to the right distance from the center and rotate the .roller element

Here's the fiddle with some more detailed explanation: https://jsfiddle.net/ilpo/zyx0ag9z/1/

Also, it works with any number of eyes at any size: https://jsfiddle.net/ilpo/zyx0ag9z/3/ And you'll only have to change the eye's height and width - the pupils' sizes and everything else scale automatically!

0
Krzysiu On

Years ago I made a jQuery plugin for googly eyes (http://my.krzysiu.net/googl/ - demo and manual). As the code isn't that long, I'm pasting it here. I never really finished it, so it have some little bugs, but it seems to work quite well and it incorporates a few tricks to make the movement looks real (mostly delay and non-linear animation). You can use it or incorporate the basic idea into your code. The idea is:

figures for idea of googly eyes

  1. We need polar coordinates (angle and distance) for the placement and CSS uses Cartesian (X/Y or top/left).
  2. We know Cartesian coordinates of the centre of the eye and the mouse pointer. We use trigonometry to convert Cartesian=>polar.
  3. We also know that angle between centre of the eye and centre of the iris (α1) must be the same as between centre of the eye and centre of pointer (fig. 1).
  4. We have angle, now we need distance. It can't be lower than 0 (middle of the eye), but it can't be higher than radius of the eye minus the eye of the iris (because if it would be greater, iris would be outside eye; see fig. 2). If our distance eye<->pointer is lesser than our r1-r2 (i.e. mouse is hovering above eye) we use that distance. If it's higher (mouse outside eye), we set it up to our limit.
  5. As we have angle and distance from centre of the eye to centre of the iris, we can convert it back to Cartesian coordinates, so we can set up the position of the iris. These will be relative coordinates, so either use relative CSS positioning or use absolute - xfinal=x1+x2 where x1 is our result and x2 is absolute position of the centre of the eye.

I keep repeating "centre" because we want iris inside eye and using corners would give us wrong visual interpretation.

(function ($) {

$.fn.googly = function(settings) {
    var conf = $.extend({
        container: false,
        trigger: false,
        x: 0,
        y: 0,
        distance: 10,
        minDelay: 250,
        moveTime: 200,
        moveType: 'swing',
        callbackOnResize: true
    }, settings);
    
    var obj = $(this);
    if (conf.container === false) conf.container = obj.parent();
    if (conf.trigger === false) conf.trigger = conf.container;      
    var box = conf.container;
    var x = 0;
    var y = 0;
    
    var setSize = function() {
        x = -(obj.outerWidth(false)/2);
        y = -(obj.outerHeight(false)/2);
        if (typeof(conf.x) == 'function') x += conf.x.call(); else x += conf.x;
        if (typeof(conf.y) == 'function') y += conf.y.call(); else y += conf.y; 
        obj.css({left: x, bottom: y});          
    }
    
    
    
    setSize.call();
    
    var canAnimate = true;
    
    if ((typeof(conf.x) == 'function' || typeof(conf.y) == 'function') && conf.callbackOnResize) {          
        $(window).resize(function() {
            setSize.call();
        });         
        
    }   
    conf.trigger.mousemove(function(e) {
        if (!canAnimate || obj.is(':animated')) return;
        
        var x2 = e.pageX - box.offset().left - (obj.outerWidth(false)/2);
        var y2 = box.offset().top + box.height() - e.pageY - (obj.outerHeight(false)/2);
        var angle = Math.atan(Math.abs(y2 - y) / Math.abs(x2 - x));
        var dX3 = conf.distance * Math.cos(angle);
        var dY3 = conf.distance * Math.sin(angle);
        var mX = x > x2 ? x-dX3 : x+dX3;
        var mY = y > y2 ? y-dY3 : y+dY3;
        
        obj.animate({left:mX, bottom: mY}, conf.moveTime, conf.moveType);
        window.setTimeout(function() {canAnimate = true;}, conf.minDelay);
        canAnimate = false;
    });
    return this;        
};  
}(jQuery));