使用JavaScript練習(xí)動畫最好的方式封面過渡
引言
首先讓我們來看一個鏡頭,這個鏡頭展示了幾個過渡效果,其中之一就是我所說的 "封面過渡",一個黑色的封面以動畫形式隱藏了一些內(nèi)容,然后新的內(nèi)容在封面上顯現(xiàn)出來(其顏色與之前的不同)。
我喜歡我們可以在網(wǎng)頁中使用大量不同的動畫來展示新內(nèi)容的內(nèi)容。所以我們今天將在一個簡短的教程中看一下他的結(jié)構(gòu)和動畫的一些亮點。
我會使用GreenSock的GSAP作為效果的動畫庫。
標(biāo)記和樣式
我會以下面這個網(wǎng)站來實現(xiàn)這個效果
首先,我們的整個頁面將是一個網(wǎng)格布局
html代碼
<div class="content"> <div class="item"> <span class="item__meta">2020</span> <h3 class="item__title">Alex Moulder</h3> <div class="item__img"><div class="item__img-inner" style="background-image:url(img/1.jpg)"></div></div> <p class="item__desc">I am only waiting for love to give myself up at last into his hands. That is why it is so late and why I have been guilty of such omissions.</p> <a class="item__link">view</a> </div> <div class="item"> <span class="item__meta">2021</span> <h3 class="item__title">Aria Bennett</h3> <div class="item__img"><div class="item__img-inner" style="background-image:url(img/2.jpg)"></div></div> <p class="item__desc">They come with their laws and their codes to bind me fast; but I evade them ever, for I am only waiting for love to give myself up at last into his hands.</p> <a class="item__link">view</a> </div> <div class="item"> <span class="item__meta">2022</span> <h3 class="item__title">Jimmy Hughes</h3> <div class="item__img"><div class="item__img-inner" style="background-image:url(img/3.jpg)"></div></div> <p class="item__desc">Clouds heap upon clouds and it darkens. Ah, love, why dost thou let me wait outside at the door all alone?</p> <a class="item__link">view</a> </div> </div>
CSS代碼
main { padding: 1.5rem 2.5rem 3rem; height: 100vh; display: grid; grid-template-columns: 100%; grid-template-areas: 'frame' 'content'; grid-template-rows: min-content 1fr; grid-row-gap: 8vh; }
內(nèi)容劃分將有以下風(fēng)格,以顯示網(wǎng)格中的項目
.content { grid-area: content; max-width: 400px; } @media screen and (min-width: 53em) { .content { max-width: none; display: grid; grid-template-columns: repeat(3,1fr); grid-template-rows: 100%; grid-column-gap: 5vw; } }
我們只想在大屏幕上并排顯示項目。所以我們添加了一個媒體查詢。
對于項目的內(nèi)部元素,我們將具有以下樣式:
.item { margin-bottom: 5rem; display: grid; grid-template-columns: 100%; grid-template-rows: 1rem auto auto 1fr auto; } .item__title { font-family: kudryashev-d-excontrast-sans, sans-serif; font-weight: 300; font-size: 2rem; margin-bottom: 0.5rem; } .item__img { position: relative; overflow: hidden; width: 100%; aspect-ratio: 500/333; } .item__img-inner { background-position: 50% 45%; background-size: cover; width: 100%; height: 100%; } .item__desc { margin-top: 2.5rem; line-height: 1.1; } .item__link { cursor: pointer; text-transform: lowercase; width: 100%; padding: 1rem; color: var(--color-text); border: 1px solid var(--color-border); border-radius: 2rem; text-align: center; } .item__link:hover { background: var(--color-text); border-color: var(--color-text); color: var(--color-text-alt); } @media screen and (min-width: 53em) { .item { margin-bottom: 0; } .item__title { font-size: clamp(1.25rem,3vw,2rem); } }
圖像元素有一個嵌套結(jié)構(gòu),可以讓我們做出一點縮放效果。這里有一個有趣的地方是寬高比屬性,它允許我們在使用背景圖像屬性時根據(jù)其實際大小設(shè)置響應(yīng)式圖像尺寸。
當(dāng)我們單擊項目按鈕時,我們將顯示一個封面動畫。這將是動畫其比例變換以覆蓋整個頁面的兩個元素:
<div class="overlay"> <div class="overlay__row"></div> <div class="overlay__row"></div> </div>
讓我們添加以下樣式:
.overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: grid; grid-template-columns: 100%; pointer-events: none; grid-template-rows: repeat(2,1fr); } .overlay__row { background: var(--color-overlay); transform: scaleY(0); will-change: transform; } .overlay__row:first-child { transform-origin: 50% 0%; } .overlay__row:last-child { transform-origin: 50% 100%; }
為每一“行”設(shè)置正確的變換原點將確保它們上下動畫,“關(guān)閉”當(dāng)前視圖并隱藏它。
接下來,讓我們看一下我們將看到的視圖。此部分將稱為“預(yù)覽”,我們將添加以下內(nèi)容:
<section class="previews"> <div class="preview"> <div class="preview__img"><div class="preview__img-inner" style="background-image:url(img/1_big.jpg)"></div></div> <h3 class="preview__title oh"><span class="oh__inner">Moulder</span></h3> <div class="preview__column preview__column--start"> <span class="preview__column-title preview__column-title--main oh"><span class="oh__inner">Alex Moulder</span></span> <span class="oh"><span class="oh__inner">2020</span></span> </div> <div class="preview__column"> <h4 class="preview__column-title oh"><span class="oh__inner">Location</span></h4> <p>And if it rains, a closed car at four. And we shall play a game of chess, pressing lidless eyes and waiting for a knock upon the door.</p> </div> <div class="preview__column"> <h4 class="preview__column-title oh"><span class="oh__inner">Material</span></h4> <p>At the violet hour, when the eyes and back, turn upward from the desk, when the human engine waits.</p> </div> <button class="unbutton preview__back"><svg width="100px" height="18px" viewBox="0 0 50 9"><path vector-effect="non-scaling-stroke" d="m0 4.5 5-3m-5 3 5 3m45-3h-77"></path></svg></button> </div> <!-- preview --> <!-- preview --> </section>
大圖像將使用本教程中詳細解釋的顯示/取消顯示動畫進行動畫處理。這就是我們使用嵌套結(jié)構(gòu)的原因,就像在項目圖像上一樣。對于我們想要通過轉(zhuǎn)變(并被父級截斷)來顯示的文本,我們將使用 .oh > .oh__inner
結(jié)構(gòu)。這背后的想法是轉(zhuǎn)變oh__inner
元素以隱藏它。對于多行文本,我們將使用 JavaScript 動態(tài)添加此結(jié)構(gòu)。我們 preview__column
分區(qū)中的段落將使用SplitType
分成幾行。
讓我們添加以下樣式以使線條魔術(shù)起作用:
.oh { position: relative; overflow: hidden; } .oh__inner { will-change: transform; display: inline-block; } .line { transform-origin: 0 50%; white-space: nowrap; will-change: transform; }
現(xiàn)在,讓我們把這個寶貝做成動畫
The JavaScript
讓我們先定義和實例化一些東西
import { gsap } from 'gsap'; import { Item } from './item'; import { Preview } from './preview'; // body element const body = document.body; // .content element const contentEl = document.querySelector('.content'); // frame element const frameEl = document.querySelector('.frame'); // 頂部和底部疊加的疊加元素 const overlayRows = [...document.querySelectorAll('.overlay__row')]; const previews = []; [...document.querySelectorAll('.preview')].forEach(preview => previews.push(new Preview(preview))); //項目實例列表 const items = []; [...document.querySelectorAll('.item')].forEach((item, pos) => items.push(new Item(item, previews[pos])));
現(xiàn)在,當(dāng)我們打開一個項目時,我們首先要把我們的內(nèi)容設(shè)置為不能再點擊。用一個類來完成。
然后,我們在顯示預(yù)覽內(nèi)容后,隱藏所有那些我們想要動畫化的線條和元素。preview-visible
類幫助我們設(shè)置一些顏色和指針事件。我們還用它來隱藏我們在頁面頂部的小框架,這樣,一旦封面隱藏了初始視圖,我們就可以用動畫再次顯示它。
通過將圖像元素向一個方向平移,將內(nèi)部元素(實際上包含了背景圖像)向相反的方向平移,圖像就不會被顯示出來。
我們也最終顯示了所有的線條和oh__inner
元素。
const openItem = item => { gsap.timeline({ defaults: { duration: 1, ease: 'power3.inOut' } }) .add(() => { // 指針事件沒有指向內(nèi)容 contentEl.classList.add('content--hidden'); }, 'start') .addLabel('start', 0) .set([item.preview.DOM.innerElements, item.preview.DOM.backCtrl], { opacity: 0 }, 'start') .to(overlayRows, { scaleY: 1 }, 'start') .addLabel('content', 'start+=0.6') .add(() => { body.classList.add('preview-visible'); gsap.set(frameEl, { opacity: 0 }, 'start') item.preview.DOM.el.classList.add('preview--current'); }, 'content') // Image animation (reveal animation) .to([item.preview.DOM.image, item.preview.DOM.imageInner], { startAt: {y: pos => pos ? '101%' : '-101%'}, y: '0%' }, 'content') .add(() => { for (const line of item.preview.multiLines) { line.in(); } gsap.set(item.preview.DOM.multiLineWrap, { opacity: 1, delay:0.1 }) }, 'content') // 動畫框架元素 .to(frameEl, { ease: 'expo', startAt: {y: '-100%', opacity: 0}, opacity: 1, y: '0%' }, 'content+=0.3') .to(item.preview.DOM.innerElements, { ease: 'expo', startAt: {yPercent: 101}, yPercent: 0, opacity: 1 }, 'content+=0.3') .to(item.preview.DOM.backCtrl, { opacity: 1 }, 'content') };
當(dāng)我們關(guān)閉預(yù)覽時,我們需要做一些反向動畫
const closeItem = item => { gsap.timeline({ defaults: { duration: 1, ease: 'power3.inOut' } }) .addLabel('start', 0) .to(item.preview.DOM.innerElements, { yPercent: -101, opacity: 0, }, 'start') .add(() => { for (const line of item.preview.multiLines) { line.out(); } }, 'start') .to(item.preview.DOM.backCtrl, { opacity: 0 }, 'start') .to(item.preview.DOM.image, { y: '101%' }, 'start') .to(item.preview.DOM.imageInner, { y: '-101%' }, 'start') // 動畫框架元素 .to(frameEl, { opacity: 0, y: '-100%', onComplete: () => { body.classList.remove('preview-visible'); gsap.set(frameEl, { opacity: 1, y: '0%' }) } }, 'start') .addLabel('grid', 'start+=0.6') .to(overlayRows, { //ease: 'expo', scaleY: 0, onComplete: () => { item.preview.DOM.el.classList.remove('preview--current'); contentEl.classList.remove('content--hidden'); } }, 'grid') };
不要忘記事件監(jiān)聽器
for (const item of items) { // 打開項目預(yù)覽 item.DOM.link.addEventListener('click', () => openItem(item)); // 關(guān)閉項目預(yù)覽 item.preview.DOM.backCtrl.addEventListener('click', () => closeItem(item)); }
這就是這一切的結(jié)果
在動畫進入時要有流暢的轉(zhuǎn)場動畫,并做一個快速的關(guān)閉動畫,這樣用戶就不必等待很長時間來恢復(fù)最初的視圖了。探索代碼并嘗試做一些其他的動畫、計時和緩和,給它另一種感覺,看看哪些是有效的,哪些是無效的!
以上就是使用JavaScript練習(xí)動畫最好的方式封面過渡的詳細內(nèi)容,更多關(guān)于JavaScript動畫封面過渡的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
LoadRunner調(diào)用JS加密后登錄實現(xiàn)
這篇文章主要為大家介紹了LoadRunner調(diào)用JS加密后登錄實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06