راهنمای مطالعه
SVG مخفف (Scalable Vector Graphics) است که برای تعریف عناصر گرافیکی در سطح وب بکار میرود که دارای گرادینت یا گرادینتی برای ایجاد این عناصر است.
گرادینتهای SVG کاربردهای بسیاری دارند. با استفاده از آنها میتوانیم اشکال هندسی پیچیده، عمق و همچنین کاراکترهای موردنیاز کار هنری خود را با دادن دسترسی آن به DOM یا (Document Object Model) ایجاد کنیم.
SVG دارای دو نوع گرادینت اصلی است:
- گرادینت خطی
- گرادینت شعاعی
Attribute های متنوعی برای سفارشیسازی این شیبهای رنگ خطی و شعاعی SVG وجود دارد. متحرکسازی این شیبها بهدلخواه باعث میشود تا بتوانیم موارد موردنظر خود را برای کاربران ملموستر کنیم تا از این طریق بتوانند ارتباط بهتری با آنها برقرار کنند.
مقاله مرتبط: با Animista، بهراحتی انیمیشن CSS بسازید
در این مقاله به اصول اولیهی گرادینت های SVG میپردازیم و البته تأثیرات اعمال تگ <animate> بر روی این گرادینتها را بررسی میکنیم. چند دمو نیز برای درک بهتر این موضوع در این مقاله مورد تحلیل و آنالیز قرار گرفتهاند.
پشتیبانی مرورگر
قبل از بکار بردن هرگونه کد و عنصری از آنها در پروژههایمان باید وضعیت پشتیبانی مرورگرها از آنها را بررسی کنیم. SVG نیز از این قانون مستثنا نیست.
مرورگرهای موبایل و حتی تا دو نسخهی اخیر مرورگرهای دسکتاپ از SVG ابتدایی پشتیبانی میکنند.
مرورگر Internet Explorer بر روی دسکتاپ و موبایل و Opera Mini از انیمیشنهای SVG SMIL (انیمیشنسازی درون عناصر SVG) پشتیبانی نمیکنند اما برخلاف آن تا دو نسخهی اخیر مرورگرهای Chrome، Firefox، Safari و Opera بر روی موبایل و دسکتاپ از SVG SMIL پشتیبانی میکنند.
گرادینت SVG
پیش از اینکه بحث انیمیشن را شروع کنیم باید از چگونگی عملکرد گرادینت SVG درکی کلی داشته باشید.
مقاله مرتبط: ١٠ دلیل برای استفاده از گرادینت (gradient) در طراحی
زمانی که بخواهیم به SVG رنگ دلخواه خود را بدهیم، gradients یکی از ویژگیهایی است که این امکان را برای ما فراهم میکند. برای دادن رنگ به SVG باید از اتریبیوتهای «fill» و «stroke» استفاده کنیم چرا که شیبها با fill و stroke قابل تعریف هستند و تا زمانی که این کار را نکنیم نتیجهی تغییرات اعمال شده را بهصورت دیداری نخواهیم دید.
در زیر نمونهای ساده از ساختار گرادینت خطی SVG را مشاهده میکنید:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="180px" height="337px" viewBox="0 0 180.36 336.86" enable-background="new 0 0 180.36 336.86" xml:space="preserve"> <path fill="#7A5034" stroke="7A5034" stroke-width="2.5448" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" M159.337,292.35c0.863,0.605,1.073,1.795,0.469,2.658l-20.974,29.954c-0.605,0.863-1.795,1.073-2.658,0.469l-115.15-80.629 c-0.863-0.605-1.073-1.795-0.469-2.658l20.974-29.954c0.605-0.863,1.795-1.073,2.658-0.469L159.337,292.35z M100.669,289.765 L25.16,236.893 M149.278,309.079l-77.039-53.943 M73.154,244.329L38.237,219.88 M154.817,300.734l-25.015-17.516"/> <path fill="#7A5034" stroke="#7A5034" stroke-width="2.5448" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" M44.187,325.431c-0.863,0.605-2.054,0.395-2.658-0.469l-20.974-29.954c-0.605-0.863-0.395-2.054,0.469-2.658l115.15-80.629 c0.863-0.605,2.054-0.395,2.658,0.469l20.974,29.954c0.605,0.863,0.395,2.054-0.469,2.658L44.187,325.431z M66.681,271.185 l75.509-52.872 M31.907,310.257l77.039-53.943 M118.788,260.87l34.917-24.449 M37.855,318.317l25.015-17.516"/> <path class="outer-flame" fill="url(#largeGradient)" stroke="url(#largeGradient)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" M82.579,210.049c-4.315-0.393-8.678-1.158-12.676-2.352c-19.553-5.839-36.385-22.93-40.572-43.069 c-1.102-5.301-1.471-11.261-0.887-16.656c1.646-15.209,8.889-31.008,16.749-43.975C55.992,86.183,67.031,68.265,74.26,48.634 c2.079-5.647,3.825-11.421,5.117-17.299c2.019-9.181,3.897-21.151-3.384-28.647c14.729,15.163,27.537,32.13,38.675,50.078 c4.029,6.492,7.841,13.117,11.454,19.849c3.744,6.976,7.259,14.075,10.524,21.288c4.38,9.678,7.966,19.728,10.488,30.052 c4.66,19.078,9.751,43.266-2.968,60.391c-5.683,7.652-12.951,13.902-21.589,17.991c-10.308,4.879-22.085,8.124-33.541,8.032 C86.931,210.352,84.761,210.248,82.579,210.049z"> </path> <path class="inner-flame" fill="url(#smallGradient)" stroke="url(#smallGradient)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d=" M90.043,116.799c-4.024,9.712-12.607,17.546-17.863,26.662c-5.921,10.268-11.892,23.039-9.362,35.209 ۱.۸۶۵,۸.۹۷۴,۹.۳۶۶,۱۶.۵۸۹,۱۸.۰۷۸,۱۹.۱۹۱c1.782,0.532,3.726,0.873,5.648,1.048c0.972,0.089,1.939,0.135,2.877,0.143 c5.104,0.041,10.352-1.405,14.945-3.579c3.849-1.822,7.087-4.607,9.62-8.017c7.656-10.307,3.202-24.177-1.21-34.838 c-6.142-14.841-15.085-28.459-22.297-42.793C91.464,111.781,91.118,114.204,90.043,116.799z"> </path> </svg>
تگ <defs> کوتاه شدهی عبارت «definition» است که شامل توضیحاتی در مورد عناصر خاص از جمله گرادینتها میشود.
مقاله مرتبط: Animate.css ساخت انیمیشن در وب با کتابخانه CSS٣
پس جزئیات گرادینت در تگ <defs> بکار برده میشوند ولی تا زمانی که ID مختص آن را صدا نزنیم خروجی آن را نخواهیم دید. در این مرحله اگر قصد تعریف کردن شکلی را داشته باشیم در همان تگ <svg> این امکان وجود دارد فقط باید دقت کنیم که آن را خارج از <def> بکار ببریم.
نقاطی که تگ <stop> ایجاد میکند، انتخاب رنگها و مکان آنها را بر روی گرادینتهای ترسیم شده مشخص میکند. در مورد این موضوع بیشتر توضیح خواهیم داد.
اتریبیوتهای گرادینت
Value هایی که به اتریبیوتهای <linearGradient> و <radialGradient> میدهیم به ما این امکان را میدهد تا رنگ و مختصات گرادینتهای خود را انتخاب کنیم.
<linearGradient> برای معرفی گرادینت خطی و <radialGradient> برای معرفی گرادینت شعاعی بکار میرود.
نکته:
- گرادینت شعاعی (radial gradient) توسط مرکز آن تعریف میشود.
- برای ایجاد گرادینت شعاعی باید حداقل دو نقطهی رنگی تعریف کرد.
اکنون به اتریبیوتهای بکار برده شده در دموهای این مقاله نگاهی میاندازیم.
Id
هر گرادینت به یک ID منحصربهفرد برای خوانده شدن از اتریبیوتهای «fill» و «stroke» نیاز دارد.
x1, x2, y1, y2
value هایی که برای این اتریبیوتها در نظر میگیریم مختصات نقاط شروع و پایان گرادینت خطی را در طول محور مناسب مشخص میکنند. بهطور پیشفرض این value ها بر روی عدد «۰» تنظیم شدهاند بهجز x2 که «۱۰۰%» پیشفرض آن است.
cx, cy, r, fx, fy
اتریبیوتهای گرادینت شعاعی نیز همانند گرادینت خطی هستند با این تفاوت که مختصات نقاط موردنظر کمی متفاوتتر انتخاب میشوند. درواقع بجای اینکه مختصات آنها بر روی یک خط مستقیم قرار بگیرند به شکل دایرهوار خواهند بود.
cx، cy و r یا radius خارجیترین نقطهی دایره را با ایستگاه (stop-point) صددرصد تعریف میکنند. Fx و fy نیز بهعنوان مشخص کنندهی نقطهی کانونی دایره با شاخص ۰٪ این value ها را بر روی نقشه تعیین میکنند.
<stop>
این تگ را در خودِ گرادینت بکار میبریم. Value های اتریبیوت مربوط به <stop> مشخصکنندهی رنگ، مکان و میزان شفافیت گرادینت است. بازهی رنگی برای یک گرادینت میتواند ترکیبی از دو یا چندین رنگ باشد و هرکدام از این رنگها بهوسیلهی یک تگ <stop> مشخص میشوند. اتریبیوت «offset» نقاط شروع و پایان این رنگها را در هر گرادینت تعیین میکند. درواقع offset نقطهی تغییر رنگ در یک گرادینت است.
برای گرادینتهای خطی این نقطه، فاصلهای است تا خط گرادینت و برای گرادینت شعاعی، این موقعیت فاصلهای است از نقطهی کانونی تا لبهی دایرهی ترسیم شده.
stop-color (ایستگاه رنگی) رنگهای بکار برده شده در نقاط تغییر رنگ را نشان میدهد و stop-opacity مقدار شفافیت رنگها را در همان نقاط مشخص میکند. بسته به تعداد استاپهای مورد نظرمان میتوانیم تنها با تعداد کمی از آنها تغییر رنگی ملایم و تدریجی داشته باشیم و یا اینکه با قرار دادن نقاط استاپ در نزدیکی هم طرحی را با خطوط متعدد ایجاد کنیم.
<animate>
تگ <animate> این امکان را به ما میدهد که تا اتریبیوت و ویژگی (property) های موردنظر خود را برای گرادینت انتخاب کنیم و سپس برای مدتزمانی مشخص به آن value های مختلفی برای اجرا شدن دهیم. درواقع با این کار میتوانیم باعث به حرکت درآمدن آنها شویم. تگ <animate> با المنت موردنظر ما همنشین شده و آن را با خود به حرکت درمیآورد. در زیر ساختاری ابتدایی از اعمال انیمیشن بر روی یک مستطیل را مشاهده میکنید:
<defs> <radialGradient id="smallGradient" fy="90%"> <stop offset="0%" stop-color="#f4c708"></stop> <stop offset="100%" stop-color="#f7e69a"></stop> <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" /> </radialGradient> <radialGradient id="largeGradient" fy="90%"> <stop offset="0%" stop-color="#ff8806"></stop> <stop offset="100%" stop-color="#d9574a"></stop> <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" /> </radialGradient> </defs>
در این بخش مشاهده میکنید که انیمیشن، مستطیل را در طول محور x بهاندازهی ۴۰۰ پیکسل از نقطهی شروع آن جابجا میکند. مدت زمان تعیین شده برای این انیمیشن، ۵ ثانیه است که پس از به پایان رسیدن، این فرآیند مجدداً تکرار میشود.
Attribute
با بکار بردن اتریبیوتهای مختلف در تگ <animate> هدف خود را مشخص کرده و جزئیات موردنظر را به انیمیشن اختصاص میدهیم.
در ادامه به توصیف اتریبیوتهای بکار رفته در دموهای این مقاله میپردازیم:
attributeName
attributeName نام اتریبیوت موردنظر را برای اعمال انیمیشن معرفی میکند. در کدهای انیمیشن بالا، value ی «x» برای attributeName در نظر گرفتهشده پس ما نیز میتوانیم شکلهای خود را بر روی محور x انیمیشنسازی کنیم.
to, from
اتریبیوتهای «to» و «from» نقاط شروع و پایان value ی اتریبیوت موردنظر را مشخص میکند.
values
برای این تگ، value های مد نظر خود را نوشته و با نقطه ویرگول «;» آنها را از هم تفکیک میکنیم. انیمیشن ساختهشده تمام value های مد نظر ما را در طول مدتزمان تعیین شده اجرا میکند.
اگر یک یا هر دو اتریبیوت «to» و «from» را در یک تگ <animate> قرار دهیم کدهای آنها نادیده گرفته خواهند شد، به این معنی که جای آنها از پیش گرفته شده و دیگر نیازی به بکار بردنشان نیست.
dur
«dur» که خلاصهشدهی کلمهی «duration» است مدتزمان به پایان رسیدن انیمیشن را مشخص میکند.
fill
این اتریبیوت وظیفهی اتصال عناصر شکل موردنظر به گرادینت را بر عهده دارد. هر چند «fill» به رنگ داخلی SVG اشاره میکند اما در بستر اتریبیوت <animate> رفتاری متفاوت دارد. با انتخاب value ی «freeze» برای این اتریبیوت، انیمیشن تنها برای یک بار اجرا میشود و سپس از حرکت بازخواهد ایستاد.
repeatCount
اتریبیوت «repeatCount» تعداد دفعات تکرار یک انیمیشن را مشخص میکند. value ی آن میتواند عدد و یا «indefinite» به معنای «نامحدود» انتخاب شود.
انیمیت کردن گرادینت (Animating Gradients)
برای انجام این کار باید بدانیم که دقیقاً قصد انیمیت کردن چه چیزی را داریم. ایستگاه رنگ (stop-color)، محدودهی رنگها (offset) و یا مختصاتی خاص.
مثلاً برای انیمیت کردن مستطیل بالای <animate> قرار داده شده در شکلهای موردنظر از <rect> استفاده میکنیم. بهمنظور انیمیت کردن ایستگاه (stop) های گرادینت، تگ <animate> را در <stop> موردی نظری که قصد انیمیت کردن آن را داریم قرار میدهیم. برای اینکه اتریبیوتی از جمله مختصات گرادینت را بهطور مستقیم در <linearGradient> یا <radialGradient> انیمیت کنیم، تگ <animate> را درون گرادینت و البته خارج از تگ <stop> قرار میدهیم.
اکنون نگاهی به ساختاری از انیمیشن «stop-color» اعمال شده بر روی تگ <stop> میاندازیم.
<stop offset="0%" stop-color="#f4c708"></stop> <stop offset="100%" stop-color="#f7e69a"></stop> <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" />
Demo
برای درک بهتر انیمیت کردن گرادینت (گرادینت) های SVG به تحلیل چند دمو شامل این گرادینتهای متحرک میپردازیم.
دمو شماره ۱: آتش
همانطور که در تصویر مشاهده میکنید هدف ما انیمیت کردن دو شعله است و در بخش کدهای آن میبینیم که تمام جزئیات بین تگ <defs> و در تگ <svg> نوشته شدهاند.
<defs> <radialGradient id="smallGradient" fy="90%"> <stop offset="0%" stop-color="#f4c708"></stop> <stop offset="100%" stop-color="#f7e69a"></stop> <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" /> </radialGradient> <radialGradient id="largeGradient" fy="90%"> <stop offset="0%" stop-color="#ff8806"></stop> <stop offset="100%" stop-color="#d9574a"></stop> <animate attributeName="fy" dur="700ms" from="90%" to="0%" repeatCount="indefinite" /> </radialGradient> </defs>
در اینجا دو گرادینت شعاعی به نامهای «smallGradient» و «largeGradient» میبینیم. انیمیشنهایی یکسان بر روی هرکدام از گرادینت ها اعمال شده که هدف، مختصات fy و حرکت دادن آن از ۹۰% به ۰% در مدت ۷۰۰ میلیثانیه است. انیمیشن بر روی حالت «indefinite» یا همان نامحدود تنظیم شده است.
مأموریت انجام این گرادینتها با اضافه کردن ID به «fill» مربوط به شکل از طریق یک URL به پایان میرسد. بهعنوانمثال:
fill="url(#largeGradient)"
دمو شماره ۲: درخت
برای این دمو، انیمیشن را به گرادینت «stop-color» اضافه میکنیم. دو گرادینت برای نشان دادن رنگهای مختلف این درختها وجود دارد، یکی سایههای تیرهی رنگ سبز و دیگری روشنایی. هر دو روشنایی اساساً یکسان هستند و تنها تفاوت آنها انتخاب رنگشان است.
<defs> <linearGradient id="darkGradient" x1="30%" y1="70%"> <stop offset="0%" stop-color="#0b2d13"> <animate attributeName="stop-color" values="#0b2d13; #79c98c" dur="3s" fill="freeze" /> </stop> <stop offset="100%" stop-color="#79c98c"> <animate attributeName="stop-color" values="#79c98c; #0b2d13" dur="3s" fill="freeze" /> </stop> </linearGradient> <linearGradient id="lightGradient" x1="30%" y1="70%"> <stop offset="0%" stop-color="#054f16"> <animate attributeName="stop-color" values="#054f16; #91bc9c" dur="3s" fill="freeze" /> </stop> <stop offset="100%" stop-color="#91bc9c"> <animate attributeName="stop-color" values="#91bc9c; #054f16" dur="3s" fill="freeze" /> </stop> </linearGradient> </defs>
تگ <animate> برای هر گرادینت بر روی نقطهی ۱۰۰% تنظیم شده و ایستگاه رنگی (stop-color) را مورد هدف قرار داده است. value های رنگ، توسط اتریبیوتهای آن انیمیت شدهاند. مدتزمان حرکت آن ۳ ثانیه است و پس از انجام یک دوره به دلیل استفاده از «freeze» از حرکت باز میایستد.
دمو شماره ۳: آسمان
زمانی که میخواهیم انیمیت کردن محدودهی رنگ (offset) یک نقطه را نشان دهیم، غروب خورشید مثال مناسبی است. در این بخش دو گرادینت داریم که هرکدام شامل یک سری از تغییرات رنگ انیمیت شده میشوند. با انیمیت کردن محدودهی رنگ، نقطهی ایستگاه آن از ۱۰۰% به ست پایین (۰%) حرکت میکند و سپس همین مسیر را به سمت بالا برمیگردد.
<defs> <linearGradient id="skyGradient" x1="100%" y1="100%"> <stop offset="0%" stop-color="lightblue" stop-opacity=".5"> <animate attributeName="stop-color" values="lightblue;blue;red;red;black;red;red;purple;lightblue" dur="14s" repeatCount="indefinite" /> </stop> <stop offset="100%" stop-color="lightblue" stop-opacity=".5"> <animate attributeName="stop-color" values="lightblue;orange;purple;purple;black;purple;purple;blue;lightblue" dur="14s" repeatCount="indefinite" /> <animate attributeName="offset" values=".95;.80;.60;.40;.20;0;.20;.40;.60;.80;.95" dur="14s" repeatCount="indefinite" /> </stop> </linearGradient> </defs>
برای انیمیشنهای stop-color لیستی از value هایی برای گرادینت وجود دارد که سیکل آن بر روی ۱۴ ثانیه تنظیمشده است. انیمیشن اجراشده بر روی محدودهی رنگها (offset) نیز موقعیت مکانی ایستگاه رنگی (stop point) را از ۱۰۰% بهوسیلهی یک سری value های عددی در همان بازهی زمانی ۱۴ ثانیه تغییر میدهد.
لازم به ذکر است که شما باید توانایی لازم را برای استفادهی درست و دقیق از درصدها به هنگام انیمیت کردن «offset» را داشته باشید و این کار را بدون هیچ مشکلی در Firefox، Chrome و safari انجام دهید ولی باید توجه داشته باشید که اگر درصدها را برای value های داخل تگ <animate> قرار دهید در مرورگر نتیجهی کار خود را نخواهید دید. در نمونه کدهای بالا میبینیم که چطور میتوان از قرار دادن درصدها خودداری کرد.
با استفاده از نکات گفتهشده در این مقاله و دموهای بکار برده شده میتوانید طریقهی انیمیت کردن SVG gradients را بهوضوح مشاهده کنید.