چطوری از svg ها تو پروژهات استفاده میکنی؟ جوری که استفاده میکنی چقدر در برابر تغییرات انعطافپذیره؟ چقدر میتونی یه svg رو بارها و بارها استفاده کنی و هر بار تغییرات دلخواه خودت رو روی اون اعمال کنی؟
اگه مستقیما فایلهای svg رو وارد پروژهات میکنی و مثل یه عکس باشون رفتار میکنی، بهتره با خوندن این نوشته یه تجدید نظری روی رفتارت بکنی!
اول میخوام 3 روش کلاسیکی که اکثراً استفاده میشه رو بهت نشون بدم. ?
import React from 'react'; import myLogo from './logo.svg'; const App = () => { return ( <div className="App"> <img src={myLogo} alt="My SVG Logo" /> </div> ); } export default App;
خب این پایهترین حالت استفاده از یک svg هست که به شکل یک عکس باهاش رفتار میشه! قطعا هیچ دسترسی به خود svg نداری و نمیتونی مقادیری مثل رنگ svg رو از داخل کامپوننت خودت تغییر بدی.
import React from 'react'; const App = () => { return ( <div className="App"> <svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1"> <rect width="200" height="100" stroke="black" stroke-width="6" fill="green"/> </svg> </div> ); } export default App;
توی این حالت هم میتونی محتوای فایل svg خودت رو مستقیما داخل یک تگ svg، داخل کامپوننت خودت استفاده کنی. قطعا دسترسی مستقیمی ایجاد میشه که میتونی با اجزای svg خودت بازی کنی و هر پارامتر رو که میخوای تغییر بدی یا ایجاد کنی. اما یه لحظه به حجم کد زیادی که ایجاد میشه فکر کن!
import React from 'react'; import {ReactComponent as MyLogo} from './logo.svg'; const App = () => { return ( <div className="App"> <MyLogo/> </div> ); } export default App;
به به، ببین کی اینجاس! از ریکت 16.3 به اینطرف اضافه شده و میتونی فایلهای svg خودت رو به عنوان یک کامپوننت ریکت، مستقیماً import و استفاده کنی.
? روش اول رو قطعا بدترین روش ممکن خطاب میکنم. فرض کن 100 تا فایل svg داری. باید برای استفاده از اونها، هر 100 تا فایل رو داخل پروژهات قرار بدی. همچنین به این روش، روش static میگن. یعنی svg ها قابل تغییر نیستند و باید هر آنچه که طراح گرافیکی بهت میده رو قرار بدی. نه خبری از تغییر رنگ هست، نه خبری از تغییراتی که تو مدنظرته.
فرض کن قراره از آیکونت که به صورت svg عه، چندین جا استفاده کنی که رنگهای مختلفی دارند. همچنین قراره className های مختلفی بهشون بدی تا حساس به رخدادهای خاصی مثل hover باشند. میخوای چکار کنی؟ تو رو با اعمال زشتی که تا الآن انجام میدادی تنها میذارم. ?
? روش دوم رو به عنوان کثیفترین حالت انتخاب میکنم. خب OK! تو کل محتوای xml از فایل svg خودت رو داری و میتونی هر آشی که میخوای رو باهاش بپزی و تغییرش بدی. اما نهایتا با حجم زیادی از کدهای کثیف رو به رو میشی!
اگه کتابهای مرتبط با مبحث Clean Code رو خونده باشی، میدونی که این روش اصلا منطقی نیست! چون ممکنه از یک آیکون یا لوگو که به صورت svg هست، چندین جا استفاده کنی و قطعا copy و paste کردن جالب نیست. ممکنه داخل یک کامپوننت از تعداد زیادی svg استفاده کنی که منجر به افزایش حجم کد کامپوننتت بشه.
? و اما روش سوم که خیلی مورد استفاده قرار میگیره اما باز هم مطابق میل من نیست. من این روش رو جاده خاکی حساب میکنم و نظرم اینه که باز هم تا جاده آسفالتی که قراره در ادامه بهش برسیم فاصله داره! دلیلش اینه که بازم پارامترهایی که از svg نیاز داری تغییر بدی رو نمیتونی دستکاری کنی.
برای مثال اگه بخوای یک صفت مشخص از svg خودت رو تغییر بدی، دسترسی مستقیم به مقدار اون نداری.
هدف، ایجاد یک کامپوننت مرجع برای کل svg های ماست که بتونیم هر کدوم از اونها رو که میخوایم، فراخوانی کنیم و مقادیر دلخواه صفتهای svg رو بهش بدیم. بیایید از روش دوم هم کمک بگیریم؛
یک فایل SVG.jsx حاوی یک svg xml رو ایجاد میکنیم و چند svg property رو به عنوان props ورودی مشخص میکنیم:
import React from 'react'; const SVG = ({ name = ' ', style = { }, fill = '#000000', viewBox = ' ', width = ' ', className = ' ', id = ' ', stroke = ' ' }) => ( <svg width={width} style={style} className={className} xmlns="http://www.w3.org/2000/svg" viewBox={viewBox} xmlnsXlink="http://www.w3.org/1999/xlink" id={id} > </svg> ); export default SVG;
چی میخوای return کنی؟ قطعا یدونه svg که نیست! پس یه تابع بنویس و داخلش handle کن که بر اساس مقدار name به عنوان prop ورودی (میتونی از اسمهای دیگه مثل moz، khiar و ... استفاده کنی ?)، کدوم svg رو برگردونی. حالا ما اینجا یک function به اسم getSVG ایجاد میکنیم:
من به ازای دو مقدار circle و rectangle، دو svg ساده رو قرار دادم که در ادامه میتونی نتیجه کار رو ببینی.
import React from 'react'; const getSVG = name => { switch (name) { case 'circle': return( <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /> ); case 'rectangle': return( <rect width="200" height="100" stroke="black" stroke-width="6" fill="green"/> ); default: return <path /> } } const SVG = ({ name = ' ', style = { }, fill = '#000000', viewBox = ' ', width = ' ', className = ' ', id = ' ', stroke = ' ' }) => ( <svg width={width} style={style} className={className} xmlns="http://www.w3.org/2000/svg" viewBox={viewBox} xmlnsXlink="http://www.w3.org/1999/xlink" id={id} > {getSVG(name)} </svg> ); export default SVG;
و حالا جایی که میخوایم ازش استفاده کنیم:
import SVG from './SVG';
<SVG name="circle" /> <SVG name="rectangle" />
نتیجه رو با هم ببینیم:
ما به چیزی که میخواستیم رسیدیم و تموم svg هامون رو حالا داخل یک کامپوننت داریم. وقتشه از props های ورودیمون هم استفادههایی بکنیم تا مثلا بتونیم به svg ها کلاس بدیم، رنگشون رو عوض کنیم و ...
برای مثال من اینجا مقدار fill و stroke رو از prop ورودی به اسم styles قرار میدهم.
import React from 'react'; const getSVG = (name, styles) => { switch (name) { case 'circle': return( <circle cx="50" cy="50" r="40" stroke={styles.stroke} stroke-width="3" fill={styles.fill} /> ); case 'rectangle': return( <rect width="200" height="100" stroke={styles.stroke} stroke-width="6" fill={styles.fill}/> ); default: return <path /> } } const SVG = ({ name = ' ', style = { }, fill = '#000000', viewBox = ' ', width = ' ', className = ' ', id = ' ', stroke = ' ' }) => ( <svg width={width} style={style} className={className} xmlns="http://www.w3.org/2000/svg" viewBox={viewBox} xmlnsXlink="http://www.w3.org/1999/xlink" id={id} > {getSVG(name, {fill, stroke})} </svg> ); export default SVG;
و حالا جایی که میخوایم ازش استفاده کنیم:
import SVG from './SVG';
<SVG name="circle" fill="blue" stroke="red"/> <SVG name="rectangle" fill="#fff000"/>
نتیجه رو با هم ببینیم:
پس دیدیم که با واحد کردن کامپوننت SVG و انتخاب ورودیهایی مثل width، class، viewBox، fill و stroke ، میتونیم به راحتی و نامحدود به svg ها دسترسی داشته باشیم و هر کدوم رو به هر شکلی که میخوایم شخصیسازی کنیم.
این بود چرای اینکه از این روش استفاده کنیم. قطعا پروژههای با کیفیت، دیزاینرهای با کیفیت دارند و دیزاینرهای با کیفیت، لوگوها، آیکونها و تصاویر با کیفیتی خلق میکنند. ما نیاز داریم تا بدونیم با svg ها چطور رفتار کنیم تا نتیجه رو به بهترین شکل ممکن نزدیک کنیم و از طرفی تیم توسعه رو در مسیری درست قرار بدیم. امیدوارم تونسته باشم به افزایش دانایی کسایی که به این قضیه نیاز داشتند، کمکی کرده باشم.
و در آخر خوشحال میشم نظرات خودت رو باهام به اشتراک بذاری.
ممنون از چشمهای خوشگلت که تا اینجا این نوشته رو همراهی کرد. ?