在Steam上有一个名为Dota 2的游戏。他们的“纸牌”部分显示了您扮演的角色。当您将鼠标悬停在卡片上时,会有一个非常酷的动画。卡会抬起并朝鼠标指针旋转。
附有图片。红点表示鼠标悬停的位置:
当前,我在这里有一个基本版本:https://codepen.io/riza-khan/pen/mdyvEeg,但是动画无法正常工作。
如果在Stackoverflow上不允许Codepen链接,我还将在此问题的末尾发布代码。有些代码是多余的,但我保留在其中以获取更多见解。
const container = document.querySelector('.container')
const card = document.querySelector('.card')
let x = document.querySelector('.x-axis')
let y = document.querySelector('.y-axis')
container.addEventListener('mousemove', (e) => {
let xCoords = e.offsetX
let yCoords = e.offsetY
x.innerHTML = `xCoords:${xCoords}`
y.innerHTML = `yCoords:${yCoords}`
card.style.transform = `rotateY(${yCoords}deg) rotateX(${xCoords}deg) scale(1.1)`
})
container.addEventListener('mouseout', (e) => {
card.style.transform = `rotateY(0deg) rotateX(0deg) scale(1)`
})
container.addEventListener('click', (e) => {
console.log(e)
})
body {
display: flex;
height: 90vh;
background: grey;
}
.x-axis,
.y-axis {
position: absolute;
}
.y-axis {
left:100px;
}
.container {
margin: auto;
}
.card {
height: 500px;
width: 300px;
border-radius: 10px;
overflow: hidden;
transition: all 1s ease;
box-shadow: 10px 8px 20px -20px black;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.container:hover {
.card {
transform-style: preserve-3d;
}
}
<p class="x-axis"></p>
<p class="y-axis"></p>
<div class="container">
<div class="card">
<img src="https://vignette.wikia.nocookie.net/wowwiki/images/d/d9/Illidan.png/revision/latest?cb=20140503134345" alt="">
</div>
</div>
这就是您要寻找的。要使对象具有3D感觉,必须使用CSS属性perspective
。这是一个工作示例(也可以在CodePen上找到):
const container = document.querySelector('.container')
const card = document.querySelector('.card')
const output = document.querySelector('.output')
let x = document.querySelector('.x-axis')
let y = document.querySelector('.y-axis')
container.addEventListener('mousemove', (e) => {
let xOffset = e.offsetX
let yOffset = e.offsetY
let cardHeight = card.clientHeight
let cardWidth = card.clientWidth
let heightCenter = Math.round(cardHeight / 2)
let widthCenter = Math.round(cardWidth / 2)
let rotateBaseValue = 20
let rotateXValue = (yOffset - heightCenter) / heightCenter * rotateBaseValue
let rotateYValue = (widthCenter - xOffset) / widthCenter * rotateBaseValue
card.style.transform = `scale(1.1) rotateX(${rotateXValue}deg) rotateY(${rotateYValue}deg)`
})
container.addEventListener('mouseout', (e) => {
card.style.transform = ''
})
html,
body {
margin: 0;
padding: 0;
height: 100%;
width: 100vw;
overflow: hidden;
}
body {
display: flex;
background: url(https://pbs.twimg.com/media/DySLFjlV4AEWf_F.jpg) no-repeat;
background-position: center bottom;
background-size: cover;
}
.container {
margin: auto;
perspective: 1000px;
}
.card {
height: 25vw;
width: 15vw;
border-radius: 10px;
overflow: hidden;
transition: all .25s linear;
}
.card img {
width: 100%;
height: 100%;
object-fit: cover;
}
.container:hover .card {
box-shadow: 10px 30px 50px -6px black;
}
<div class="container">
<div class="card">
<img src="https://66.media.tumblr.com/baf4a8fec55a6cb6fd7b18a7855998e4/tumblr_ply7xcI7pl1sjt61g_540.png" alt="Moonlight Cookie's Alluring Crescent Moon Costume">
</div>
</div>
编辑
根据要求,我将解释如何获得rotateXValue
和rotateYValue
的公式。
在开始之前,您需要知道rotateX
和rotateY
的作用。 rotateX
在水平轴(x轴)上旋转项目,rotateX
在垂直轴(y轴)上旋转项目。 rotateY
和rotateY
均为正值表示它们的移动是顺时针方向;负值表示它们的移动是逆时针。
尝试举起一张纸。您会注意到,如果您在x轴和y轴上逆时针旋转纸张一点(无关紧要多少度),您会发现纸张看起来就像在上悬停时一样卡的右上角。在x轴和y轴上顺时针方向尝试时,您会看到纸张像在卡的左下角悬停时一样指向您。尝试不同旋转方向的所有四个组合。
完成上述实验后,您可以很快得出结论:
rotateX
逆时针,rotateY
顺时针rotateX
和rotateY
逆时针rotateX
和rotateY
顺时针rotateX
顺时针和rotateY
逆时针假设最大旋转角度为15度。在x轴上,值的范围是15度到-15度(从左到右)。在y轴上,值的范围是-15度到15度(从上到下)。当您将鼠标悬停在卡的中间时,该卡不会旋转。计算y轴。值为0度时为中心。只需将当前y偏移量与中心偏移量相减即可,您将获得到中心偏移量的距离。通过除以中心偏移值将其转换为相对于中心偏移的分数。将分数值乘以最大度数即可旋转多少度。对x轴执行相同操作(在这种情况下,您需要反转减法,因为该值的范围是从正到负)。
P.S .:这个非常有趣。谢谢你的想法!