Tilt on hover image
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
3
down vote
favorite
I am asking for a review of this code to see if I am following common best practices or if there is a better way to accomplish the goal set for this code.
My purpose was to create an image that would CSS3 rotateY()
to your mouse's position over it with as close to a semantic approach as I could get and scalable to any size.
My approach was a simple Div->Img tag structure, the div's size is indirectly the image's size due to the design limitation of listeners in JS being attached to the div (this is so the rotation's effect on size doesn't jitter the image around).
Anyway, if I could get some critique I would be very appreciative. Thank you for reading!
Live Version
HTML index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hover Card</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="hover-card">
<img src="images/me.jpg" alt="A picture of Torben Leif.">
</div>
</div>
<script src="scripts/main.js"></script>
</body>
</html>
css/style.css
.container
margin: calc(50vh - 125px) auto;
width: 250px;
height: 250px;
.hover-card
width: 230px;
height: 230px;
.hover-card img
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
object-fit: cover;
object-position: center 20%; /* Specific To Avatar Image */
transition: .2s linear;
transform-style: preserve-3d;
transform: perspective(600px) rotateY(var(--js-hover-rotate-val));
scripts/main.js
var card = document.querySelector('.hover-card');
var img = document.querySelector('.hover-card img');
var hoverComplete = true; // Used For Smooth Transitions While Rotating.
var degrees = 0; // External For Freeze Fix.
img.addEventListener('transitionend', (e) =>
if(e.propertyName == 'transform')
hoverComplete = true;
);
card.addEventListener('mousemove', (e) =>
if(hoverComplete)
let newDegrees = Math.floor((1 - (e.pageX - card.getBoundingClientRect().left) / card.offsetWidth) * 90 - 45) * -1;
if(newDegrees !== degrees) // Freeze Fix
degrees = newDegrees;
img.style.setProperty('--js-hover-rotate-val', degrees + 'deg');
hoverComplete = false;
);
card.addEventListener('mouseleave', (e) =>
img.style.setProperty('--js-hover-rotate-val', '0deg')
hoverComplete = false;
);
javascript css image html5
add a comment |Â
up vote
3
down vote
favorite
I am asking for a review of this code to see if I am following common best practices or if there is a better way to accomplish the goal set for this code.
My purpose was to create an image that would CSS3 rotateY()
to your mouse's position over it with as close to a semantic approach as I could get and scalable to any size.
My approach was a simple Div->Img tag structure, the div's size is indirectly the image's size due to the design limitation of listeners in JS being attached to the div (this is so the rotation's effect on size doesn't jitter the image around).
Anyway, if I could get some critique I would be very appreciative. Thank you for reading!
Live Version
HTML index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hover Card</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="hover-card">
<img src="images/me.jpg" alt="A picture of Torben Leif.">
</div>
</div>
<script src="scripts/main.js"></script>
</body>
</html>
css/style.css
.container
margin: calc(50vh - 125px) auto;
width: 250px;
height: 250px;
.hover-card
width: 230px;
height: 230px;
.hover-card img
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
object-fit: cover;
object-position: center 20%; /* Specific To Avatar Image */
transition: .2s linear;
transform-style: preserve-3d;
transform: perspective(600px) rotateY(var(--js-hover-rotate-val));
scripts/main.js
var card = document.querySelector('.hover-card');
var img = document.querySelector('.hover-card img');
var hoverComplete = true; // Used For Smooth Transitions While Rotating.
var degrees = 0; // External For Freeze Fix.
img.addEventListener('transitionend', (e) =>
if(e.propertyName == 'transform')
hoverComplete = true;
);
card.addEventListener('mousemove', (e) =>
if(hoverComplete)
let newDegrees = Math.floor((1 - (e.pageX - card.getBoundingClientRect().left) / card.offsetWidth) * 90 - 45) * -1;
if(newDegrees !== degrees) // Freeze Fix
degrees = newDegrees;
img.style.setProperty('--js-hover-rotate-val', degrees + 'deg');
hoverComplete = false;
);
card.addEventListener('mouseleave', (e) =>
img.style.setProperty('--js-hover-rotate-val', '0deg')
hoverComplete = false;
);
javascript css image html5
add a comment |Â
up vote
3
down vote
favorite
up vote
3
down vote
favorite
I am asking for a review of this code to see if I am following common best practices or if there is a better way to accomplish the goal set for this code.
My purpose was to create an image that would CSS3 rotateY()
to your mouse's position over it with as close to a semantic approach as I could get and scalable to any size.
My approach was a simple Div->Img tag structure, the div's size is indirectly the image's size due to the design limitation of listeners in JS being attached to the div (this is so the rotation's effect on size doesn't jitter the image around).
Anyway, if I could get some critique I would be very appreciative. Thank you for reading!
Live Version
HTML index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hover Card</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="hover-card">
<img src="images/me.jpg" alt="A picture of Torben Leif.">
</div>
</div>
<script src="scripts/main.js"></script>
</body>
</html>
css/style.css
.container
margin: calc(50vh - 125px) auto;
width: 250px;
height: 250px;
.hover-card
width: 230px;
height: 230px;
.hover-card img
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
object-fit: cover;
object-position: center 20%; /* Specific To Avatar Image */
transition: .2s linear;
transform-style: preserve-3d;
transform: perspective(600px) rotateY(var(--js-hover-rotate-val));
scripts/main.js
var card = document.querySelector('.hover-card');
var img = document.querySelector('.hover-card img');
var hoverComplete = true; // Used For Smooth Transitions While Rotating.
var degrees = 0; // External For Freeze Fix.
img.addEventListener('transitionend', (e) =>
if(e.propertyName == 'transform')
hoverComplete = true;
);
card.addEventListener('mousemove', (e) =>
if(hoverComplete)
let newDegrees = Math.floor((1 - (e.pageX - card.getBoundingClientRect().left) / card.offsetWidth) * 90 - 45) * -1;
if(newDegrees !== degrees) // Freeze Fix
degrees = newDegrees;
img.style.setProperty('--js-hover-rotate-val', degrees + 'deg');
hoverComplete = false;
);
card.addEventListener('mouseleave', (e) =>
img.style.setProperty('--js-hover-rotate-val', '0deg')
hoverComplete = false;
);
javascript css image html5
I am asking for a review of this code to see if I am following common best practices or if there is a better way to accomplish the goal set for this code.
My purpose was to create an image that would CSS3 rotateY()
to your mouse's position over it with as close to a semantic approach as I could get and scalable to any size.
My approach was a simple Div->Img tag structure, the div's size is indirectly the image's size due to the design limitation of listeners in JS being attached to the div (this is so the rotation's effect on size doesn't jitter the image around).
Anyway, if I could get some critique I would be very appreciative. Thank you for reading!
Live Version
HTML index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hover Card</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="container">
<div class="hover-card">
<img src="images/me.jpg" alt="A picture of Torben Leif.">
</div>
</div>
<script src="scripts/main.js"></script>
</body>
</html>
css/style.css
.container
margin: calc(50vh - 125px) auto;
width: 250px;
height: 250px;
.hover-card
width: 230px;
height: 230px;
.hover-card img
width: 100%;
height: 100%;
border-radius: 20px;
overflow: hidden;
object-fit: cover;
object-position: center 20%; /* Specific To Avatar Image */
transition: .2s linear;
transform-style: preserve-3d;
transform: perspective(600px) rotateY(var(--js-hover-rotate-val));
scripts/main.js
var card = document.querySelector('.hover-card');
var img = document.querySelector('.hover-card img');
var hoverComplete = true; // Used For Smooth Transitions While Rotating.
var degrees = 0; // External For Freeze Fix.
img.addEventListener('transitionend', (e) =>
if(e.propertyName == 'transform')
hoverComplete = true;
);
card.addEventListener('mousemove', (e) =>
if(hoverComplete)
let newDegrees = Math.floor((1 - (e.pageX - card.getBoundingClientRect().left) / card.offsetWidth) * 90 - 45) * -1;
if(newDegrees !== degrees) // Freeze Fix
degrees = newDegrees;
img.style.setProperty('--js-hover-rotate-val', degrees + 'deg');
hoverComplete = false;
);
card.addEventListener('mouseleave', (e) =>
img.style.setProperty('--js-hover-rotate-val', '0deg')
hoverComplete = false;
);
javascript css image html5
edited Feb 6 at 7:47
Billal BEGUERADJ
1
1
asked Feb 6 at 6:54
TorbenLeif
183
183
add a comment |Â
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
2
down vote
accepted
I find the calculation of tilt a bit complicated. If you know maximum tilt in degrees that shall happen on the left and right edges, you could declare it and a calculation function as
const MAX_INCLINE = 28; // <- just a guess
const shift = (w, x, limit = MAX_INCLINE) => (x / w * 2 - 1) * limit;
Next, Element#getBoundingClientRect
, in my opinion, is unnecessary, because you receive all the necessary information in the instance of Event
passed to your event listener function:
event.target.width
is the width of target element that listens to mouse event, meaning the image in your case, andevent.offsetX
is the position of mouse on X-axis relative to the element, meaning it's closer to 0 when the cursor is closer to the left edge, and closer to X when the cursor is closer to the right edge, where X is width of the element (image).
Considering this, the event listener function would look as simple as
(event) =>
const width = event.target;
const offsetX = event;
image.style.setProperty('--js-hover-rotate-val', `$shift(width, offsetX)deg`);
;
A codepen with the final code might be also useful.
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
I find the calculation of tilt a bit complicated. If you know maximum tilt in degrees that shall happen on the left and right edges, you could declare it and a calculation function as
const MAX_INCLINE = 28; // <- just a guess
const shift = (w, x, limit = MAX_INCLINE) => (x / w * 2 - 1) * limit;
Next, Element#getBoundingClientRect
, in my opinion, is unnecessary, because you receive all the necessary information in the instance of Event
passed to your event listener function:
event.target.width
is the width of target element that listens to mouse event, meaning the image in your case, andevent.offsetX
is the position of mouse on X-axis relative to the element, meaning it's closer to 0 when the cursor is closer to the left edge, and closer to X when the cursor is closer to the right edge, where X is width of the element (image).
Considering this, the event listener function would look as simple as
(event) =>
const width = event.target;
const offsetX = event;
image.style.setProperty('--js-hover-rotate-val', `$shift(width, offsetX)deg`);
;
A codepen with the final code might be also useful.
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
add a comment |Â
up vote
2
down vote
accepted
I find the calculation of tilt a bit complicated. If you know maximum tilt in degrees that shall happen on the left and right edges, you could declare it and a calculation function as
const MAX_INCLINE = 28; // <- just a guess
const shift = (w, x, limit = MAX_INCLINE) => (x / w * 2 - 1) * limit;
Next, Element#getBoundingClientRect
, in my opinion, is unnecessary, because you receive all the necessary information in the instance of Event
passed to your event listener function:
event.target.width
is the width of target element that listens to mouse event, meaning the image in your case, andevent.offsetX
is the position of mouse on X-axis relative to the element, meaning it's closer to 0 when the cursor is closer to the left edge, and closer to X when the cursor is closer to the right edge, where X is width of the element (image).
Considering this, the event listener function would look as simple as
(event) =>
const width = event.target;
const offsetX = event;
image.style.setProperty('--js-hover-rotate-val', `$shift(width, offsetX)deg`);
;
A codepen with the final code might be also useful.
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
add a comment |Â
up vote
2
down vote
accepted
up vote
2
down vote
accepted
I find the calculation of tilt a bit complicated. If you know maximum tilt in degrees that shall happen on the left and right edges, you could declare it and a calculation function as
const MAX_INCLINE = 28; // <- just a guess
const shift = (w, x, limit = MAX_INCLINE) => (x / w * 2 - 1) * limit;
Next, Element#getBoundingClientRect
, in my opinion, is unnecessary, because you receive all the necessary information in the instance of Event
passed to your event listener function:
event.target.width
is the width of target element that listens to mouse event, meaning the image in your case, andevent.offsetX
is the position of mouse on X-axis relative to the element, meaning it's closer to 0 when the cursor is closer to the left edge, and closer to X when the cursor is closer to the right edge, where X is width of the element (image).
Considering this, the event listener function would look as simple as
(event) =>
const width = event.target;
const offsetX = event;
image.style.setProperty('--js-hover-rotate-val', `$shift(width, offsetX)deg`);
;
A codepen with the final code might be also useful.
I find the calculation of tilt a bit complicated. If you know maximum tilt in degrees that shall happen on the left and right edges, you could declare it and a calculation function as
const MAX_INCLINE = 28; // <- just a guess
const shift = (w, x, limit = MAX_INCLINE) => (x / w * 2 - 1) * limit;
Next, Element#getBoundingClientRect
, in my opinion, is unnecessary, because you receive all the necessary information in the instance of Event
passed to your event listener function:
event.target.width
is the width of target element that listens to mouse event, meaning the image in your case, andevent.offsetX
is the position of mouse on X-axis relative to the element, meaning it's closer to 0 when the cursor is closer to the left edge, and closer to X when the cursor is closer to the right edge, where X is width of the element (image).
Considering this, the event listener function would look as simple as
(event) =>
const width = event.target;
const offsetX = event;
image.style.setProperty('--js-hover-rotate-val', `$shift(width, offsetX)deg`);
;
A codepen with the final code might be also useful.
answered Feb 6 at 15:23
rm-
306311
306311
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
add a comment |Â
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
1
1
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
Thank you for your reply and analysis, I greatly appreciate the feedback. Your shift function is undoubtedly more elegant than mine, I was also unaware offsetX worked in this manner. I'll take your advice into consideration in the future.
â TorbenLeif
Feb 6 at 20:02
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186890%2ftilt-on-hover-image%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password