[使用CSS和Javascript的3D动画

问题描述 投票:1回答:1

在Steam上有一个名为Dota 2的游戏。他们的“纸牌”部分显示了您扮演的角色。当您将鼠标悬停在卡片上时,会有一个非常酷的动画。卡会抬起并朝鼠标指针旋转。

附有图片。红点表示鼠标悬停的位置:

左下:enter image description here

中心:enter image description here

左中心:enter image description here

当前,我在这里有一个基本版本: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>
javascript html css 3d css-animations
1个回答
1
投票

这就是您要寻找的。要使对象具有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>

编辑

根据要求,我将解释如何获得rotateXValuerotateYValue的公式。

在开始之前,您需要知道rotateXrotateY的作用。 rotateX在水平轴(x轴)上旋转项目,rotateX在垂直轴(y轴)上旋转项目。 rotateYrotateY均为正值表示它们的移动是顺时针方向;负值表示它们的移动是逆时针。

尝试举起一张纸。您会注意到,如果您在x轴和y轴上逆时针旋转纸张一点(无关紧要多少度),您会发现纸张看起来就像在上悬停时一样卡的右上角。在x轴和y轴上顺时针方向尝试时,您会看到纸张像在卡的左下角悬停时一样指向您。尝试不同旋转方向的所有四个组合。

完成上述实验后,您可以很快得出结论:

  • [左上角:rotateX逆时针,rotateY顺时针
  • 右上角:rotateXrotateY逆时针
  • [左下角:rotateXrotateY顺时针
  • 右下角:rotateX顺时针和rotateY逆时针

假设最大旋转角度为15度。在x轴上,值的范围是15度到-15度(从左到右)。在y轴上,值的范围是-15度到15度(从上到下)。当您将鼠标悬停在卡的中间时,该卡不会旋转。计算y轴。值为0度时为中心。只需将当前y偏移量与中心偏移量相减即可,您将获得到中心偏移量的距离。通过除以中心偏移值将其转换为相对于中心偏移的分数。将分数值乘以最大度数即可旋转多少度。对x轴执行相同操作(在这种情况下,您需要反转减法,因为该值的范围是从正到负)。

P.S .:这个非常有趣。谢谢你的想法!

© www.soinside.com 2019 - 2024. All rights reserved.