ساخت ناوبری دایره ای با SVG

هفته گذشته CIRCULUS.SVG – تولید کننده منوی دایره ای SVG را منتشر کردم. در این مقاله میخواهم بررسی کنم که چرا SVG برای ایجاد این نوع عنصر رابط کاربری مناسبتر است و یک نمای کلی از کد SVG برای ایجاد آیتمهای منو با استفاده از عناصر و تبدیلهای SVG ارائه میدهم.
توجه داشته باشید که بر خلاف آموزش های معمول من، قصد نداریم به جزئیات در مورد نحوه انجام آن بپردازیم، فقط مروری بر مفاهیم پشت آن داریم. ایجاد منو با جزئیات به ریاضیات زیادی نیاز دارد و در سینتکس داده مسیر SVG نیاز دارد، که مستحق یک مقاله جداگانه است. بنابراین برای اختصار، آن را انجام خواهم داد نه من قصد دارم به هر یک از اینها بپردازم، اما به سرعت مفاهیم را مرور خواهم کرد.
اکنون، برای ترسیم بخش ها، البته می توانید به معنای واقعی کلمه من نقاشی می کنم آنها را در یک ویرایشگر گرافیکی مانند Illustrator، Inkscape یا Sketch قرار دهید و سپس گرافیک خود را به صورت SVG صادر کنید، آن را تعاملی کنید و آن را جاسازی کنید. با این حال، از آنجایی که عنوان می گوید “ساختمان”، ما به نحوه ترسیم این عناصر با کد خواهیم پرداخت.
اگر فقط به نتیجه نهایی علاقه دارید – یک منوی دایره ای قابل استفاده، می توانید به ژنراتور بروید و منوی خود را در آنجا ایجاد کنید. در غیر این صورت، بیایید با این شروع کنیم که چرا SVG برای ایجاد منوهای دایره ای بهتر از CSS است.
SVG در مقابل CSS
بیش از یک سال پیش، مقاله ای در مورد Codrops در مورد استفاده از CSS Transforms برای ایجاد ناوبری دایره ای نوشتم. در حالی که این تکنیک کار می کند، با چند اشکال مرورگر و ناهماهنگی همراه است، ناگفته نماند که عملاً هک است – ما مدل جعبه مستطیلی را خم می کنیم تا آیتم های منو را با تاب برداشتن و چرخاندن آیتم های لیست و برش دادن آنها ایجاد کنیم، و سرریز را در ظرف آنها پنهان می کنیم. داخل آیتم های لیست باید “پیچ خورده” باشد و همه چیز کاملاً در جای خود قرار گیرد.
اسکرین شات مراحل لازم برای ایجاد یک منوی دایره ای در CSS را نشان می دهد. نسخه ی نمایشی تعاملی را می توان در مقاله Codrops یافت.
قرار دادن محتوایی غیر از نمادها در منو بسته به نوع محتوا ممکن است دشوار شود. در نهایت، برای فعال کردن منو، باید از پرسشهای رسانهای استفاده کنید و اندازههای مختلف مورد استفاده را برای عرض (و/یا ارتفاع) پنجرههای مختلف تنظیم کنید.
از طرف دیگر، با SVG بسیار متفاوت است.
اشکال در SVG به عنوان عناصر XML معنایی و کاملاً قابل دسترسی مانند ، ، و . و با عناصر طراحی مختلف موجود، SVG کاندیدای عالی برای ترسیم اشکال و عناصر غیر مستطیلی است. و علاوه بر آن، عناصر SVG را می توان استایل و اسکریپت کرد و بنابراین کاملاً تعاملی هستند. این دقیقا همان چیزی است که ما برای منوی دایره ای خود نیاز داریم.
از آنجایی که ما در حال ایجاد برش های دایره ای هستیم – a.k.a بخش ها (نماد: ⌔) – به عنوان آیتم های منو استفاده خواهیم کرد عنصر برای علامت گذاری هر برش به سمت بالا، زیرا دستورات مسیر SVG به ما این امکان را می دهد که با استفاده از دستورات خط و قوس موجود، برش ها را به روشی ساده تر ترسیم کنیم.
کشیدن آیتم های منو در SVG بسیار بسیار ساده تر است. در اینجا یک نسخه ی نمایشی تعاملی است که نشان می دهد آیتم ها چگونه ترسیم و در منو قرار می گیرند. برای دیدن نسخه نمایشی انیمیشن را پخش کنید.
منوی Pen Building A Circular With SVG #2 توسط Sara Soueidan (@SaraSoueidan) را در CodePen بررسی کنید.
در حال حاضر که قطعا بهتر از مراحل انجام شده در css است، درست است؟ SVG همراه با یک دسته از دستورات برای رسم خطوط و کمان است. بیایید نگاهی دقیق تر به دستورات و پارامترهای مورد استفاده برای ترسیم آیتم های منو بیندازیم.
طراحی یک آیتم منو با استفاده از SVG
برای ترسیم بخش های خود به داده هایی نیاز داریم. سپس این داده ها را به آن منتقل می کنیم دستورات به عنوان پارامترهایی که شکل هایی را که می کشیم تعریف می کنند.
یک بخش با سه نقطه، شعاع و زاویه تعریف می شود. برای ترسیم یک بخش با استفاده از SVG عنصر، شما باید مختصات سه نقطه را بدانید. سپس، با استفاده از دستورات مسیر، به مسیر حرکت خواهیم کرد حرکت به مرکز دایره (نقطه اول)، a را بکشید خط به محیط دایره (نقطه دوم)، سپس رسم کنید قوس بیضوی از نقطه دوم به سمت نقطه سوم و بعد از آن جاده را ببند با کشیدن یک خط به مرکز.
تصویر زیر یک تصویر تعاملی است که نحوه ترسیم مسیر را نشان می دهد. برای شروع دمو روی دکمه کلیک کنید.
قلم 24de844274fb139d7eb1702783c9076d توسط Sara Soueidan (@SaraSoueidan) را در CodePen بررسی کنید.
سه نقطه رنگی نقاط مورد نیاز برای ترسیم بخش هستند. پس بیایید چند محاسبات ساده برای تعیین مختصات این نقاط انجام دهیم.
تعیین مختصات نقاط
برای ساخت منوی دایرهای، با یک بوم SVG مربعی شروع میکنیم 500 پیکسل در 500 پیکسل ابعاد بنابراین منو در مرکز آن قرار می گیرد. مرکز دایره در مرکز مربع خواهد بود. شعاع خواهد بود 250 پیکسل. بنابراین نقطه آبی در دمو بالا (نقطه A) دارای مختصات (250px، 250px) و نارنجی (نقطه B) در (500px، 250px) قرار خواهد گرفت.
برای تعیین مختصات نقطه سوم ©، به مقدار زاویه (که بر اساس تعداد آیتم های منو تعیین می شود) نیاز داریم. سپس با استفاده از داده های داده شده و مقادیر سینوس و کسینوس زاویه می توانیم به دست آوریم مختصات قطبی از نقطه سوم را آقای مقدار نقطه صورتی در سیستم مختصات قطبی برابر است با گناه (زاویه) ضرب در شعاع r. را x مقدار برابر است cos (زاویه) ضرب در شعاع r.
را آقای مقدار مختصات قطبی نقطه صورتی در سیستم مختصات قطبی برابر است با گناه(ها) (h/r) برابر شعاع r. را x مقدار مختصات قطبی برابر است با cos (الف) (w/r) برابر شعاع r.
برای داده های مسیری که نیاز داریم مختصات دکارتی از نقطه، به این معنی که اکنون باید مختصات قطبی x و y را به مختصات دکارتی تبدیل کنیم. با استفاده از یک تبدیل ریاضی ساده می توانیم این مختصات را به مختصات دکارتی تبدیل کنیم که مختصات نقطه صورتی را در بوم SVG نشان می دهد. فرمول تبدیل به این شکل است (در JS صحبت می شود):
angleInRadians = -angleInDegrees * Math.PI / 180.0;
x = centerX + radius * Math.cos(angleInRadians);
y = centerY + radius * Math.sin(angleInRadians);
وقتی همه مختصات را داشتید، آماده ترسیم سکتور هستید.
ترسیم خطوط و قوس بخش
با استفاده از SVG عنصر، هر بخش را می توان با استفاده از یک خط SVG ترسیم کرد:
<path fill="transparent" stroke="#111" stroke-width="2" d="M250,250 l250,0 A250,250 0 0,0 466.5063509461097,125 z" />
بخشی که ما به آن علاقه مندیم محتوای آن است d (= داده) ویژگی; این جایی است که مختصات ما استفاده خواهد شد. در اینجا یک تفکیک رنگی از داده های جاده آمده است:
M250,250 l250,0 A250,250 0 0,0 466.5063509461097,125 z
در اینجا از چهار دستور مسیر استفاده می کنیم: م، ل (L کوچک)، الف و z.
اول، حرکت به (M) نقطه با مختصات 250250 – مرکز دایره.
سپس یک را بکشید خط به (l) نقطه ای که روی 250.0 است نسبت به موقعیت فعلی. به عبارت دیگر وقتی به نقطه نارنجی می رویم از مختصات آن نقطه استفاده نمی کنیم. فاصله افقی و عمودی این نقطه را نسبت به موقعیت فعلی – که در این حالت مرکز دایره است – محاسبه می کنیم. با این حال، در صورت استفاده می توانید از مختصات نقطه استفاده کنید L دستور (بزرگ) که با استفاده از مختصات مطلق به جای مختصات نسبی یک خط می کشد.
خوب، با کشیدن یک خط در آن جهت، از مرکز 250 واحد به سمت راست حرکت کنید.
سپس رسم کنید قوس بیضوی (A) تعریف شده توسط: 250.250 0 0.0 (ما در یک لحظه به این موارد باز خواهیم گشت)، از موقعیت فعلی تا نقطه 466.5063509461097.125 – که مختصات دکارتی نقطه صورتی است. حرف بزرگ الف دستور با استفاده از مقادیر مطلق یک قوس رسم می کند. یعنی یک کمان از موقعیت فعلی به موقعیتی که در مختصات مشخص کرده اید رسم می کند و آن مختصات مطلق خواهد بود. نه نسبت به موقعیت فعلی
سپس، بستن جاده (z): یک خط از نقطه صورتی به مرکز کشیده می شود و بخش کامل می شود.
اما این چیه 250.250 0 0.0 بخشی برای همه چیز؟
دستور قوس بیضوی چندین پارامتر را می گیرد: (rx ry-x-axis-rotation-arc-flag-sweep flag-flag x y).
برای منوی گرد ما، 250,250 بخشی شعاع افقی و عمودی را مشخص می کند (rx ry). هر دو مقدار با ترسیم a برابر هستند گرد بخش، بیضوی نیست. آنها را برابر با شعاع دایره ای که روی آن کار می کنید، تنظیم می کنید.
برای اختصار، فعلاً از سه پارامتر بعدی صرف نظر می کنم. چیزی که باید بدانید این است که برای منوی دایرهای ما، باید این سه پارامتر را روی صفر قرار دهید، زیرا در حال رسم کمانهای دایرهای کوچک هستیم.
در نهایت مختصات نقطه ای که قوس به آن کشیده می شود ارائه می شود (x y).
با ترسیم یک بخش، بقیه همان مسیر را دنبال می کنند. هر تعداد بخش که نیاز دارید بکشید. سپس بخشهای باقیمانده به زاویه مورد نیاز چرخانده میشوند تا در امتداد دایره قرار گیرند، همانطور که در نمایش بخش قبل دیدیم.
از آنجایی که تبدیلهای CSS روی عناصر SVG در IE پشتیبانی نمیشوند، من از تبدیلهای SVG بومی برای چرخاندن عناصر استفاده کردم. را transform این ویژگی سه پارامتر دارد: زاویه چرخش و موقعیت x و y مرکز چرخش. مرکز چرخش مرکز دایره در (250 پیکسل، 250 پیکسل) است و زاویه چرخش بر اساس تعداد آیتمهای منو که در رابط کاربری گرافیکی انتخاب میکنید و اینکه منو به صورت دایره کامل یا نیم دایره است، محاسبه میشود.
آیکون ها را به آیتم های منو اضافه کنید
از آنجایی که هر نمادی میتواند چیزی بیش از یک نماد باشد – به عنوان مثال، یک نماد و یک برچسب، یا فقط یک برچسب، بهتر است برای هر محتوایی که در نماد هر عنصر باشد، یک “wrapper” داشته باشید. اولین چیزی که در این مورد به ذهن می رسد استفاده از عنصر گروه است: . با این حال محدودیت های خود را دارد زیرا با الف همراه نیست viewBox ویژگی، و همچنین یک سیستم مختصاتی برای قرار دادن محتویات آن ایجاد نمی کند. گزینه منطقی بعدی استفاده از an است عنصر به عنوان یک پوسته
نمادها توانست پیچیده شود عناصری که یک سیستم مختصات برای محتویات آیکون ایجاد می کنند. همانطور که گفته شد، من ترجیح دادم از این گزینه استفاده نکنم، زیرا هر زمان که میخواهید آیکونها را تغییر دهید یا تغییر دهید، باید دستان خود را با کد کثیف کنید. می خواستم آن را تا حد امکان ساده کنم. به همین دلیل، بهترین گزینه بعدی را انتخاب کردم: و .
الف را می پذیرد viewBox صفت، و می پذیرد width و height ویژگی هایی که به عنوان دریچه دید برای viewBox نشان داده شده در . به این ترتیب ترکیب شده، و چه چیزی را در اختیار ما قرار دهد به ما یک راه مثبت برای جدا کردن تعاریف نماد از استفاده واقعی آنها در سراسر منو داده است. کامل
موقعیت یابی نمادها
ما موقعیتیابی نسبی در SVG نداریم که به ما امکان میدهد یک عنصر را نسبت به عنصر دیگر قرار دهیم، اما میتوانیم از SVGهای تودرتو برای دور زدن این موضوع استفاده کنیم. همانطور که گفته شد، قرار دادن SVG برای قرار دادن نمادها “نسبت” به بخش ها (یا به عبارت دقیق تر: نسبت به یک کانتینر معمولی) بسیار زیاد است، با توجه به اینکه ما می توانیم این کار را به روش دیگری انجام دهیم.
هدف من این بود که نمادها را در مرکز بخش ها قرار دهم و آنها را در یک زاویه بچرخانم تا شبیه چرخش به نظر برسند. با بخش از نظر بصری، نمادها در امتداد یک خط مجازی قرار می گیرند که گوشه بخش را به دو نیم می کند و فراتر از وتر اتصال نقاط نارنجی و صورتی تصویر در بخش قبل نیست.
با استفاده از SVG DOM API میتوانیم منطق بالا را به کد تبدیل کنیم، ابتدا خط تراز مجازی را برای نماد بخش میانی تعریف میکنیم، حداکثر طول آن خط را میتوانیم پس از به دست آوردن نقطه آکوردی که خط مجازی و آکورد را قطع میکنند، مشخص کنیم و سپس از SVG استفاده کنیم. getPointAtLength() روشی برای تعیین اینکه نماد باید در کجای این ردیف قرار گیرد. سپس چیزی که بعد از آن باقی میماند این است که نماد را در نیمه گوشه بخش بچرخانیم و کمی آن را تکان دهیم تا مرکز آن در نقطهای از خطی که میخواهیم قرار گیرد.
دو نقطه سیاه در تصویر بالا موقعیت نماد را در امتداد خط نشان می دهد (که می توانیم از آن استفاده کنیم getPointAtLength()) و تقاطع خط با وتر سکتور. کنترل محدوده در رابط کاربری گرافیکی برنامه، که به شما امکان می دهد موقعیت نماد را در هر عنصر تغییر دهید، در واقع نتیجه را تغییر می دهد. getPointAtLength()، دقت کنید که از نقطه تلاقی با وتر تجاوز نکند.
اتصال در منو
هر آیتم منو شامل مسیری است که شکل بخش و a را نشان می دهد مورد مربوط به الف . این دو عنصر در یک عنصر لنگر پیچیده شده اند: برای ایجاد یک عنصر قابل کلیک
درست مثل HTML عناصر، لنگر SVG نیز دارد href و title ویژگی ها، با یک تفاوت مهم: فضای نام. قبل از بله href و title قطعاتی که باید اضافه کنید xlink فضای نام به طوری که پیوند به صورت زیر مشخص شود:
<a xlink:href="https://www.sarasoueidan.com/blog/building-a-circular-navigation-with-svg/.." xlink:title="https://www.sarasoueidan.com/blog/building-a-circular-navigation-with-svg/.."> <!-- item contents --> </a>
همچنین، ژنراتور منو اضافه می کند role و tabindex ویژگی های دسترسی و این تقریباً تمام چیزی است که برای اقلام نیاز دارید.
درباره سبک و تعامل
در نسخه CSS این منو، رویدادهای اشاره گر در برخی از مرورگرها باگ بودند و z-index برای مقابله با عناصر همپوشانی لازم بود. با SVG و به دلیل ماهیت عناصر SVG، رویدادهای اشاره گر به هر شکلی بدون نیاز به انجام کار اضافی محدود می شوند. از آنجایی که هر شکل مستقل از دیگری است و با هم همپوشانی ندارد، نیازی به پردازش پشته نیست. همه چیز همانطور که انتظار دارید کار می کند.
علاوه بر این، عناصر SVG را می توان در CSS انتخاب و استایل دهی کرد. برای سهولت در استایل دادن به عناصر و نمادها، از افزودن ویژگی های ارائه غیر ضروری اجتناب کردم.
شما می توانید با آیتم های منو تعامل داشته باشید و آنها را به طور مستقل با استفاده از CSS یا جاوا اسکریپت متحرک کنید. این برنامه همراه با یک آموزش است که شامل چندین مثال متحرک با استفاده از جاوا اسکریپت است. من دومی را به جای CSS برای سازگاری مرورگر انتخاب کردم، زیرا باز هم، IE هنوز از تبدیل CSS عناصر SVG پشتیبانی نمی کند.
کلمات پایانی
SVG بسیار قدرتمند است و مسیرهای SVG یکی از قدرتمندترین ویژگی های آن است. ماهیت عناصر SVG به ما انعطاف بیشتری برای ایجاد و متحرک سازی عناصر غیر مستطیلی UI می دهد. و این واقعیت که این عناصر را می توان ترسیم کرد در حالی که معنایی و کاملاً در دسترس هستند به SVG مزیتی برای ایجاد رابط های بصری و عملکردی برتر می دهد.
امیدوارم این مقاله برای شما مفید بوده باشد. ممنون که خواندید.




