Faces following the mouse
This is an old experiment I did where I had my face follow the mouse around the browser document. Originally I wrote it using jQuery, but I've updated it to vanilla js. Source available on Github. You can access it on its own here: Physiognomy - A JS experiment.
Step one is to create an image with the nine different head positions:
Next create a function to take the mouse position and image position which will then be fed to another function which calculates which image to show. imagew
and imageh
are the size of the final element, in other words should be a third of the height and width
function changeFace(mousex, mousey, face_id){
var face = document.querySelector(face_id)
var imagew = 160;
var imageh = 160;
var facepos = { // image position
top: face.offsetTop,
left: face.offsetLeft
};
face.style.backgroundPosition = calucateBp(imagew, imageh, mousex, mousey, facepos);
}
Next create a function to calculate which the CSS background-position
and return it. This looks complicated but should be self explanatory. Each if statement tests where the mouse is relative to the element and sets the background-position
accordingly.
function calucateBp(imagew, imageh, mousex, mousey, facepos){
// TOP LEFT
if(mousex < facepos.left && mousey < facepos.top){
return '0px 0px';
}
// TOP
if((facepos.left + imagew) > mousex && mousex > facepos.left && mousey < facepos.top){
return '-'+ imagew +'px 0px';
}
// TOP RIGHT
if(mousex > (facepos.left + imagew) && mousey < facepos.top){
return '-'+ (2 * imagew) +'px 0px';
}
// LEFT
if(mousex < facepos.left && mousey < (facepos.top + imageh) && mousey > facepos.top){
return '0px -'+ imageh +'px';
}
// FRONT
if((facepos.left + imagew) > mousex && mousex > facepos.left && mousey < (facepos.top + imageh) && mousey > facepos.top){
return '-'+ imagew +'px -'+ imageh +'px'
}
// RIGHT
if(mousex > (facepos.left + imagew) && mousey < (facepos.top + imageh) && mousey > facepos.top){
return '-'+ (2 * imagew) +'px -'+ imageh +'px';
}
// BOTTOM LEFT
if(mousex < facepos.left && mousey > (facepos.top + imageh)){
return '0px -'+ (2 * imageh) +'px';
}
// BOTTOM
if((facepos.left + imagew) > mousex && mousex > facepos.left && mousey > (facepos.top + imageh)){
return '-'+ imagew +'px -'+ (2 * imageh) +'px';
}
// BOTTOM RIGHT
if(mousex > (facepos.left + imagew) && mousey > (facepos.top + imageh)){
return '-'+ (2 * imagew) +'px -'+ (2 * imageh) +'px';
}
}
To make it all work create an event listener for onmousemove
passing in the x and y coordinates of the mouse and the ID of the element to apply.
document.addEventListener('mousemove', (e) => {
changeFace(e.pageX, e.pageY, '#jerry');
changeFace(e.pageX, e.pageY, '#george');
changeFace(e.pageX, e.pageY, '#elaine');
changeFace(e.pageX, e.pageY, '#kramer');
});
Note .offsetTop
and .offsetLeft
return the offset relative to the parent element, not the document. Some extra maths are involved to allow for this if the element isn't at the root of the DOM.