با سلام و احترام خدمت شما همراهان گرامی روکسو، در این قسمت از آموزش جاوا اسکریپت میخواهیم با موضوع انیمیشن ها در جاوا اسکریپت آشنا شویم. مبحث انیمیشن ها در جاوا اسکریپت بسیار پیچیده است و نیاز به یک دوره ی جداگانه دارد اما در این قسمت با مفاهیم اصلی و نحوه ی کار انیمیشن های DOM در جاوا اسکریپت آشنا می شویم.
ممکن است بپرسید منظور ما از انیمیشن های DOM چیست؟ منظور ما این است که در دنیای وب راه های متفاوتی برای ساخت انیمیشن و پویا نمایی صفحات وجود دارد اما ما میخواهیم راهی بسیار ساده و ابتدایی در این مورد را بررسی کنیم که با دستکاری DOM انجام میگیرد.
بهترین روش یادگیری انیمیشن ها از طریق مثال است بنابراین بیایید ابتدا یک صفحه ی ساده ی وب را به وجود بیاوریم:
<!DOCTYPE html> <html> <body> <h1>My First JavaScript Animation</h1> <div id="animation">My animation will go here</div> </body> </html>
حالا باید فضایی را تعریف کنیم که انیمیشن ما در آن انجام شود:
<div id ="container"> <div id ="animate">My animation will go here</div> </div>
در این کد که قرار است به صفحه ی اصلی ما اضافه شود دو عدد عنصر <div> را به صورت تو در تو (nested) قرار داده ایم اما میدانیم که div ها تنها container (نگه دارنده ی) دیگر عناصر هستند و چیزی درونشان نیست بنابراین بیایید به این دو عنصر استایل بدهیم. برای div اول (فضایی که در آن انیمیشن اتفاق می افتد) ;position: relative
و برای div دوم (که خود انیمیشن خواهد بود ;position: absolute
قرار می دهیم. سپس بقیه ی استایل ها را طبق سلیقه ی خودمان اضافه می کنیم.
کد من به این شکل است:
<!Doctype html> <html> <style> #container { width: 400px; height: 400px; position: relative; background: yellow; } #animate { width: 50px; height: 50px; position: absolute; background: red; } </style> <body> <h2>My First JavaScript Animation</h2> <div id="container"> <div id="animate"></div> </div> </body> </html>
اگر به خروجی نگاهی بیندازید متوجه می شوید که ما div اول را تبدیل به یک مربع زرد رنگ کرده ایم و div دوم را به صورت یک مربع کوچکتر و به رنگ قرمز درون آن گذاشته ایم. حالا میخواهیم کاری کنیم که مربع قرمز رنگ درون مربع زرد رنگ جا به جا شود که همان انیمیشن ما خواهد بود. اینجاست که جاوا اسکریپت وارد کار می شود:
function myMove() { var elem = document.getElementById("animate"); var pos = 0; var id = setInterval(frame, 5); function frame() { if (pos == 350) { clearInterval(id); } else { pos++; elem.style.top = pos + 'px'; elem.style.left = pos + 'px'; } } }
(کد جاوا اسکریپت برای انیمیشن)
به نظر شما این کد جاوا اسکریپت که قرار است بعدا به کد اصلی ما اضافه شود چه کار می کند؟
همانطور که میبینید ابتدا یک تابع تعریف کرده ایم و نام آن را myMove (به معنی حرکت من) گذاشته ایم. سپس یک متغیر به نام elem (مخفف element و به معنای «عنصر») ساخته ایم. از اسمش مشخص است که چه چیزی را در این متغیر قرار داده ایم:
var elem = document.getElementById("animate");
در قسمت های قبلی توضیح دادیم که اگر می خواهیم در جاوا اسکریپت دستوری را بنویسیم که عنصری از DOM را بگیرد باید با document
شروع کنیم چرا که شیء اصلی در مرورگر ما می باشد. سپس از دستور getElementById
استفاده کرده ایم که اگر یادتان باشد کارش دریافت عناصر HTML بر اساس id آن ها بود؛ animate
را به آن داده ایم.
سپس یک متغیر دیگر به اسم pos (مخفف position و به معنی «موقعیت مکانی») ساخته ایم و فعلا مقدارش را صفر گذاشته ایم. متغیر سوم نیز id نام دارد و با استفاده از تابع setInterval به آن گفته ایم که هر 5 میلی ثانیه تابع frame را اجرا کند. در مورد تابع setInterval در دوره ی گذشته صحبت کرده ایم ولی برای یادآوری دوباره مثالی از آن می زنم.
تابع ()setInterval
دو آرگومان میگیرد که اولی یک تابع است و دومی زمان (در واحد میلی ثانیه). کار این تابع این است که تابع مورد نظر ما را هر فلان میلی ثانیه تکرار می کند.
مثال:
<!DOCTYPE html> <html> <body> <p dir='rtl'>هنگامی که روی دکمه ی زیر کلیک کنید، پیام "سلام به شما" هر 3 ثانیه یک بار برایتان نمایش داده می شود.</p> <button onclick="myFunction()">Try it</button> <script> var myVar; function myFunction() { myVar = setInterval(alertFunc, 3000); } function alertFunc() { alert("سلام به شما"); } </script> </body> </html>
در مثال بالا یک دکمه دارید. اگر روی این دکمه کلیک کنید، هر 3 ثانیه یک بار، پیام «سلام به شما» برایتان به نمایش در می آید. کار با این تابع آسان است و مطمئن هستم منظور من را فهمیده اید اما بیایید کمی پیشرفته تر شویم!
یکی دیگر از توابع مربوط به Interval می باشد تابع ()clearInterval
است که تابع ()setInterval
را نگه می دارد و اجازه نمی دهد دیگر اجرا شود. در مثال زیر کدها را طوری نوشته ایم که هر ثانیه ساعت ما آپدیت شود (با استفاده از setInterval
) بنابراین یک ساعت دیجیتال را داریم.
سپس دکمه ای قرار داده ایم که اگر آن را بزنید، دیگر setInterval اجرا نمی شود (این همان clearInterval
است):
<!DOCTYPE html> <html> <body> <p>A script on this page starts this clock:</p> <p id="demo"></p> <button onclick="myStopFunction()">Stop time</button> <script> var myVar = setInterval(myTimer, 1000); function myTimer() { var d = new Date(); var t = d.toLocaleTimeString(); document.getElementById("demo").innerHTML = t; } function myStopFunction() { clearInterval(myVar); } </script> </body> </html>
حالا که با توابع ()clearInterval
و ()setInterval
آشنا شدیم بهتر است برویم سراغ مبحث اصلی خودمان!
ما در (کد جاوا اسکریپت برای انیمیشن) به تابع ()setInterval
گفته ایم که هر 5 میلی ثانیه تابع ()frame
را اجرا کند. سپس تابع فریم را تعریف کرده ایم.
سوال: چرا تابع frame را ابتدا استفاده و سپس تعریف کرده ایم؟ قبل از اینکه تابعی تعریف شود چطور می توان از آن استفاده کرد؟
پاسخ: در بسیاری از زبان های برنامه نویسی چنین کاری خطا محسوب می شود اما اگر یادتان باشد گفته بودیم که در جاوا اسکریپت مبحثی به نام Hoisting وجود دارد. Hoisting باعث می شود این کد صحیح باشد.
در تابع ()frame
گفته ایم اگر pos ==
350
یعنی موقعیت افقی و عمودی عنصر به 350 پیکسل رسید clearInterval کند تا دیگر جلو نرود. به نظرتان چطور به عدد 350 رسیدیم؟ اگر یادتان باشد div اول که فضای انیمیشن بود دارای طول و عرض 400 پیکسلی بود و div دوم نیز طول و عرض 50 پیکسلی داشت. اگر بخواهیم div دوم در div اول باقی بماند و از آن خارج نشود باید 400 را منهای 50 کنیم که می شود 350!
سپس گفته ایم اگر pos ==
350
نبود، یک واحد به pos اضافه کن (++pos
) و بعد از آن دستور زیر را آورده ایم:
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
این دو دستور در واقع مقدار CSS عنصر را تغییر می دهند. style.top یعنی کد، به استایل های CSS برو فاصله از بالای این عنصر را برابر pos پیکسل قرار بده! این کار را برای فاصله از چپ نیز انجام داده ایم. از طرفی می دانیم تابع frame هر 5 میلی ثانیه توسط setInterval اجرا می شود که یعنی هر 5 میلی ثانیه یک واحد به pos اضافه شده و طبعا فاصله از بالا و چپ یک پیکسل اضافه می شود. این مسئله تا زمانی ادامه پیدا می کند که pos برابر 350 پیکسل شود و سپس clearInterval اجرا شود.
حالا مثال نهایی را می بینیم:
<!DOCTYPE html> <html> <style> #container { width: 400px; height: 400px; position: relative; background: yellow; } #animate { width: 50px; height: 50px; position: absolute; background-color: red; } </style> <body> <p><button onclick="myMove()">Click Me</button></p> <div id ="container"> <div id ="animate"></div> </div> <script> function myMove() { var elem = document.getElementById("animate"); var pos = 0; var id = setInterval(frame, 5); function frame() { if (pos == 350) { clearInterval(id); } else { pos++; elem.style.top = pos + "px"; elem.style.left = pos + "px"; } } } </script> </body> </html>
این مقاله پایه ی بحث انیمیشن ها را به شما نشان می دهد و بسیار ساده است. شما می توانید انیمیشن ها را بسیار پیشرفته تر و حتی بعضا تنها با CSS و بدون نیاز به جاوا اسکریپت پیاده کنید. چند مثال پیشرفته تر برایتان آورده ام!
ابتدا کدهای CSS:
.preloader { height: 100%; width: 100%; background: #fff; position: fixed; left: 0; top: 0; z-index: 10000; perspective: 1600px; perspective-origin: 20% 50%; transition: 0.5s all; opacity: 1; } .spinner { width: 80px; height: 80px; border: 2px solid #f3f3f3; border-top: 3px solid #0088cf; border-radius: 100%; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; animation: spin 1s infinite linear; } .preloader.fade { opacity: 0; } .b-ico-preloader { background: url(http://weblaboratory.in.ua/wp-content/themes/graphy/images/new_logo.svg); background-size: cover; width: 52px; height: 67px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; animation: ico 5s infinite linear; transform-style: preserve-3d; } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes ico { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }
سپس کدهای جاوا اسکریپت:
var preload = document.createElement('div'); preload.className = "preloader"; preload.innerHTML = '<div class="b-ico-preloader"></div><div class="spinner"></div>'; document.body.appendChild(preload); window.addEventListener('load', function() { // Uncomment to fade preloader after document load // preload.className += ' fade'; // setTimeout(function(){ // preload.style.display = 'none'; // },600); })
کدهای HTML:
<div id=container> Make <div id=flip> <div><div>wOrK</div></div> <div><div>lifeStyle</div></div> <div><div>Everything</div></div> </div> AweSoMe! </div> <p>a css3 animation demo</p>
کدهای CSS:
@import url('https://fonts.googleapis.com/css?family=Roboto:700'); body { margin:0px; font-family:'Roboto'; text-align:center; } #container { color:#999; text-transform: uppercase; font-size:36px; font-weight:bold; padding-top:200px; position:fixed; width:100%; bottom:45%; display:block; } #flip { height:50px; overflow:hidden; } #flip > div > div { color:#fff; padding:4px 12px; height:45px; margin-bottom:45px; display:inline-block; } #flip div:first-child { animation: show 5s linear infinite; } #flip div div { background:#42c58a; } #flip div:first-child div { background:#4ec7f3; } #flip div:last-child div { background:#DC143C; } @keyframes show { 0% {margin-top:-270px;} 5% {margin-top:-180px;} 33% {margin-top:-180px;} 38% {margin-top:-90px;} 66% {margin-top:-90px;} 71% {margin-top:0px;} 99.99% {margin-top:0px;} 100% {margin-top:-270px;} } p { position:fixed; width:100%; bottom:30px; font-size:12px; color:#999; margin-top:200px; }
روش های بسیاری برای انیمیشن سازی در دنیای وب وجود دارد و امیدوارم این قسمت شما را به این دنیای زیبا و جذاب معرفی کرده باشد. امیدوارم از این قسمت لذت برده باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.