Heim > Artikel > Web-Frontend > Machen Sie die Interaktion lebendiger! Cleverer Einsatz von CSS, um einen mausfolgenden 3D-Rotationseffekt zu erzielen
In diesem Artikel erfahren Sie, wie Sie mithilfe von CSS einen interessanten 3D-Rotationseffekt mit der Maus erzielen und die Interaktion lebendiger gestalten. Ich hoffe, dass er für alle hilfreich ist!
Heute stellte eine Gruppe von Freunden die Frage, wie man den folgenden interaktiven Effekt mit der Maus umsetzen kann, wie unten gezeigt:
Eine kurze Analyse zeigt, dass dieser interaktive Effekt hauptsächlich zwei Kerne hat:
Mit Hilfe von Ohne die Fähigkeit von CSS 3D
Die Drehung von Elementen muss mit der Bewegung der Maus kombiniert werden
In diesem Artikel wird beschrieben, wie Sie mit reinem CSS ähnliche interaktive Effekte erzielen und JavaScript verwenden um Mausereignisse zu binden, um den oben genannten Effekt schnell wiederherzustellen. [Empfohlenes Lernen: CSS-Video-Tutorial]
Wie erreicht man einen ähnlichen 3D-Rotationseffekt ohne JavaScript, nur CSS?
Ein kleiner Trick namens positive und negative Rotationsaufhebung oder positive und negative Rotationsaufhebung wird hier verwendet. Nun, der Name ist sehr seltsam, es scheint ein mathematisches Konzept zu sein.
Rotation ist in der Animation ein sehr häufig verwendetes Attribut.
{ transform: rotate(90deg); }
Was passiert, wenn wir Elementen auf verschiedenen Ebenen Rotation in verschiedene Richtungen hinzufügen?
Nehmen wir zunächst das Szenario an:
<div> <div> <div>正负旋转相消3D动画</div> </div> </div>
Der Stil ist wie folgt:
.content
ist unser Hauptinhalt. Wie wird der Effekt aussehen, wenn das übergeordnete Element .rotate
eine lineare 360°-Drehung nach vorne durchführt und das äußerste übergeordnete Element .reverseRotate
eine lineare 360°-Drehung in umgekehrter Richtung ausführt? .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>Wir können eine solche Animation erhalten (beachten Sie, dass das Bild unten ein GIF und kein PNG ist):
.content
immer noch stationär aus! Beachten Sie, dass es hier sehr wichtig ist, dass der gesamte .content
statisch ist. Einige Leser sind kurz davor zu fluchen, wenn sie das sehen. Autor, Sie sind ein zurückgebliebener Mensch. Wenn Sie aufhören, gibt es dann keine Animation? Woher haben Sie Ihre Animationsfähigkeiten? Mach dir keine Sorgen! Obwohl es stationär aussieht, drehen sich die beiden Vorgängerelemente tatsächlich! Dies mag wie ein beruhigender Effekt erscheinen, doch dahinter verbirgt sich tatsächlich eine Unterströmung. Die Verwendung von Entwicklertools zur Auswahl des äußersten Vorgängerelements sieht folgendermaßen aus:
Zuerst fügen wir diesen Elementen eine CSS-3D-Transformation hinzu:
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); }
Der Effekt ist wie folgt:
Wow, das muss sorgfältig verstanden werden. Da die Inhaltsebene .content
statisch ist, die beiden äußeren Ebenen jedoch tatsächlich rotieren, entspricht das Festlegen eines zusätzlichen rotateX(40deg)
dem Überlagern einer zusätzlichen Animation. Da die Vorwärts- und Rückwärtsdrehungen versetzt sind, kann die gesamte Animation nur die gedrehte rotateX(40deg)
-Animation sehen, die den oben genannten Effekt erzeugt. Auf diese Weise simulieren wir ohne JavaScript-Eingriff den im Titelbild gezeigten 3D-Effekt. Dies allein reicht natürlich nicht aus, um eine Verknüpfung mit dem Benutzer herzustellen. Wenn dies mit der Mausbewegung kombiniert werden muss, benötigen wir Unterstützung durch JavaScript.
Unser Ziel ist es, einen solchen Animationseffekt zu erzielen:
🎜Hier haben wir tatsächlich zwei Kernelemente:🎜🎜🎜🎜Mausaktivitätsbereich🎜🎜🎜 🎜Das rotierende Objekt selbst🎜🎜🎜🎜Die Bewegung der Maus innerhalb des 🎜Mausaktivitätsbereichs🎜 wirkt sich auf die 3D-Rotation des 🎜rotierenden Objekts selbst🎜 aus, und die Drehrichtung kann tatsächlich in die X-Achsen-Richtung zerlegt werden die Y-Achsenrichtung. 🎜🎜Lassen Sie uns einen Blick darauf werfen, vorausgesetzt, unsere HTML-Struktur ist wie folgt: 🎜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) "; }🎜Holen Sie sich eine solche Grafik: 🎜🎜🎜🎜
这里,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前端)
Das obige ist der detaillierte Inhalt vonMachen Sie die Interaktion lebendiger! Cleverer Einsatz von CSS, um einen mausfolgenden 3D-Rotationseffekt zu erzielen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!