이 기사에서는 CSS를 사용하여 마우스를 따라가는 흥미로운 3D 회전 효과를 구현하고 상호 작용을 더욱 생생하게 만드는 방법을 소개합니다. 모든 사람에게 도움이 되기를 바랍니다.
오늘 친구 그룹이 아래와 같이 마우스 팔로우 상호작용 효과를 구현하는 방법에 대해 질문했습니다.
간단한 분석에 따르면 이 상호작용 효과는 주로 두 개의 코어로 구성됩니다.
With CSS 3D 기능이 없는 경우
요소의 회전은 마우스의 움직임과 결합되어야 합니다
이 문서에서는 순수 CSS를 사용하여 유사한 대화형 효과를 얻는 방법과 JavaScript를 사용하여 다음을 수행하는 방법을 설명합니다. 위의 효과를 빠르게 복원하려면 마우스 이벤트를 바인딩하세요. [추천 학습: css 비디오 튜토리얼]
JavaScript 없이 CSS만으로 유사한 3D 회전 효과를 얻는 방법은 무엇입니까?
여기에서는 양 및 음의 회전 취소 또는 양 및 음의 회전 취소라는 작은 트릭이 사용됩니다. 글쎄요, 이름이 참 이상하네요. 마치 수학적 개념처럼 보이네요.
애니메이션에서 회전은 매우 일반적으로 사용되는 속성입니다.
{ transform: rotate(90deg); }
서로 다른 레벨의 요소에 서로 다른 방향으로 회전을 추가하면 어떻게 될까요?
먼저 다음과 같은 HTML 구조 레이어가 있다고 가정합니다.
<div> <div> <div>正负旋转相消3D动画</div> </div> </div>
스타일은 다음과 같습니다.
.content
가 주요 콘텐츠입니다. 상위 요소 .rotate
가 정방향 선형 360° 회전을 수행하고 가장 바깥쪽 상위 요소 .reverseRotate
가 역방향 선형 360° 회전을 수행하는 경우 효과는 어떻게 될까요? .content
内是我们的主要内容,好了,现在想象一下,如果父元素 .rotate
进行正向 linear 360° 旋转,最外层的父级元素 .reverseRotate
进行反向 linear 360° 旋转,效果会是啥样?
CSS 代码如下:
.rotate { animation: rotate 5s linear infinite; } .reverseRotate { animation: reverseRotate 5s linear infinite; } @keyframes rotate { 100% { transform: rotate(360deg); } } @keyframes reverseRotate { 100% { transform: rotate(-360deg); } }
我们可以得到这样一种动画(注意,下图是 GIF 不是 PNG):
神奇!因为一正一反的旋转,且缓动函数一样,所以整个 .content
看上去依然是静止的!注意,这里整个 .content
静止的非常重要。
有读者看到这里就要骂人了,作者你个智障,静止了不就没动画了吗?哪来的动画技巧?
别急!虽然看上去是静止的,但是其实祖先两个元素都是在旋转的!这会看上去风平浪静的效果底下其实是暗流涌动。用开发者工具选取最外层祖先元素是这样的:
既然如此,我们继续思考,如果我在其中旋转的一个父元素上,添加一些别的动画会是什么效果?想想就很刺激。
首先,我们先给这几个元素添加 CSS 3D 转换:
div { transform-style: preserve-3d; perspective: 100px; }
接着,尝试修改上面的旋转动画,在内层旋转上额外添加一个 rotateX:
@keyframes rotate { 0% { transform: rotateX(0deg) rotateZ(0deg); } 50% { transform: rotateX(40deg) rotateZ(180deg); } 100% { transform: rotateX(0deg) rotateZ(360deg); } }
效果如下:
Wow,这里需要好好理解一下。由于内容 .content
层是静止的但其实外层两个图层都在旋转,通过设置额外的 rotateX(40deg)
,相当于叠加多了一个动画,由于正反旋转抵消了,所有整个动画只能看到旋转的 rotateX(40deg)
<div></div>
.content
는 여전히 정지된 것처럼 보입니다! 여기에서는 전체 .content
가 정적이라는 것이 매우 중요합니다. 이거 보면 욕할 것 같은 작가님, 멈추면 애니메이션이 안 나오는 거 아닌가요? 애니메이션 기술은 어디서 얻었나요? 걱정하지 마세요! 정지해 있는 것처럼 보이지만 조상의 두 요소는 실제로 회전하고 있습니다! 이는 차분한 효과처럼 보일 수 있지만 그 밑에는 실제로 저류가 있습니다. 개발자 도구를 사용하여 가장 바깥쪽 조상 요소를 선택하는 방법은 다음과 같습니다.
먼저 다음 요소에 CSS 3D 변환을 추가해 보겠습니다.
body { width: 100vw; height: 100vh; transform-style: preserve-3d; perspective: 500px; } div { width: 200px; height: 200px; background: #000; transform-style: preserve-3d; }
div { transform: rotateX(15deg) rotateY(30deg); }
효과는 다음과 같습니다.
와우, 이건 주의 깊게 이해해야 합니다. 콘텐츠 .content
레이어는 정적이지만 두 개의 외부 레이어가 실제로 회전하므로 추가 rotateX(40deg)
를 설정하면 추가 애니메이션을 겹쳐놓는 것과 같습니다. 정방향 및 역방향 회전이 오프셋되어 전체 애니메이션에서 위의 효과를 생성하는 회전된 rotateX(40deg)
애니메이션만 볼 수 있습니다. 이런 방식으로 JavaScript 개입 없이 제목 그림에 표시된 3D 효과를 시뮬레이션합니다. 물론 이것만으로는 사용자와 연결하기에는 충분하지 않습니다. 마우스 움직임과 결합되어야 한다면 JavaScript의 도움이 필요합니다.
우리의 목표는 이러한 애니메이션 효과를 달성하는 것입니다.
🎜여기에는 실제로 두 가지 핵심 요소가 있습니다.🎜🎜🎜🎜마우스 활동 영역🎜🎜🎜 🎜회전하는 개체 자체🎜🎜🎜🎜🎜마우스 활동 영역🎜 내에서 마우스의 움직임은 🎜회전하는 개체 자체🎜의 3차원 회전에 영향을 미치며, 회전 방향은 실제로 X축 방향으로 분해되어 Y축 방향. 🎜🎜HTML 구조가 다음과 같다고 가정하고 살펴보겠습니다. 🎜const mouseOverContainer = document.getElementsByTagName("body")[0]; const element = document.getElementById("element"); mouseOverContainer.onmousemove = function(e) { let box = element.getBoundingClientRect(); let calcY = e.clientX - box.x - (box.width / 2); element.style.transform = "rotateY(" + calcY + "deg) "; }
这里,body
的范围就是整个鼠标可活动区域,也是我们添加鼠标的 mousemove
事件的宿主 target,而 #element
就是需要跟随鼠标一起转动的旋转物体本身。
因为整个效果是需要基于 CSS 3D 的,我们首先加上简单的 CSS 3D 效果:
body { width: 100vw; height: 100vh; transform-style: preserve-3d; perspective: 500px; } div { width: 200px; height: 200px; background: #000; transform-style: preserve-3d; }
效果如下:
没有什么不一样。这是因为还没有添加任何的 3D 变换,我们给元素添加 X、Y 两个方向的 rotate()
试一下(注意,这里默认的旋转圆心即是元素中心):
div { transform: rotateX(15deg) rotateY(30deg); }
效果如下,是有那么点意思了:
好,接下来,我们的目标就是通过结合 mouseover 事件,让元素动起来。
当然,为了更加容易理解,我们把动画拆分为 X、Y 两个方向上的移动。首先看 X 方向上的移动:
这里,我们需要以元素的中心为界:
当鼠标在中心右侧连续移动,元素绕 Y 轴移动,并且值从 0 开始,越来越大,范围为(0, +∞)deg
反之,当鼠标在中心左侧连续移动,元素绕 Y 轴移动,并且值从 0 开始,越来越小,范围为(-∞, 0)deg
这样,我们可以得到这样一个公式:
rotateY = (鼠标 x 坐标 - 元素左上角 x 坐标 - 元素宽度的一半)deg
通过绑定 onmousemove 事件,我们尝试一下:
const mouseOverContainer = document.getElementsByTagName("body")[0]; const element = document.getElementById("element"); mouseOverContainer.onmousemove = function(e) { let box = element.getBoundingClientRect(); let calcY = e.clientX - box.x - (box.width / 2); element.style.transform = "rotateY(" + calcY + "deg) "; }
效果如下:
好吧,旋转的太夸张了,因此,我们需要加一个倍数进行控制:
const multiple = 20; const mouseOverContainer = document.getElementsByTagName("body")[0]; const element = document.getElementById("element"); mouseOverContainer.onmousemove = function(e) { let box = element.getBoundingClientRect(); let calcY = (e.clientX - box.x - (box.width / 2)) / multiple; element.style.transform = "rotateY(" + calcY + "deg) "; }
通过一个倍数约束后,效果好了不少:
同理,我们利用上述的方式,同样可以控制 Y 方向上的移动:
const multiple = 20; const mouseOverContainer = document.getElementsByTagName("body")[0]; const element = document.getElementById("element"); mouseOverContainer.onmousemove = function(e) { let box = element.getBoundingClientRect(); let calcX = (e.clientY - box.y - (box.height / 2)) / multiple; element.style.transform = "rotateX(" + calcX + "deg) "; };
效果如下:
当然,在这里,我们会发现方向是元素运动的方向是反的,所以需要做一下取反处理,修改下 calcX
的值,乘以一个 -1
即可:
let calcX = (e.clientY - box.y - (box.height / 2)) / multiple * -1;
OK,到这里,我们只需要把上述的结果合并一下即可,同时,上面我们使用的是 onmousemove
触发每一次动画移动。现代 Web 动画中,我们更倾向于使用 requestAnimationFrame
去优化我们的动画,确保每一帧渲染一次动画即可。
完整的改造后的代码如下:
const multiple = 20; const mouseOverContainer = document.getElementsByTagName("body")[0]; const element = document.getElementById("element"); function transformElement(x, y) { let box = element.getBoundingClientRect(); let calcX = -(y - box.y - (box.height / 2)) / multiple; let calcY = (x - box.x - (box.width / 2)) / multiple; element.style.transform = "rotateX("+ calcX +"deg) " + "rotateY("+ calcY +"deg)"; } mouseOverContainer.addEventListener('mousemove', (e) => { window.requestAnimationFrame(function(){ transformElement(e.clientX, e.clientY); }); });
至此,我们就能简单的实现题图所示的鼠标跟随 3D 旋转动效:
现在,还有最后一个问题,就是当我们的鼠标离开活动区域时,元素的 transform 将停留在最后一帧,正确的表现应该是复原到原状。因此,我们还需要添加一些事件监听做到元素的平滑复位。
通过一个 mouseleave
事件配合元素的 transition
即可。
div { // 与上述保持一致... transition: all .1s; }
mouseOverContainer.addEventListener('mouseleave', (e) => { window.requestAnimationFrame(function(){ element.style.transform = "rotateX(0) rotateY(0)"; }); });
至此,我们就可以完美的实现平滑出入,整体效果最终如下:
完整的代码,你可以戳这里:CodePen Demo -- CSS 3D Rotate With Mouse Move
(学习视频分享:web前端)
위 내용은 상호작용을 더욱 생생하게 만들어보세요! 마우스를 따라가는 3D 회전 효과를 얻기 위해 CSS를 기발하게 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!