SVG برای سازماندهی و ساختاربندی سند، روش مخصوص به خود را دارد. این کار در SVG با عناصر مخصوصی انجام می شود که این عناصر به ما اجازه می دهند تا اشیا را تعریف، گروه بندی و یا بصورت منبع در بیارویم. این عناصر استفاده دوباره از اشیا را ساده می کنند و همچنین باعث می شوند تا کد ما تمیز و خواناتر شود.
در این مطلب این عناصر را تعریف و تفاوت و برتری هر کدام را بیان می کنیم.
گروه بندی با عنصر <g>
g
اول کلمه گروه می باشد. از این عنصر برای گروه بندی عناصری که از نظر منطقی در یک گروه قرار میگیرند استفاده می شود.
در Adobe Illustrator هم معمولا عناصر مرتبط به هم را در یک گروه قرار می دهیم تا مثلا اگر می خواهیم همه را با هم جابجا کنیم یا تغییر اندازه بدهیم این کار برای ما ساده تر و سریع تر باشد.
عنصر <g>
می تواند id
یا class
داشته باشد تا بتوان از آن تغییر در CSS استایل های مورد نیاز را به آن داد.
استایل هایی که به عنصر <g>
داده می شود بر روی عناصر داخلی آن نیز اعمال می شود. منطقی هم هست: دقیقا شبیه به همان تغییر مکان یک گروه در Adobe Illustrator که وقتی گروه را جابجا کنیم کل عناصر جابجا می شوند. پس این مورد کمک می کند تا استایل دهی و حتی اعمال انیمیشن ها به عناصر SVG ساده تر باشد.
به عنوان نمونه پرنده زیر از چندین عنصری که با هم تشکیل یک گروه را داده اند ساخته شده است:
پس اگر بخواهیم در Adobe Illustrator اشکال بالا را به یک گروه تبدیل کنیم می توانیم بصورت زیر عمل کنیم:
گروه بندی در SVG نیز به همین صورت است و از طریق عنصر <g>
انجام می شود. در این مثال ما اشکال مربوط به بدن پرنده را در یک گروه و اشکال مربوط به سر پرنده را در گروه دیگر و در آخر هر دو گروه را درون یک گروه با id
به نام bird
قرار داده ایم:
<svg width="1144.12px" height="400px" viewBox="0 0 572.06 200">
<style>
svg{background-color:white;}
#wing{fill:#81CCAA;}
#body{fill:#B8E4C2;}
#pupil{fill:#1F2600;}
#beak{fill:#F69C0D;}
.eye-ball{fill:#F6FDC4;}
</style>
<g id="bird">
<g id="body">
<path d="M48.42,78.11c0-17.45,14.14-31.58,31.59-31.58s31.59,14.14,31.59,31.58c0,17.44-14.14,31.59-31.59,31.59 S48.42,95.56,48.42,78.11"/>
<path d="M109.19,69.88c0,0-8.5-27.33-42.51-18.53c-34.02,8.81-20.65,91.11,45.25,84.73 c40.39-3.65,48.59-24.6,48.59-24.6S124.68,106.02,109.19,69.88"/>
<path id="wing" d="M105.78,75.09c4.56,0,8.84,1.13,12.62,3.11c0,0,0.01-0.01,0.01-0.01l36.23,12.38c0,0-13.78,30.81-41.96,38.09 c-1.51,0.39-2.82,0.59-3.99,0.62c-0.96,0.1-1.92,0.16-2.9,0.16c-15.01,0-27.17-12.17-27.17-27.17 C78.61,87.26,90.78,75.09,105.78,75.09"/>
</g>
<g id="head">
<path id="beak" d="M50.43,68.52c0,0-8.81,2.58-10.93,4.86l9.12,9.87C48.61,83.24,48.76,74.28,50.43,68.52"/>
<path class="eye-ball" d="M60.53,71.68c0-6.33,5.13-11.46,11.46-11.46c6.33,0,11.46,5.13,11.46,11.46c0,6.33-5.13,11.46-11.46,11.46 C65.66,83.14,60.53,78.01,60.53,71.68"/>
<path id="pupil" d="M64.45,71.68c0-4.16,3.38-7.53,7.54-7.53c4.16,0,7.53,3.37,7.53,7.53c0,4.16-3.37,7.53-7.53,7.53 C67.82,79.22,64.45,75.84,64.45,71.68"/>
<path class="eye-ball" d="M72.39,74.39c0-2.73,2.22-4.95,4.95-4.95c2.73,0,4.95,2.21,4.95,4.95c0,2.74-2.22,4.95-4.95,4.95 C74.6,79.34,72.39,77.13,72.39,74.39"/>
</g>
</g>
</svg>
به عنوان مثال اگر بخواهیم رنگ تمام عناصر داخل بدن را تغییر دهیم کافی است رنگ body
یا همان عنصر گروه بندی را تغییر دهیم و این خیلی کار را ساده می کند.
یا فرض کنید می خواستیم اندازه پرنده را دو برابر کنیم کافی است بصورت زیر عمل کنیم:
#bird {
transform: scale(2);
}
همچنین گروه بندی کارهای تعاملی را راحت تر می کند. زمانی که بخواهیم با کلیک کردن روی پرنده یک اتفاق خاصی بیافتد کافی است فقط این تعامل را برای عنصر <g id="bird">
بنویسیم و دیگر لازم نیست برای تک تک اشکال داخلی آن کار را تکرار کنیم.
یکی دیگر از ویژگی های خوب عنصر <g>
این است که می تواند <title>
و <desc>
مربوط به خود را داشته باشد که از این طریق می توان اطلاعاتی را برای صفحه خوان ها مهیا کنیم که کار ما از لحاظ دسترسپذیری هم بی نقص باشد و همه نوع کاربر بتوانند بخوبی از محصول ما استفاده کنند.
همانطور که از نام این تگ ها پیداست عنوان و توضیحی برای یک گروه از اشکال تعیین می کنند:
<g id="bird">
<title>پرنده</title>
<desc>تصویری از یک پرنده کاکل به سر بی کاکل</desc>
<!-- ... -->
</g>
استفاده دوباره از عناصر توسط عنصر <use>
معمولا در زمان طراحی اشکال و عناصری وجود دارند که نیاز داریم آنها را تکرار کنیم. خب قطعا آنها را دوباره نمی سازیم بلکه آن شکل را کپی می کنیم و از آن دوباره استفاده می کنیم.
عنصر <use>
این عملکرد را که ما در نرم افزارهای گرافیکی داریم در SVG برای ما به ارمغان می آورد. توسط این عنصر می توان یک تک شکل یا گروهی از عناصر (<g>
) را دوباره استفاده کرد.
عنصر <use>
ویژگی هایی از قبیل x
، y
و width
، height
و xlink:href
را دارد.
فرض کنید می خواهیم از پرنده ای که داشتیم یک کپی بسازیم. کافی است id
آن را به ویژگی xlink:href
بدهیم. همینطور مختصاتی که می خواهیم نقطه (0, 0) پرنده دوم داشته باشد را به ویژگی های x
و y
عنصر <use>
می دهیم و آن را در تگ svg
قرار می دهیم:
<use x="100" y="100" xlink:href="#bird" />
توجه داشته باشید ما می توانیم به هر عنصری توسط xlink:href
در عنصر <use>
اشاره کنیم حتی اگر آن عنصر در فایل دیگری باشد.
فرض کنید در مثال ما عنصر درون یک فایل svg دیگر به نام animals.svg
بود در این صورت خواهیم داشت:
<use x="100" y="100" xlink:href="path/to/animals.svg#bird" />
اشاره کردن به فایل های دیگر در بیشتر مرورگر های IE کار نمی کند. در مورد روش های دور زدن این مشکل در مطالب بعد بحث می کنیم.
نکته خیلی مهم اینکه ویژگی های x
و y
کوتاه شده عملیات انتقال یک عنصر توسط ویژگی transform
هستند و همانطور که می دانیم انتقال یک عنصر نسبت به مکانی که هست اتفاق می افتد.
پس کد نوشته شده در بالا برابر این کد می باشد:
<use xlink:href="#bird" transform="translate(100, 100)" />
مورد دیگری که باید در زمان استفاده از عنصر <use>
در نظر داشته باشیم این است که کپی جدید از یک عنصر دیگر تمام استایل ها و تغییر شکل های عنصر اصلی و اولیه را خواهد داشت. پس هر زمان بر روی پرنده اصلی استایل جدید اعمال کنیم پرنده کپی هم آن استایل و تغییر شکل ها را خواهد داشت.
فرض کنید پرنده کپی را از طریق transform
و تابع scale
نصفش کنیم زمانی که اندازه پرنده اصلی هم نصف شود پرنده کپی یک چهارم اندازه اولیه اش می شود.
همچنین این امکان برای ما وجود ندارد تا استایل هایی از قبیل fill
و stroke
عنصر اصلی را override کنیم. آنها برای عنصر کپی بصورت جداگانه قابل تغییر نخواهند بود.
پس اگر می خواهید یک آیکون داشته باشید و از آن آیکون در جاهای مختلف با رنگ های مختلف استفاده کنید نیاز است به خواندن ادامه بدهید :)
استفاده دوباره از عناصر ذخیره شده توسط عنصر <defs>
عنصر <use>
به ما اجازه استفاده دوباره از عنصری را می دهد که رسم شده و نمایش داده می شود. حال اگر بخواهیم یک عنصر را تعریف کنیم ولی آن را نمایش ندهیم و بعدا هر زمانی و هرجایی که خواستیم از آن استفاده کنیم چه؟
اینجا جایی است که عنصر <defs>
وارد می شود.
یک کاربرد عالی برای این عنصر ساختن الگوهای خاص است که نیازی به رسم آنها بطور مستقیم نداریم بلکه عناصر مختلف از آنها درون خود استفاده می کنند.
از طریق <defs>
می توان هر چیزی را تعریف کرد. از یک گروه مثل پرنده ای که ساختیم گرفته تا ماسک ها و گرادینت ها در SVG.
می توان به این عنصر به دید یک تمپلت نگاه کرد که ساخته می شود و هر زمان که نیازش داشته باشیم یک نمونه از آن را در صفحه استفاده و رسم می کنیم. خود تمپلت هیچگاه رسم نمی شود.
در مثال زیر از این عنصر برای تعریف یک گرادینت در SVG استفاده می کنیم و سپس آن گرادینت برای رنگ آمیزی یک مستطیل استفاده می کنیم:
<svg>
<defs>
<linearGradient id="gradient">
<stop offset="0%" style="stop-color: deepPink"></stop>
<stop offset="100%" style="stop-color: #009966"></stop>
</linearGradient>
</defs>
<rect width="200" height="100" stroke="#eee" stroke-width="5" fill="url(#gradient)"></rect>
</svg>
در قسمت قبل به دو مشکل عنصر <use>
اشاره کردیم:
? مکان عنصر کپی شده نسبت به عنصر اصلی تعیین می شد و به آن وابسته بود.
? استایل های عنصر اصلی را نمی توانستیم در عنصر کپی شده بازنویسی و تغییر بدهیم.
و مشکل دیگر اینکه عنصر اصلی هم حتما باید در صفحه رسم میشد.
هیچکدام از این مشکلات در مورد <defs>
وجود ندارد.
به عنوان نمونه فرض کنید پرنده را درون یک <defs>
بنویسیم:
<defs>
<g id="bird" >
<g id="body">
<path d="M48.42,78.11c0-17.45,14.14-31.58,31.59-31.58s31.59,14.14,31.59,31.58c0,17.44-14.14,31.59-31.59,31.59 S48.42,95.56,48.42,78.11"/>
<path d="M109.19,69.88c0,0-8.5-27.33-42.51-18.53c-34.02,8.81-20.65,91.11,45.25,84.73 c40.39-3.65,48.59-24.6,48.59-24.6S124.68,106.02,109.19,69.88"/>
<path id="wing" d="M105.78,75.09c4.56,0,8.84,1.13,12.62,3.11c0,0,0.01-0.01,0.01-0.01l36.23,12.38c0,0-13.78,30.81-41.96,38.09 c-1.51,0.39-2.82,0.59-3.99,0.62c-0.96,0.1-1.92,0.16-2.9,0.16c-15.01,0-27.17-12.17-27.17-27.17 C78.61,87.26,90.78,75.09,105.78,75.09"/>
</g>
<g id="head">
<path id="beak" d="M50.43,68.52c0,0-8.81,2.58-10.93,4.86l9.12,9.87C48.61,83.24,48.76,74.28,50.43,68.52"/>
<path class="eye-ball" d="M60.53,71.68c0-6.33,5.13-11.46,11.46-11.46c6.33,0,11.46,5.13,11.46,11.46c0,6.33-5.13,11.46-11.46,11.46 C65.66,83.14,60.53,78.01,60.53,71.68"/>
<path id="pupil" d="M64.45,71.68c0-4.16,3.38-7.53,7.54-7.53c4.16,0,7.53,3.37,7.53,7.53c0,4.16-3.37,7.53-7.53,7.53 C67.82,79.22,64.45,75.84,64.45,71.68"/>
<path class="eye-ball" d="M72.39,74.39c0-2.73,2.22-4.95,4.95-4.95c2.73,0,4.95,2.21,4.95,4.95c0,2.74-2.22,4.95-4.95,4.95 C74.6,79.34,72.39,77.13,72.39,74.39"/>
</g>
</g>
</defs>
? اولا که پرنده تا زمانی که توسط عنصر <use>
مورد استفاده قرار نگیرد رسم نمی شود.
? دوما اگر به صورت زیر سه عدد پرنده بسازیم هر کدام نسبت به سیستم مختصات خودشان مکان می گیرند و به مکان عنصر اصلی وابسته نیستند، چرا که عنصر اصلی اصلا رسم نشده و مکانی ندارد:
<use xlink:href="#bird" x="50" y="100" />
<use xlink:href="#bird" x="200" y="100" />
<use xlink:href="#bird" x="350" y="100" />
حال می توانیم به پرنده های مختلف رنگ های و استایل متفاوت بدهیم اما به یک شرط:
نباید آن استایل ها در <defs>
برای تمپلت تعریف شده باشند و الا دوباره همان قصه قبلی بوجود خواهد آمد و استایل ها قابل بازنویسی نخواهند بود.
توجه داشته باشید حتی اگر مقدار ویژگی display عنصر <defs>
برابر با none
قرار دهیم باز هم فرزندان داخل آن می توانند توسط عناصر دیگر فراخوانی شده و بر روی صفحه رسم شوند.
گروه بندی با عنصر <symbol>
عنصر <symbol>
هم شبیه به عنصر <g>
است و از آن می توان برای گروه بندی عناصر استفاده کرد. اما دو تفاوت در اینجا وجود دارد:
1. عنصر <symbol>
رسم نمی شود، در واقع شبیه به <defs>
عمل می کند و زمانی نمایش داده می شود که توسط <use>
مورد استفاده قرار بگیرد.
2. عنصر <symbol>
می توان ویژگی های viewBox و preserveAspectRatio مخصوص به خود را داشته باشد.
که این امر باعث می شود تا درون هر فضایی که قرار بگیرد به خوبی متناسب آنجا شود.
در مورد این ویژگی ها در مطالب بعد بصورت مفصل خواهیم گفت.
با توجه به این موارد <symbol>
مناسب ترین راه برای تعریف عناصری هستند که قرار است دوباره مورد استفاده قرار بگیرند.
جمع بندی
در این مطلب با روش های مختلفی برای ساختاردهی به عناصر در SVG و تمیز نگهداشتن کد آشنا شدیم. تفاوت روش های مختلف را نسبت به هم بیان کردیم و همینطور می دانیم که هر کدام از روش ها کاربرد مربوط به خود را دارند که بنا به نیاز از آنها استفاده می شود.
بسیار بسیار عالی
ممنون از شما
منتطر ادامه مطلب هستیم
تشکر
با زبان بسیار ساده و خوبی توضیح داده بودید
سلام
بهترین ادیتور برای فایل SVG چی پیشنهاد میدن ؟
You must set the width and height to display the rect.
جناب سیدی چرا کد میفرستم نمایش نمیده؟
اون مستطیل گرادینت بدون عرض و ارتفاع نمایش داده نمیشه. الان که چند درس جلو رفتم دلیلشو فهمیدم. بهتره کد رو درست کنید که کسایی که تازه کار میکنند و اطلاعاتشون کمه از svg، به مشکل نخورن.
ممنونم، درست شد