برای درک بهتر آنچه که می‌خواهیم بسازیم، این را بررسی کنید صفحه نمایشی. برای تکرار انیمیشن حتما روی لینک های منو کلیک کنید.

از آنجایی که هر دو انیمیشن شباهت هایی دارند، من برخی از بخش های محتوایی را از آموزش قبلی قرض می کنم. این کمک می کند تا هر آموزش دقیق و مستقل بماند.

نمایش انیمیشن صفحه

برای این آموزش نسخه ی نمایشی ما نمی خواهد زنده در CodePen از آنجایی که برای نمایش انیمیشن به صفحات مختلفی نیاز داریم، تصمیم گرفتم که بهتر است آن را در GitHub میزبانی کنیم. اینجاست ساختار پروژه:

1
panels-animation/
2
├── about.html
3
├── contact.html
4
├── index.html
5
├── main.css
6
└── main.js

قبل از اینکه ادامه دهیم، شایان ذکر است که الهام‌بخش این دمو از نمایش نسبتاً دوست‌داشتنی گرفته شده است وب سایت Nine Orchard.

اسکرین شات از وبسایت 9 باغاسکرین شات از وبسایت 9 باغاسکرین شات از وبسایت 9 باغ

1. با علامت گذاری صفحه شروع کنید

بیایید نشانه گذاری را برای index.html صفحه این صفحه مشابه صفحات دیگر خواهد بود.

در داخل آن قرار می دهیم:

  • یک هدر صفحه معمولی
  • پنل هایی که وظیفه تقسیم صفحه نمایش به هفت قسمت مساوی را بر عهده خواهند داشت.
  • این main عنصری که محتوای اصلی صفحه در آن زندگی می کند.

علاوه بر این، ما وارد خواهیم کرد:

با در نظر گرفتن تمام موارد فوق، در اینجا نشانه گذاری مرتبط آمده است:

1
<!doctype html>
2
<html lang="en">
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <link rel="preconnect" href="https://fonts.gstatic.com">
7
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap">
8
    <link rel="stylesheet" href="main.css">
9
    <title>Simple JavaScript Page Loading Animation</title>
10
  </head>
11
  
12
  <body>
13
    <header class="page-header">
14
      <nav>
15
        <ul>
16
          <li>
17
            <a href="index.html">Home</a>
18
          </li>
19
          <!-- more list items -->
20
        </ul>
21
      </nav>
22
    </header>
23
    
24
    <ul class="panels">
25
      <li class="panel" style="--index: 3"></li>
26
      <li class="panel" style="--index: 2"></li>
27
      <li class="panel" style="--index: 1"></li>
28
      <li class="panel" style="--index: 0"></li>
29
      <li class="panel" style="--index: 1"></li>
30
      <li class="panel" style="--index: 2"></li>
31
      <li class="panel" style="--index: 3"></li>
32
    </ul>
33
    
34
    <main class="page-main">
35
      <div>
36
        <h1>Home Page</h1>
37
        <!-- put more content here -->
38
      </div>
39
    </main>
40
    
41
    <script src="main.js"></script>   
42
  </body>
43
</html>

استایل های درون خطی را که به پنل ها اضافه می کنیم در نظر بگیرید. همانطور که بعدا خواهیم دید، ما از آن استفاده خواهیم کرد index متغیر CSS برای متحرک سازی آنها. هر چه مقدار بزرگتر باشد، زمان بیشتری طول می کشد تا عنصر مرتبط متحرک شود.

2. برخی از سبک های اساسی را تعریف کنید

در مرحله بعد، با برخی از متغیرهای CSS و بازنشانی سبک‌ها ادامه می‌دهیم:

1
:root {
2
  --panel-width: calc(100% / 7);
3
  --darkblue: #02020c;
4
  --white: #fff;
5
  --lightgray: #fafafb;
6
}
7

8
* {
9
  padding: 0;
10
  margin: 0;
11
  box-sizing: border-box;
12
}
13

14
ul {
15
  list-style: none;
16
}
17

18
a {
19
  color: inherit;
20
  text-decoration: none;
21
}
22

23
h1 {
24
  font-size: 3rem;
25
}
26

27
body {
28
  height: 100vh;
29
  font-family: "Montserrat", sans-serif;
30
  color: var(--white);
31
  background: var(--darkblue);
32
  overflow: hidden;
33
}

سه نکته قابل توجه:

  • این panel-width متغیر عرض پانل را تعیین می کند.
  • ارتفاع صفحه برابر با ارتفاع نمای پورت خواهد بود.
  • ما هر نوار پیمایش احتمالی را که ممکن است بسته به مقدار محتوای صفحه ظاهر شود، پنهان می کنیم.

3. سبک های اصلی را مشخص کنید

بیایید اکنون بر روی آن تمرکز کنیم اصلی سبک ها ما سبک‌های هدر را کنار می‌گذاریم زیرا اهمیتی ندارند.

پانل ها

پانل ها عناصر با موقعیت ثابت و آنها خواهند بود width و left ارزش اموال به panel-width متغیر. که گفت، left مقدار پانل اول 0، برای پانل دوم حدود 14.28٪، برای پانل سوم حدود 28.5٪ و غیره خواهد بود. ارتفاع آنها برابر با ارتفاع نمای و به طور پیش فرض نامرئی خواهد بود. ما استفاده خواهیم کرد clip-path خاصیت فشرده سازی و انتقال آنها به قسمت پایین صفحه.

عنصر اصلی

این main عنصر تمام صفحه با محتوای مرکزی افقی و عمودی خواهد بود. برای سادگی، ما فقط یک عنوان و یک لینک قرار می دهیم، اما شما می توانید هر چیزی را که دوست دارید قرار دهید. مجدداً، به طور پیش فرض، تمام این محتوا نامرئی خواهد بود و 100 پیکسل دور از موقعیت اصلی خود قرار می گیرد.

در اینجا سبک های مربوطه آمده است:

1
/*CUSTOM VARIABLES HERE*/
2

3
.panels .panel {
4
  position: fixed;
5
  top: 0;
6
  left: 0;
7
  bottom: 0;
8
  width: calc(var(--panel-width) + 1px);
9
  clip-path: inset(100% 0 0 0);
10
  background: var(--lightgray);
11
  transition: all 1s cubic-bezier(0.25, 1, 0.25, 1);
12
}
13

14
.panels .panel:nth-child(2) {
15
  left: var(--panel-width);
16
}
17

18
.panels .panel:nth-child(3) {
19
  left: calc(var(--panel-width) * 2);
20
}
21

22
.panels .panel:nth-child(4) {
23
  left: calc(var(--panel-width) * 3);
24
}
25

26
.panels .panel:nth-child(5) {
27
  left: calc(var(--panel-width) * 4);
28
}
29

30
.panels .panel:nth-child(6) {
31
  left: calc(var(--panel-width) * 5);
32
}
33

34
.panels .panel:nth-child(7) {
35
  left: calc(var(--panel-width) * 6);
36
}
37

38
.page-main {
39
  display: flex;
40
  height: 100%;
41
  padding: 100px 15px;
42
  overflow-y: auto;
43
}
44

45
.page-main > div {
46
  text-align: center;
47
  margin: auto;
48
}
49

50
.page-main > div > * {
51
  opacity: 0;
52
  transition: all 0.5s ease-out;
53
}
54

55
.page-main h1 {
56
  transform: translateY(-100px);
57
}
58

59
.page-main p {
60
  font-size: 20px;
61
  margin-top: 20px;
62
  transform: translateY(100px);
63
}

اطلاعات

اگر بررسی کنید width مقدار پانل ها، متوجه خواهید شد که یک پیکسل اضافی وجود دارد. وظیفه آن این است که پانل ها را کمی روی هم قرار دهد و در نتیجه از ایجاد حاشیه های آبی (رنگ آنها به رنگ صفحه بستگی دارد) بین پانل های مجاور جلوگیری کند.

خطوط آبی که بین پانل ها ظاهر می شودخطوط آبی که بین پانل ها ظاهر می شودخطوط آبی که بین پانل ها ظاهر می شود

4. انیمیشن ها را آتش بزنید

هنگامی که صفحه بارگیری می شود، انیمیشن های زیر باید به ترتیب پخش شوند:

  1. ابتدا، پانل ها باید از پایین به بالا ظاهر شوند.
  2. سپس، پانل ها باید ناپدید شوند و به سمت بالا حرکت کنند.
  3. در نهایت، تمام محتویات صفحه باید قابل مشاهده باشند.

در دو مرحله اول، پانل ها با کمی تاخیر جابجا می شوند. همانطور که قبلاً بحث کردیم، این به ارزش آنها بستگی دارد index متغیر.

تقلید از یک جدول زمانی

خلق كردن دنباله ای از توئین ها مانند دفعه قبل جدول زمانی GSAP، ما تاز یک رویداد کمتر شناخته شده به نام استفاده کنید transitionend. این رویداد هر بار که یک انتقال CSS به پایان می رسد فعال می شود و به ما توانایی همگام سازی انیمیشن ها را می دهد.

البته، ما به همه انتقال‌ها علاقه‌ای نداریم، در عوض، فقط به انتقال پانل‌ها و به‌ویژه انتقال‌های آخرین پانل متحرک اهمیت می‌دهیم. در مورد ما، آخرین پانل های متحرک اولین و هفتمین (آخرین) خواهد بود همانطور که هر دو دارند index: 3.

تأخیر انتقال آخرین پانلتأخیر انتقال آخرین پانلتأخیر انتقال آخرین پانل

همانطور که در کد خواهید دید، ما با آخرین مورد کار خواهیم کرد، اما به همان اندازه می توانستیم از اولین مورد استفاده کنیم. برای درک بهتر آن، سعی کنید به پانل انتخاب شده تاخیر زیادی در حدود 1 ثانیه بدهید و ببینید که چگونه انیمیشن ها از هماهنگی خارج می شوند.

از نظر منطق کد، کارهای زیر را به ترتیب انجام می دهیم:

  1. ابتدا، هنگامی که صفحه بارگیری می شود، ما آن را اضافه می کنیم loaded کلاس به body.
  2. سپس، منتظر می‌مانیم تا انتقال آخرین پانل به پایان برسد-این در مجموع دو بار شلیک می کند. در آن مرحله، کلاس دیگری را به آن اضافه می کنیم body. اولین بار ما اضافه می کنیم second-round کلاس، در حالی که بار دوم، ما را اضافه می کنیم third-round.

پس از تکمیل انتقال ما، body این کلاس ها را خواهند داشت:

کلاس های متصل به بدنکلاس های متصل به بدنکلاس های متصل به بدن

این کد جاوا اسکریپت است:

1
const body = document.body;
2
const lastPanel = document.querySelector(".panels .panel:last-child");
3

4
window.addEventListener("load", () => {
5
  body.classList.add("loaded");
6
  
7
  lastPanel.addEventListener("transitionend", () => {
8
    if (body.classList.contains("second-round")) {
9
      body.classList.add("third-round");
10
    } else {
11
      body.classList.add("second-round");
12
    }
13
  });
14
});

به جای load رویداد، ما می توانستیم از آن استفاده کنیم DOMContentLoaded رویداد.

و سبک های مربوطه:

1
.loaded .panels .panel {
2
  clip-path: inset(0);
3
  transition-delay: calc(var(--index) * 0.06s);
4
}
5

6
.loaded.second-round .panels .panel {
7
  clip-path: inset(0 0 100% 0);
8
}
9

10
.loaded.third-round {
11
  overflow: auto;
12
}
13

14
.loaded.third-round .page-main > div > * {
15
  opacity: 1;
16
  transform: none;
17
}

نتیجه

تبریک میگم، مردم! ما موفق به ساخت یک جذاب شدیم انیمیشن بارگذاری صفحه جاوا اسکریپت توسط انیمیشن های خیره کننده به لطف transitionend رویداد. بدیهی است که برای استفاده سنگین تر از انیمیشن ها، کتابخانه ای مانند GSAP رویکرد قوی تری برای دنبال کردن است. می توانید نسخه ی نمایشی را همانطور که می خواهید گسترش دهید و آن را با من به اشتراک بگذارید!

مثل همیشه، خیلی ممنون که خواندید!

پروژه های بیشتر برای تمرین

به این پروژه ها در Tuts+ که از clip-path ویژگی برای اعمال انواع مختلف انیمیشن ها.