Category: طراحی سایت

انیمیشن های پیشرفته با استفاده از CSS – Smashing Magazine

خلاصه سریع ↬
امروز، شما یاد خواهید گرفت که چگونه یک مسیر ترن هوایی ایجاد کنید که توپ با استفاده از بزیرهای مکعبی و انتقال CSS دنبال می کند. شما همچنین خواهید آموخت که چگونه cubic-bezier تابع در CSS با جزئیات کار می کند و چگونه می توان چندین انیمیشن ساده را برای ایجاد یک انیمیشن پیچیده روی هم قرار داد.

توجه داشته باشید: این مقاله فرض می کند که شما دانش اولیه انیمیشن های CSS را دارید. اگر این کار را نمی کنید، لطفاً قبل از ادامه این مقاله، این راهنمای تام واترهاوس را بررسی کنید.

ایجاد انیمیشن های CSS پیشرفته برای اهداف UX و طراحی عالی است. شما می توانید یک وب سایت تعاملی بسازید که بازدید کننده را خوشحال کند و باعث شود وب سایت شما را به خاطر بسپارد. انیمیشن‌ها موضوع سختی به نظر می‌رسند، اما زمانی که آنها را درک کردید، می‌توانید وب‌سایت‌های شگفت‌انگیزی مانند آن ایجاد کنید این یکی! بله، این فقط با CSS ایجاد می شود!

ابتدا بیایید به جادو و قدرت آن شیرجه بزنیم cubic-bezier عملکرد.

cubic-bezier: چیست و چگونه می توانیم از آن استفاده کنیم؟

در cubic-bezier تابع در CSS یک تابع آسان‌کننده است که به شما کنترل کاملی بر نحوه رفتار انیمیشن شما با توجه به زمان می‌دهد. در اینجا تعریف رسمی است:

«یک تابع آسان‌کننده مکعبی Bézier یک نوع است عملکرد تسهیل با چهار عدد واقعی تعریف می شود که دو نقطه کنترل P1 و P2 یک منحنی مکعبی بزیه را مشخص می کند که نقاط انتهایی P0 و P3 به ترتیب در (0، 0) و (1، 1) ثابت هستند. مختصات x P1 و P2 به محدوده محدود شده است [0, 1]”

– پیش نویس پیشنهادات نامزد W3C سطح 1 توابع تسهیل CSS، 1 آوریل 2021

اگر می‌خواهید درباره عملکردهای آسان‌سازی اطلاعات بیشتری کسب کنید، می‌توانید این مقاله توسط Adrian Bece را بررسی کنید. پشت صحنه چقدر خطی است، cubic-bezier و توابع راه پله کار می کنند.

(پیش نمایش بزرگ)

محور x (زمان) بین محدود شده است [0,1]. با این حال، محور y (خروجی) به محدوده خاصی محدود نمی شود.

هدف ما برای مکعب بیزیر ایجاد سهمی کشویی در ابتدای انیمیشن مورد نیاز است. اما برای اینکه به آنجا برسیم، از کوچک شروع می کنیم و یاد می گیریم که چگونه یک منحنی سهموی با استفاده از مکعب بزیر ایجاد کنیم.

منحنی سهمی

از تعریف منحنی سهموی، ممکن است متوجه شوید که ایجاد یک منحنی سهموی کامل غیرممکن به نظر می رسد زیرا P0 باید در (0، 0) و P3 باید در (1، 1) باشد در حالی که منحنی های سهمی در همان محور افقی شروع و پایان می یابند. ، بنابراین ما باید P3 در (1، 0) باشد.

(اعتبار تصویر: ) (پیش نمایش بزرگ)

درست است که ما نمی توانیم یک سهمی کامل بسازیم. با این حال، ما می توانیم چیزی نزدیک به آن ایجاد کنیم.

ایجاد توپ

ما باید یک شی بسازیم که برای انیمیشن خود مدل کنیم، من یک توپ را انتخاب کردم زیرا ساده است، اما البته شما آزاد هستید که از هر شیئی که می خواهید استفاده کنید.

کد زیر را به فایل های HTML و CSS خود اضافه کنید:

<div class="ball"></div>
.ball {
  background-color: burlywood;
  height: 50px;
  width: 50px;
  border: 1px solid black;
  border-radius: 50px;
  position: fixed;
  left: 10px;
  top: 300px;
}

شما باید چیزی شبیه به این دریافت کنید:

(پیش نمایش بزرگ)
بیشتر بعد از پرش! ادامه مطلب زیر ↓

حرکت توپ در امتداد محور X

ما می خواهیم دو انیمیشن بسازیم، یکی در محور x و دیگری در محور y. انیمیشن محور x یک انیمیشن خطی است که توپ را از یک نقطه به نقطه دیگر حرکت می دهد.

  • یک فریم کلیدی اضافه کنید، آن را x می نامیم:
@keyframes x {
  to {
    left: 500px;
  }
}
  • فریم کلیدی را به ویژگی انیمیشن در کلاس توپ اضافه کنید:
.ball {
  background-color: burlywood;
  height: 50px;
  width: 50px;
  border: 1px solid black;
  border-radius: 50px;
  position: fixed;
  left: 10px;
  top: 300px;
  animation: x 2s linear forwards;
}

حالا توپ در امتداد محور x حرکت می کند!

قلم را ببینید [x-axis animation](https://codepen.io/smashingmag/pen/qBxawvO) توسط یسرا عماد.

قلم را ببینید انیمیشن محور x توسط یسرا عماد.

حرکت توپ در امتداد محور Y

برای انیمیشن در امتداد محور y، می خواهیم توپ در امتداد یک منحنی حرکت کند. آخرین نقطه در محور y همان نقطه اولیه است. با این حال، برای اینکه انیمیشن اجرا شود، باید تفاوت کوچکی در محور y ایجاد کنیم. بنابراین، در مورد ما، ما را تغییر خواهیم داد top ویژگی کلاس توپ از 300 تا 299.5.

توجه کنید که چگونه ما کاهش یافته مقدار ویژگی بالا؛ این باعث می شود انیمیشن ما در جهت عادی حرکت کند (پایین → بالا → پایین). اگر به جای آن مقدار ویژگی top را به 300.5 افزایش دهیم، انیمیشن را در جهت مخالف پخش می کند:

@keyframes y {
  to {
    top: 299.5px;
  }
}
  • فریم های کلیدی جدید را به همان انیمیشن در کلاس توپ اضافه کنید
animation: x 2s linear forwards, y 2s cubic-bezier(0, 500, 1, 500) forwards;

این انیمیشن حاصل می شود:

قلم را ببینید [y-axis animation](https://codepen.io/smashingmag/pen/mdXRzRW) توسط یسرا عماد.

قلم را ببینید انیمیشن محور y توسط یسرا عماد.

اما چرا ما این مقادیر مشخص تابع مکعب بیزیر را انتخاب کردیم؟ بیایید دریابیم!

🚨 هشدار: ریاضیات در پیش است! 🚨

ریاضیات پشت cubic-bezier عملکرد

یک بزیر مکعبی را می توان با استفاده از فرمول زیر تعریف کرد:

$$P = (1-t)^3P_0 + 3(1-t)^2tP_1 +3(1-t)t^2P_2+t^3P_3$$

ما می خواهیم منحنی ما دقیقاً در 0.5 زمان به اوج برسد. برای انجام این کار، $P_1$ و $P_2$ باید به ترتیب در (0,x) و (1,x) باشند. اگر نمی‌خواهید پیک روی 0.5 باشد، باید موقعیت زمانی $P_0$ و $P_1$ را تغییر دهید. در حال حاضر، ما به ایجاد منحنی در نیمه زمان انیمیشن پایبند هستیم.

اکنون می دانیم که:

$$P_0 = (0.0)، P_1 = (0، X)، P_2 = (1،X)، P_3 = (1،1)$$

با جایگزینی معادله، می توانیم دو معادله مجزا به دست آوریم، یکی برای هر محور:

  1. محور x:

$$X

.ball {
  background-color: burlywood;
  height: 50px;
  width: 50px;
  border: 1px solid black;
  border-radius: 50px;
  position: fixed;
  left: 10px;
  top: 300px;
}

اکنون باید مسیر ترن هوایی را بسازیم. مسیر از دو بخش تشکیل شده است:

  1. قسمت کشویی
  2. قسمت حلقه
(پیش نمایش بزرگ)

قسمت کشویی

ایجاد بخشی که توپ در آن می لغزد را می توان با استفاده از تابع مکعب-بزیر انجام داد! این انیمیشن از 2 انیمیشن تشکیل شده است، یکی در امتداد محور x و دیگری در امتداد محور y. انیمیشن محور x یک انیمیشن خطی معمولی در امتداد محور x است. می توانیم فریم های کلیدی آن را به صورت زیر تعریف کنیم:

@keyframes x {
  to {
    left: 500px;
  }
}

به صورت زیر آن را به ویژگی انیمیشن خود در مسیر توپ اضافه کنید:

animation: x 4s linear forwards

انیمیشن محور y همانی است که در آن از تابع مکعب بزیر استفاده خواهیم کرد. اجازه دهید ابتدا فریم های کلیدی انیمیشن را تعریف کنیم. ما می خواهیم تفاوت بین نقطه شروع و نقطه پایان آنقدر کم باشد که توپ تقریباً به همان ارتفاع برسد.

@keyframes y {
  to {
    top: 299.5px;
  }
}

حالا بیایید به تابع مکعب بیزیر فکر کنیم. ما می‌خواهیم مسیرمان به آرامی به سمت راست حرکت کند، سپس وقتی می‌لغزد، باید سریع‌تر پیش رود.

(پیش نمایش بزرگ)
  • حرکت آهسته به سمت راست به این معنی است که P1 در امتداد محور x قرار خواهد گرفت. بنابراین، ما می دانیم که در (V, 0) است
    • باید یک V مناسب انتخاب کنیم که باعث شود انیمیشن ما به آرامی به سمت راست برود اما نه خیلی زیاد که کل فضا را اشغال کند. در این مورد متوجه شدم که 0.55 بهترین تناسب را دارد
  • برای دستیابی به اثر لغزشی، باید P2 را به سمت پایین محور y حرکت دهیم (مقدار منفی) بنابراین P2=(X, -Y)
    • Y باید یک مقدار بزرگ باشد. در این مورد، Y=800 را انتخاب کردم
    • برای بدست آوردن X، می دانیم که سرعت انیمیشن ما باید در هنگام لغزش سریعتر و در هنگام بالا رفتن دوباره کندتر باشد. بنابراین، هر چه X به صفر نزدیک‌تر باشد، انیمیشن شیب‌دارتر می‌شود. در این مورد، X = 0.8 را بگذارید

حالا شما تابع مکعب بیزیر خود را دارید، این کار خواهد بود cubic-bezier(0.55, 0, 0.2, -800).

بیایید فریم های کلیدی را به ویژگی انیمیشن خود اضافه کنیم:

animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards;

این اولین قسمت از انیمیشن ما است، بنابراین تاخیر انیمیشن صفر است. ما باید یک ویژگی animation-delay اضافه کنیم زیرا از انیمیشن بعدی، انیمیشن ها در زمانی متفاوت از انیمیشن اول شروع می شوند.

animation-delay: 0s, 0s;

توجه داشته باشید: اگر در مورد مقادیر تابع مکعب بیزیر مطمئن نیستید، می توانید بررسی کنید این وب سایت جایی که می‌توانید مکعب‌بزیرها را تجسم کنید و ایده بگیرید که P0 و P1 باید در کجا باشند.

افزودن یک انیمیشن در امتداد محور X

قبل از ایجاد حلقه، توپ باید برای مدت کوتاهی در امتداد محور x حرکت کند تا بین هر دو انیمیشن فاصله وجود داشته باشد. بنابراین، بیایید این کار را انجام دهیم!

@keyframes x2 {
  to {
    left: 600px;
  }
}
  • آن را به ویژگی انیمیشن اضافه کنید:
animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards;

این انیمیشن باید بعد از انیمیشن کشویی شروع شود و انیمیشن کشویی چهار ثانیه طول می کشد، بنابراین تاخیر انیمیشن چهار ثانیه خواهد بود:

animation-delay: 0s, 0s, 4s;

نتیجه

قلم را ببینید [rollercoaster part 1](https://codepen.io/smashingmag/pen/JjpEmLG) توسط یسرا عماد.

قلم را ببینید ترن هوایی قسمت 1 توسط یسرا عماد.

قسمت حلقه

برای ایجاد یک دایره (حلقه) در CSS، باید دایره را به مرکز حلقه منتقل کرده و انیمیشن را از آنجا شروع کنیم. ما می خواهیم شعاع دایره 100 پیکسل باشد، بنابراین موقعیت دایره را به تغییر می دهیم top: 200px (300 – شعاع دلخواه). با این حال، این باید پس از انجام انیمیشن کشویی اتفاق بیفتد، بنابراین انیمیشن دیگری با مدت زمان صفر ثانیه ایجاد می کنیم و تاخیر انیمیشن مناسب را اضافه می کنیم.

@keyframes pointOfCircle {
  to {
    top: 200px;
  }
}
  • این را به لیست انیمیشن های با مدت زمان = 0 ثانیه اضافه کنید
animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards,
    pointOfCircle 0s linear forwards;
  • تاخیر انیمیشن را اضافه کنید که 4.5 ثانیه خواهد بود
animation-delay: 0s, 0s, 4s, 4.5s;

خود حلقه

برای ایجاد یک انیمیشن حلقه:

  • یک فریم کلیدی ایجاد کنید که توپ را به موقعیت قبلی برمی گرداند و سپس توپ را می چرخاند:
@keyframes loop {
  from {
    transform: rotate(0deg) translateY(100px) rotate(0deg);
  }
  to {
    transform: rotate(-360deg) translateY(100px) rotate(-360deg);
  }
}
  • فریم های کلیدی حلقه را به ویژگی انیمیشن اضافه کنید:
animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards,
    pointOfCircle 0s linear forwards, loop 3s linear forwards;
  • تأخیر انیمیشن را اضافه کنید که در اینجا نیز 4.5 ثانیه خواهد بود:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s;
(پیش نمایش بزرگ)

حرکت دادن توپ در امتداد محور X (دوباره)

ما تقریباً تمام شده ایم! فقط باید توپ را بعد از انیمیشن در امتداد محور x حرکت دهیم تا توپ دقیقاً بعد از حلقه متوقف نشود، همانطور که در تصویر بالا انجام می شود.

@keyframes x3 {
  to {
    left: 1000px;
  }
}
  • فریم های کلیدی را به ویژگی انیمیشن اضافه کنید:
animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -800) forwards, x2 0.5s linear forwards,
    pointOfCircle 0s linear forwards, loop 3s linear forwards,
    x3 2s linear forwards;
  • با اضافه کردن تاخیر مناسب، در اینجا 7.5 ثانیه خواهد بود:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s, 7.5s;

خروجی نهایی

قلم را ببینید [rollercoaster](https://codepen.io/smashingmag/pen/oNEBadz) توسط یسرا عماد.

قلم را ببینید ترن هوایی توسط یسرا عماد.

نتیجه

در این مقاله به نحوه ترکیب چندین فریم کلیدی برای ایجاد یک مسیر انیمیشن پیچیده پرداختیم. ما همچنین مکعب‌بزیرها و نحوه استفاده از آن‌ها را برای ایجاد عملکرد آسان‌کننده خود توضیح دادیم. من توصیه می کنم ادامه دهید و مسیر انیمیشن خود را ایجاد کنید تا دستان خود را با انیمیشن ها کثیف کنید. اگر به کمک نیاز دارید یا می‌خواهید بازخورد بدهید، می‌توانید به هر یک از آنها پیام ارسال کنید لینک های اینجا. روز/شب فوق العاده ای داشته باشید!

سرمقاله Smashing
(il)
Read More

ژانویه – مه 2022 – مجله Smashing

خلاصه سریع ↬

چه چیزی باعث ایجاد یک سیستم طراحی موفق می شود؟ چگونه می توانید گردش کار تست خود را به سطح بعدی ببرید؟ و چه الگوهای طراحی رابط هوشمند می تواند به شما در بهبود رابط کاربری خود کمک کند؟ بیایید آن را بفهمیم. با ما کارگاه های آنلاین front-end و UX.

ممکن است قبلاً آن را بدانید: ما مرتباً می دویم کارگاه های آنلاین دوستانه در اطراف front-end و UX. و، خوب، ما یک زن و شوهر از موارد جدید هیجان انگیز در راه است در چند ماه آینده شما می توانید به راحتی از روی میز خود به ما بپیوندید، و برای اطمینان از اینکه کارگاه ها با برنامه شلوغ شما مطابقت دارند، هر یک از آنها را به چند دسته تقسیم می کنیم. جلسات 2.5 ساعته در چند روز. به این ترتیب، شما همیشه زمان کافی برای درک همه چیز، امتحان کردن چیزها، تماشای مجدد یک جلسه، و فکر کردن به سوالاتی که دوست دارید در صورت ملاقات مجدد به آنها پاسخ دهید، دارید.

ما بسیار هیجان زده هستیم که اعلام کنیم در ماه های آینده چه چیزی در انتظار شماست. بنابراین، ممکن است ارائه کنیم…

کارگاه های Smashing چگونه هستند

چیزهای زیادی از یک کارگاه Smashing انتظار می رود، اما مهمترین آنها تمرکز روی آن است مثال ها و تکنیک های عملی. کارگاه ها گفتگو نیستند. آن ها هستند جلسات زنده تعاملی، با گفتگو با شما، شرکت کنندگان و گاهی اوقات با چالش ها، تکالیف و کار تیمی.

پانلی از گربه‌های دوستانه، که البته به صورت آنلاین در مورد فرانت‌اند و UX بحث می‌کنند.
فرقی نمی کند که در دفتر هستید، پشت میز آشپزخانه یا روی کاناپه، داخل کارگاه های ما، همه یک مستطیل کمی تار روی صفحه هستند. همه با هم برابرند و برای شرکت دعوت شده اند.

در هر جلسه، همیشه زمان کافی برای طرح سؤالات یا صرف یک فنجان چای وجود دارد. ما در محتوا عجله نمی کنیم، اما سعی می کنیم استقبالی ایجاد کنیم محیطی دوستانه و فراگیر برای همه، با زمان برای فکر کردن، بحث کردن و گرفتن بازخورد. البته تمام مواد کارگاهی و ضبط های ویدئویی همچنین، بنابراین اگر جلسه‌ای را از دست دادید، می‌توانید هر زمان که خواستید دوباره آن را تماشا کنید.

TL; DR

  • دوره کارگاه ها چند روزه، تقسیم به جلسات 2.5 ساعته.
  • زمان کافی برای پرسش و پاسخ زنده هر روز.
  • ده ها نمونه های عملی و تکنیک ها
  • همه مطالب و موارد ضبط شده کارگاه را دریافت خواهید کرد.
  • تمامی کارگاه ها روی front-end و UX متمرکز هستند.
  • یک بسته کارگاهی دریافت کنید برای 3، 5 یا 10 بلیط و بین 255 تا 1250 دلار صرفه جویی کنید.

متشکرم!

یک مخلص متشکرم برای حمایت همیشگی و مهربان شما – برای بودن درهم شکستن، اکنون و همیشه. مفتخریم که در یکی از کارگاه های آینده با شما آشنا شویم.

Read More

مجموعه نمادهای Wayfinding (164 نماد، PNG، SVG، AI، EPS – مجله Smashing

خلاصه سریع ↬

هر چند وقت یکبار، مطالب رایگان مربوط به مناسبت ها و موضوعات مختلف را منتشر می کنیم. ما امیدواریم که با این مجموعه آیکون، هر کسی بتواند مورد استفاده خود را برای این آیکون ها به طور خاص پیدا کند. امروز، ما سه مجموعه آیکون را به شما ارائه می‌کنیم که توسط افراد خلاق GraphicSurf طراحی شده‌اند – همه رایگان برای استفاده شخصی و تجاری.

هر زمان که از مکان‌های جدید بازدید می‌کنیم، اغلب نیاز داریم که به سرعت حرکت کنیم و مسیر درست را پیدا کنیم. در نتیجه راهیابی به بخشی جدایی ناپذیر از معماری مدرن تبدیل شده است. پیمایش می‌تواند با نمادهایی برای درک بصری همراه باشد، و اگر می‌خواهید به افراد کمک کنید تا به طور مؤثرتری پیمایش کنند، تصاویر بصری مکانی عالی برای شروع هستند.

سه کیت ناوبری وجود دارد که توسط گرافیک سرف که می تواند در مکان های مختلف، به عنوان مثال در نمایشگاه ها، کنسرت ها و موزه ها استفاده شود. هر یک از مجموعه های ارائه شده در اینجا شامل ناوبری اولیه به شکل فلش های جهت دار، آسانسور، پله برقی و حتی رمپ برای افراد با تحرک محدود است. همچنین نمادهای ایمنی آتش نشانی شیرهای آتش نشانی و دفتر پزشکی وجود دارد. هر مجموعه همچنین شامل آیکون های تخصصی است که می تواند برای شناسایی مناطق خاصی از یک رویداد خاص استفاده شود. لذت بردن!

یادداشت ویراستار: لطفاً جزئیات مجوز را بررسی کنید. هیچ منبعی لازم نیست، با این حال، فروش مجدد بسته‌ها یا نمادهای فردی جالب نیست. اگر می‌خواهید این موضوع را در پست‌های وبلاگ یا هر جای دیگری منتشر کنید، این کار را راحت انجام دهید، اما لطفاً به خاطر داشته باشید که به طراحان اعتبار دهید و پیوندی به این مقاله ارائه دهید.

بیشتر بعد از پرش! ادامه مطلب زیر ↓

مجموعه نمادهای Wayfinding “Exhibition”

نمونه هایی از 56 نماد نمایشگاه Wayfinding

از نزدیک نگاه کنید 👀 →

نمونه هایی از نمادهای نمایشگاهی

از نزدیک نگاه کنید 👀 →

نمونه هایی از نمادهای نمایشگاهی

از نزدیک نگاه کنید 👀 →

مجموعه آیکون “نمایشگاه” را دانلود کنید

مجموعه نمادهای Wayfinding “Museum”

نمونه هایی از 54 نماد موزه Wayfinding

از نزدیک نگاه کنید 👀 →

مجموعه آیکون “موزه” را دانلود کنید

مجموعه نمادهای Wayfinding “Concert”

نمونه هایی از 54 نماد کنسرت Wayfinding

از نزدیک نگاه کنید 👀 →

مجموعه آیکون “کنسرت” را دانلود کنید

یادداشت ویراستار: یک تشکر بزرگ از افراد خوب GraphicSurf – ما صمیمانه از وقت و تلاش شما قدردانی می کنیم. به کار بی نظیرتون ادامه بدین!

موارد رایگان بیشتر در مجله Smashing

سرمقاله Smashing
(vf، yk، او)

Read More

شیرجه عمیق CSS به گرادیان های شعاعی و مخروطی – مجله Smashing

خلاصه سریع ↬

در این مقاله، ما نگاهی دقیق تر به دو شیب خواهیم داشت: conic-gradient و radial-gradient. خواهید دید که چگونه هر یک از آنها با جزئیات کار می کنند، چه تفاوت ها و شباهت هایی بین آنها وجود دارد، چگونه و کجا از آنها استفاده کنید، و برخی موارد استفاده برای هر کدام.

گرادیان های CSS یک ویژگی مفید CSS است که می تواند برای ایجاد افکت های رابط کاربری جالب یا حتی به ما در ترسیم چیزی بدون نیاز به ایجاد عناصر HTML برای آن کمک کند. دو شیب که می خواهم در این مقاله روی آنها تمرکز کنم عبارتند از conic-gradient و radial-gradient. هر کدام متفاوت عمل می کنند (شیب های مخروطی منحنی هستند، در حالی که گرادیان های شعاعی یک خط مستقیم هستند).

برای دنبال کردن، نیازی به دانستن هیچ کدام ندارید radial-gradient یا conic-gradient. من تمام تلاشم را می کنم که آنها را به خوبی توضیح دهم.

بیایید شیرجه بزنیم!

گرادیان شعاعی چیست؟

از نام آنها، radial-gradients توانایی ترسیم عناصر شعاعی مانند دایره یا بیضی را به ما می دهد.

بیایید به ابتدایی ترین نحو نگاه کنیم.

ابتدایی ترین مثال

در این مثال، ما یک radial-gradient با دو استاپ رنگ این منجر به یک شیب بیضی شکل شد.

.element {
    background: radial-gradient(#9c27b0, #ff9800);
}

گرادیان شعاعی

(پیش نمایش بزرگ)

موارد فوق اساسی ترین هستند radial-gradient می توانیم در CSS انجام دهیم. ممکن است تعجب کنید که چرا به صورت پیش فرض بیضی شد؟ خب بذار توضیح بدم

اگر هیچ نام شکلی در شیب تعریف نشده باشد (دایره یا بیضی)، به طور پیش فرض بیضی خواهد بود در موارد زیر:

  • هیچ اندازه تعیین نشده است.
  • یا، دو مقدار (برای عرض و ارتفاع) وجود دارد.

گرادیان شعاعی چگونه کار می کند؟

من یک سری تصاویر بصری را مرور خواهم کرد که نحوه عملکرد یک گرادیان را با افزایش کلمات کلیدی و اضافات مختلف نشان می دهد.

ابتدا اجازه دهید به مثال اولیه برگردیم.

.element {
    background: radial-gradient(#9c27b0, #ff9800);
}

هنگامی که دو رنگ بدون مشخص کردن شکل وجود دارد، گرادیان به صورت پیش‌فرض بیضی می‌شود، مانند:

شیب بیضی شکل

(پیش نمایش بزرگ)

بیضی عرض و ارتفاع ظرف خود را پر می کند. تار به نظر می رسد زیرا مرورگر فرض کرده است که نقطه شروع و توقف هستند 0% و 100%، به ترتیب.

در اینجا نحوه مشاهده گرادیان توسط مرورگر آمده است:

.element {
    background: radial-gradient(#9c27b0 0%, #ff9800 100%);
}

اگر اضافه کنیم circle قبل از اولین توقف رنگ، اینگونه به نظر می رسد:

.element {
    background: radial-gradient(circle, #9c27b0, #ff9800);
}

گرادیان دایره ای شکل

(پیش نمایش بزرگ)

اکنون که ایده ای در مورد اینکه دایره و بیضی به طور پیش فرض چگونه به نظر می رسند، بیایید وارد این موضوع شویم تثبیت موقعیت.

به طور پیش فرض، هر دوی آنها به صورت افقی و عمودی در ظرف خود در مرکز قرار دارند. به عبارت دیگر، در 50% 50%:

عناصر بیضی و دایره به صورت افقی و عمودی در ظرف خود در مرکز قرار دارند

(پیش نمایش بزرگ)

نکته مهمی که در اینجا باید به آن توجه کرد این است که موقعیت از مرکز دایره یا بیضی اتفاق می افتد، بنابراین یک دایره را در top left، آنچه قرار خواهد گرفت نقطه مرکزی است.

بیایید نگاهی دقیق تر به چند مثال بیندازیم.

.element {
    background: radial-gradient(circle at top left, #9c27b0, #ff9800);
}

گرادیان شعاعی با دایره در بالا سمت چپ

(پیش نمایش بزرگ)

ما همچنین می توانیم آن را در سمت راست وسط قرار دهیم. فقط اضافه کردن right دایره را در مرکز قرار می دهد right 50%:

.element {
    background: radial-gradient(circle at right, #9c27b0, #ff9800);
}

در اینجا به نظر می رسد:

گرادیان شعاعی با دایره در سمت راست

(پیش نمایش بزرگ)

بیشتر بعد از پرش! ادامه مطلب زیر ↓

گرادیان مخروطی چیست؟

در conic-gradient() تابع CSS یک گرادیان ایجاد می کند که به دور مرکز عنصر می چرخد. بیایید یک مثال اساسی را ببینیم.

.element {
    background: conic-gradient(#9c27b0, #ff9800);
}

شیب مخروطی

(پیش نمایش بزرگ)

نگاه کنید که چگونه گرادیان از نقطه مرکزی عنصر شروع می شود. از آن می چرخد 0deg به 360 به صورت پیش فرض.

بیایید ببینیم چه اتفاقی می‌افتد وقتی یک مقدار توقف سخت برای رنگ اول اضافه می‌کنیم.

.element {
    background: conic-gradient(#9c27b0 50%, #ff9800);
}

شیب مخروطی که در آن رنگ اول 50 درصد عنصر را پر می کند، رنگ دوم به تدریج تا 100 درصد نشان داده می شود.

(پیش نمایش بزرگ)

حالا اولین رنگ پر می شود 50% عنصر، در حالی که دومی به تدریج نشان داده می شود 100%.

اگر روی رنگ دوم هم یک استاپ سخت اعمال کنیم چه اتفاقی می‌افتد؟ در قطعه زیر، اولین رنگ پر می شود 50% از عنصر، دومی از آن شروع خواهد شد 50% تا آخر (100%).

.element {
    background: conic-gradient(#9c27b0 50%, #ff9800 0);
}

گرادیان مخروطی که در آن رنگ اول 50 درصد عنصر را پر می کند و رنگ دوم از 50 درصد شروع می شود تا به پایان برسد.

(پیش نمایش بزرگ)

با افزایش اولین مقدار توقف رنگ، پر شدن زاویه ای ایجاد می شود:

.element {
    background: conic-gradient(#9c27b0 65%, #ff9800 0);
}

اولین توقف رنگ تا 65 درصد افزایش می یابد که یک پر شدن زاویه دار را تشکیل می دهد

(پیش نمایش بزرگ)

نه تنها این، بلکه می‌توانیم با استفاده از تابع CSS یک گرادیان تکراری ایجاد کنیم repeating-conic-gradient() همانطور که در زیر نشان داده شده است.

.element {
    background: repeating-conic-gradient(
    #9c27b0 0 15deg,
    #ff9800 15deg 30deg
    );
}

تکه های بالا اولین رنگ را پر می کنند 0deg به 15deg، سپس رنگ دوم از پر می شود 15deg به 30deg. با تکرار، مانند شکل زیر می شود:

Repeating-conic-gradient

(پیش نمایش بزرگ)

استفاده از موارد برای گرادیان شعاعی

اغلب، ما نیاز داریم که یک تصویر یا یک الگو را به عنوان پس‌زمینه اضافه کنیم. در صورت وجود تیتر و/یا متن فرعی، البته ممکن است خواندن آنها دشوار باشد.

radial-gradient در بخش قهرمان

استفاده از شیب بیضی با همان رنگ پس زمینه می تواند به برجسته شدن محتوا کمک کند. در مثال زیر به نحوه همپوشانی محتوا با پس زمینه توجه کنید. تمرکز بر خواندن را کمی سخت می کند تا نگاه کردن به الگو:

نمونه ای از موارد استفاده که در آن محتوا با پس زمینه همپوشانی دارد

(پیش نمایش بزرگ)

یک راه حل معمول برای آن اضافه کردن یک بیضی با همان رنگ پس‌زمینه زیر آن است (تا با آن ترکیب شود).

در اینجا بخش قهرمان با بیضی (رنگی خاکستری، فقط برای اهداف نمایشی) است:

بخش قهرمان با بیضی به رنگ خاکستری

(پیش نمایش بزرگ)

در اینجا نحوه انعکاس آن در CSS آمده است:

.hero {
    background-color: #fbfafa;
    background-image: radial-gradient(#fbfafa, rgba(0,0,0,0) center/70% 70% no-repeat, url("hero-bg.svg");
    background-position: center;
    background-size: 70% 70%, cover;
    background-repeat: no-repeat;
}

و مثالی از یک مورد استفاده که در آن محتوا دیگر با پس‌زمینه همپوشانی ندارد، به دلیل اضافه شدن بیضی با همان رنگ پس‌زمینه زیر.

(پیش نمایش بزرگ)

به این ترتیب، ما الگو را در زیر محتوا پوشش دادیم، اکنون خواندن آن بسیار ساده تر است.

جلوه الگوی نقطه‌ای

برای ایجاد جلوه ای از الگوی نقطه چین می توانیم استفاده کنیم radial-gradient. در اینجا به نظر می رسد:

الگوی نقطه چین

(پیش نمایش بزرگ)

برای رسیدن به آن، می توانیم یک دایره کوچک ایجاد کنیم و بقیه گرادیان شفاف خواهد بود.

در اینجا این است که چگونه به خودی خود به نظر می رسد:

رنگ دایره و بقیه گرادیان رنگ شفاف است.

(پیش نمایش بزرگ)

هنگامی که این الگو تکرار می شود، در اینجا به نظر می رسد:

یک الگوی تکراری با رنگ دایره ای و بقیه گرادیان رنگ شفاف است

(پیش نمایش بزرگ)

برای منعکس کردن آن در CSS، باید یک عرض و ارتفاع برای گرادیان اضافه کنیم. از آنجایی که گرادیان ها به طور پیش فرض تکرار می شوند، به الگوی بالا منجر می شود.

.dot-pattern {
  --color-1: #9c27b0;
  --color-2: rgba(0,0,0,0);
  background-image: radial-gradient(circle at 2px 2px, var(--color-1) 1px, var(--color-2) 0);
  background-size: 15px 15px;
}

جلوه های تصویری

ترکیب شده با mix-blend-mode، گرادیان های شعاعی می توانند جلوه های رابط کاربری جالبی برای تصاویر ایجاد کنند. در مثال زیر، به نحوه قرارگیری دایره در گوشه بالا سمت چپ توجه کنید. ما می توانیم با بازی با حالت های ترکیبی برای رسیدن به یک اثر خاص از آن بهره ببریم.

مثالی که در آن گرادیان شعاعی یک افکت رابط کاربری جالب برای یک تصویر ایجاد می کند.  یعنی دایره در گوشه سمت چپ بالای تصویر قرار دارد که یک گرادیان ایجاد می کند

(پیش نمایش بزرگ)

.thumb:after {
    content: "";
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at top left, #9c27b0, #ff9800);
    mix-blend-mode: hard-light;
    opacity: 0.4;
}

موارد استفاده برای گرادیان مخروطی

نمودارهای پای

اولین مورد استفاده ای که می توانم برای شیب مخروطی فکر کنم نمودارهای دایره ای ساده است. چندی پیش این کاری بود که می‌خواستیم در CSS انجام دهیم، و اکنون به راحتی امکان‌پذیر است.

نمودار دایره ای

یک نمودار دایره ای ساده (پیش نمایش بزرگ)

.pie-chart {
    width: 100px;
    height: 100px;
    background: conic-gradient(from 0deg, #b2daf9 128deg, #2096f3 0);
    border-radius: 50%;
}

پس زمینه ها و الگوها

هزاران امکان برای ایجاد الگوی با شیب مخروطی وجود دارد. برای این مثال، من روی الگوی شطرنجی تمرکز خواهم کرد.

الگوی شطرنجی

یک الگوی شطرنجی 2×2 به دست آمده با conic-gradient(). (پیش نمایش بزرگ)

در اینجا چیزی است که در گرادیان زیر اتفاق می افتد:

  • در #fff رنگ پوشاننده است 90deg از عنصر؛
  • سپس آن را به دنبال دارد #000 به 180deg;
  • سپس آن را به دنبال دارد #fff به 270deg;
  • در نهایت، #000 پر شده تا انتهای زاویه (360deg).
.checkerboard {
    --size: 25px;
    width: 200px;
    height: 100px;
    background-image: conic-gradient(#fff 90deg, #000 0 180deg, #fff 0 270deg, #000 0);
    background-size: var(--size) var(--size);
}

هنگامی که تکرار و کنترل از طریق background-size، شبیه این خواهد شد:

یک الگوی شطرنجی مکرر

پیش نمایشی از الگوی شطرنجی که چندین بار تکرار شده است. (پیش نمایش بزرگ)

نه تنها این، بلکه می‌توانیم با چرخاندن برخی از مقادیر به روشی متفاوت، به جلوه‌های واقعاً جالبی برسیم. به عنوان مثال:

.element {
    background-image: conic-gradient(#fff 90deg, #000 0 136deg, #fff 0 313deg, #000 0);
}

یک الگوی شطرنجی مکرر چرخشی

الگوی تخته چک یکسان، اما متفاوت. (پیش نمایش بزرگ)

الگوهای رابط کاربری

گاهی اوقات، ممکن است نیاز داشته باشیم که یک الگوی رابط کاربری تصادفی ایجاد کنیم که اشکال مختلفی دارد. می توانیم استفاده کنیم conic-gradient برای رسیدن به آن ایده این است که ما اندازه گرادیان را از طریق کنترل می کنیم background-size، و سپس تغییر دهید conic-gradient زاویه برای دستیابی به اثرات مختلف.

ما یک عنصر با عرض و ارتفاع داریم 200px. در این عنصر، پس زمینه را تکرار می کنیم.

.element {
    --size: 20px;
    width: 200px;
    height: 200px;
    background-size: var(--size) var(--size);
}

برای تصور بهتر، هر پس‌زمینه اندازه‌ای دارد 20px هم برای عرض و هم برای ارتفاع و به صورت افقی و عمودی تکرار خواهد شد.

عنصری با عرض و ارتفاع 200 پیکسل و درون این عنصر یک پس زمینه تکراری وجود دارد که اندازه آن 20 پیکسل است.

عنصری (200×200 پیکسل) که دارای پس‌زمینه تکراری با اندازه 20 پیکسل است. (پیش نمایش بزرگ)

حال، هر مربعی که می بینید حاوی یک است conic-gradient. در حال حاضر، من دو سایه آبی اضافه می کنم تا مفهوم را بهتر نشان دهم.

.element {
    --size: 20px;
    width: 200px;
    height: 200px;
    background: conic-gradient(#2296F3 0.13turn, rgba(255,255,255,0) 0);
    background-size: var(--size) var(--size);
}

شیب مخروطی بدون تکرار آن به این صورت به نظر می رسد:

دو مربع با شیب مخروطی آبی به شکل مثلث.  مربع اول دارای پس زمینه آبی تیره و مربع دوم دارای پس زمینه شفاف است

(پیش نمایش بزرگ)

با تکرار، به نظر می رسد این است. حال نکته این است که رنگ دوم را شفاف کنید که به شکل مثلث در می آید.

عنصری با پس‌زمینه تکراری با اشکال مثلثی

(پیش نمایش بزرگ)

با داشتن یک زاویه متفاوت، می توانیم شکل الگو را تصادفی کنیم تا جلوه های جالبی به دست آوریم.

اشکال الگوی مختلف که توسط زوایای مختلف تشکیل می شوند: 0.08 چرخش، 0.03 چرخش و 0.5 دور

(پیش نمایش بزرگ)

متحرک سازی گرادیان های مخروطی با @property

ما می توانیم جلوه های انیمیشن جالبی ایجاد کنیم conic-gradient. با این حال، این به طور پیش فرض امکان پذیر نیست. ما باید از @property تعریف برای تعریف یک ویژگی سفارشی که برای انیمیشن استفاده خواهیم کرد.

@property --conic-mask {
    syntax: '<percentage>';
    inherits: false;
    initial-value: 0%;
}

.conic-mask {
    --conic-mask: 0%;
    -webkit-mask: conic-gradient(from 0deg at 50% 50%, #000 var(--conic-mask), #0000);
    transition: --conic-mask 1s ease-out;
}

.conic-mask: hover {
    --conic-mask: 100%;
}
یک افکت انیمیشن با conic-gradient.

برش گوشه ها با اشکال سفارشی

این نسخه ی نمایشی توسط عفیف را همراهی کنید. ایده این است که استفاده کنید conic-gradient به عنوان ماسک برای ایجاد افکت های برش:

قلم را ببینید [Cut corners with custom shape [forked]](https://codepen.io/smashingmag/pen/jOGKjxQ) توسط عفیف را همراهی کنید.

قلم را ببینید گوشه ها را با شکل دلخواه برش دهید [forked] توسط عفیف را همراهی کنید.

گرادیان های مخروطی

می توانیم استفاده کنیم conic-gradient برای ایجاد افکت‌های گرادیان ظریف که گوشه‌هایی تیره‌تر یا روشن‌تر با رنگ‌های دیگر دارند. Conic.css یک کتابخانه کوچک CSS توسط آدام آرگیل است که دارای شیب های مخروطی دوست داشتنی زیادی است.

شیب مخروطی با رنگ های مختلف

(پیش نمایش بزرگ)

استفاده از گرادیان های مخروطی برای پس زمینه بخش

من این را در نسخه ی نمایشی به اشتراک گذاشته شده توسط اسکات کلوم دیدم. روش کار این تکنیک برای افزودن رنگ جزئی به پاورقی و در عین حال صاف به نظر می رسد را بسیار دوست داشتم.

.footer {
    background: conic-gradient(from 0.25turn at 25% 0%, #FFD9CE, rgba(#FFD9CE, 0) 50%);
}

فوتر Typetura با گرادیان مخروطی

(پیش نمایش بزرگ)

نتیجه

همانطور که دیدید، با استفاده از CSS radial-gradient و conic-gradient توابع می توانند باعث ایجاد رابط های کاربری بسیار جالب (و مفید) شوند. با این حال، در مورد زمان استفاده از هر کدام، هیچ سیاه و سفیدی وجود ندارد. بیشتر اوقات، این بستگی به مورد استفاده در دست دارد.

امیدوارم مقاله برای شما مفید واقع شود. با تشکر فراوان برای خواندن!

خواندن بیشتر در مجله Smashing

سرمقاله Smashing
(vf، yk، او)

Read More

ایجاد یک ورودی محدوده سفارشی که در همه مرورگرها یکسان به نظر می رسد – مجله Smashing

خلاصه سریع ↬

ورودی‌های محدوده معمولاً برای استایل کردن بسیار دردسرساز بوده‌اند. هر مرورگر ورودی را به گونه‌ای متفاوت ارائه می‌کند و از شما می‌خواهد از پیشوندهای فروشنده استفاده کنید تا ظاهر و احساسی منسجم ایجاد کنید. در این مقاله، نگاهی به عجیب بودن ورودی محدوده HTML خواهیم داشت و نحوه استایل دادن به ورودی را به گونه‌ای که در تمام مرورگرهای اصلی یکسان به نظر برسد، نشان خواهیم داد.

من به‌عنوان یکی از نگهدارنده‌های کتابخانه مؤلفه‌های رابط کاربری، هزاران عنصر ورودی را پیاده‌سازی و استایل‌سازی کرده‌ام. یک روز وظیفه اضافه کردن الف به من محول شد ورودی محدوده به کتابخانه و، من فکر کردم که این فرآیند مشابه سایر ورودی‌هایی است که در گذشته پیاده‌سازی کرده بودم. این فرض درست بود تا اینکه شروع به آزمایش ورودی محدوده در چندین مرورگر کردم و به سرعت متوجه شدم که کار بسیار بیشتری در دستانم است.

بعد از کلی تحقیق، بالاخره توانستم به اندازه کافی مشخص کنم پست های وبلاگ، مقالات، و آموزش های عمیق تا به من کمک کند تا ورودی محدوده را به گونه ای تنظیم کنم که به طور مداوم ارائه شود. هدف این پست وبلاگ به جای جست‌وجوی منابع متعدد، ارائه یک فروشگاه یک‌جا برای یادگیری نحوه درست استایل دادن به ورودی محدوده است که در همه مرورگرها ثابت به نظر می‌رسد. این مقاله ای است که آرزو می کردم وقتی مجبور شدم خودم این کار را انجام دهم و امیدوارم به شما کمک کند که این روند سریعتر و روان تر شود.

آناتومی یک ورودی محدوده

ورودی محدوده از دو بخش اصلی تشکیل شده است:

  1. مسیر
    این بخشی از نوار لغزنده است که انگشت شست دویدن در امتداد. یا به عبارت دیگر، این عنصر طولانی است که محدوده مقادیر قابل انتخاب را نشان می دهد.
  2. شست
    این عنصری در مسیر است که کاربر می تواند در اطراف آن حرکت کند تا مقادیر محدوده متفاوتی را انتخاب کند.

ورودی محدوده از یک آهنگ و انگشت شست تشکیل شده است.

ورودی محدوده از یک آهنگ و انگشت شست تشکیل شده است. (پیش نمایش بزرگ)

اگر یک معادله ریاضی بود:

محدوده ورودی = آهنگ + انگشت شست

ورودی محدوده گاهی اوقات به عنوان یک “لغزنده” نامیده می شود و در ادامه این مقاله، من از این اصطلاحات به جای یکدیگر استفاده خواهم کرد.

ناهماهنگی های مرورگر

برای نشان دادن اینکه چرا ما حتی در وهله اول به یک آموزش در مورد ورودی های محدوده یک ظاهر نیاز داریم، نگاهی به برخی از تصاویر ورودی محدوده پیش فرض HTML و نحوه ارائه آن در چهار مرورگر اصلی (Chrome، Firefox، Safari، و) خواهیم انداخت. حاشیه، غیرمتمرکز). یا در صورت تمایل می توانید این را مشاهده کنید نسخه ی نمایشی CodeSandbox در هر یک از مرورگرهای مربوطه، ناهماهنگی های مرورگر را با شکوه تمام ببینید.

توجه داشته باشید: این اسکرین شات ها از سپتامبر 2021 گرفته شده اند و ممکن است با به روز رسانی مرورگرهای مربوطه تغییر کنند.

بیایید کار را با نگاهی به Chrome شروع کنیم که به نظر من کاربرپسندترین نسخه ورودی را به طور پیش فرض ارائه می کند.

نسخه نمایشی Chrome ورودی محدوده پیش‌فرض HTML

نسخه نمایشی Chrome ورودی محدوده پیش‌فرض HTML. (پیش نمایش بزرگ)

فایرفاکس در مرحله بعدی قرار دارد و به نظر متفاوت از ورودی رندر شده کروم است. در فایرفاکس، ارتفاع مسیر کمی کوتاهتر است. از طرفی ارتفاع و عرض انگشت شست بزرگتر است و همان رنگ پس زمینه آبی که نسخه کروم دارد را ندارد.

نسخه ی نمایشی فایرفاکس ورودی محدوده پیش فرض HTML

نسخه ی نمایشی فایرفاکس ورودی محدوده پیش فرض HTML. (پیش نمایش بزرگ)

نوار لغزنده سافاری از نظر ظاهری به نسخه فایرفاکس نزدیک‌ترین است، اما باز هم متفاوت است. به نظر می رسد این بار در اطراف مسیر اثری سایه دار دارد و ارتفاع انگشت شست و عرض آن کمتر از نسخه های کروم و فایرفاکس است. اگر به دقت نگاه کنید، می‌توانید متوجه شوید که انگشت شست مستقیماً روی مسیر قرار ندارد و ظاهر و احساسی صیقلی به آن نمی‌دهد.

نسخه ی نمایشی سافاری ورودی محدوده پیش فرض HTML

نسخه ی نمایشی سافاری ورودی محدوده پیش فرض HTML. (پیش نمایش بزرگ)

آخرین اما نه کم اهمیت ترین Edge است که در حال حاضر مایکروسافت اج از کرومیوم ساخته شده است، نسبت به نسخه قبلی خود با سه مرورگر دیگر هماهنگ تر است. با این حال، می بینیم که هنوز هم متفاوت از سه مرورگر دیگر رندر می شود. نمایش Edge از ورودی محدوده خود بسیار شبیه به نسخه کروم است، با این تفاوت که رنگ پس‌زمینه خاکستری تیره‌تری برای انگشت شست و سمت چپ آهنگ قبل از انگشت شست دارد.

نسخه نمایشی لبه ورودی محدوده پیش فرض HTML

نسخه نمایشی لبه ورودی محدوده پیش فرض HTML. (پیش نمایش بزرگ)

اکنون که دیدیم هر مرورگر تا چه حد ناسازگاری ورودی محدوده را ارائه می دهد، نگاهی به این خواهیم داشت که چگونه می توانیم از CSS برای یکسان سازی آنها استفاده کنیم.

بیشتر بعد از پرش! ادامه مطلب زیر ↓

بازنشانی محدوده (سبک‌های پایه)

از آنجایی که ناهماهنگی های مرورگر بسیار متفاوت است، باید از یک زمین بازی شروع کنیم. هنگامی که سبک های پیش فرضی که هر مرورگر اعمال می کند حذف شد، می توانیم برای ایجاد ورودی یکسان تر شروع به کار کنیم. ما استفاده خواهیم کرد input[type="range"] انتخابگر عنصر-ویژگی و سبک های اعمال شده در اینجا مانند یک تنظیم مجدد CSS برای ورودی عمل می کنند.

برای اعمال سبک های پایه به چهار ویژگی نیاز داریم:

  1. -webkit-appearance: none;
    این خاصیت یک پیشوند فروشنده که برای همه مرورگرهای اصلی اعمال می شود. با دادن ارزش به آن none این به هر مرورگر مربوطه می‌گوید که سبک‌های پیش‌فرض را پاک کند. این به ما این امکان را می دهد که بتوانیم از ابتدا شروع کنیم و ظاهر ورودی را از آن نقطه ایجاد کنیم.
  2. background: transparent;
    این کار پس‌زمینه پیش‌فرض اعمال شده روی ورودی را پاک می‌کند.
  3. cursor: pointer;
  4. width
    عرض کلی ورودی را تنظیم می کند.
input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  background: transparent;
  cursor: pointer;
  width: 15rem;
}

محدوده ورودی در کروم قبل از پس‌زمینه: شفاف اعمال می‌شود.

محدوده ورودی در کروم قبل از پس‌زمینه: شفاف اعمال می‌شود. (پیش نمایش بزرگ)

پس از اعمال همه سبک‌های بازنشانی، محدوده ورودی در Chrome.

پس از اعمال همه سبک‌های بازنشانی، محدوده ورودی در Chrome. (پیش نمایش بزرگ)

یک ظاهر طراحی شده آهنگ

هنگام استایل دادن به آهنگ (و انگشت شست) ما باید پیشوندهای فروشنده خاص مرورگرهای مختلف را هدف قرار دهیم تا سبک های مناسب را در عنصر مربوطه اعمال کنیم. به جلو، هر شبه عنصر پیشوند با -webkit برای مرورگرهای Chrome، Safari، Opera و Edge (پس از Chromium) اعمال خواهد شد. هر چیزی که با پیشوند -moz مربوط به فایرفاکس است

در زیر شبه عناصری وجود دارد که برای هدف قرار دادن مسیر استفاده خواهیم کرد:

  • ::-webkit-slider-runnable-track
    را هدف قرار می دهد مسیر در Chrome، Safari، و Edge Chromium.
  • ::-moz-range-track
    را هدف قرار می دهد مسیر در فایرفاکس
                        /***** Track Styles *****/
/***** Chrome, Safari, Opera, and Edge Chromium *****/
input[type="range"]::-webkit-slider-runnable-track {
  background: #053a5f;
  height: 0.5rem;
}

/******** Firefox ********/
input[type="range"]::-moz-range-track {
  background: #053a5f;
  height: 0.5rem;
}

تنها ویژگی های مورد نیاز برای مسیر هستند height و background. با این حال، معمول است که a border-radius به منظور گرد کردن لبه ها اعمال می شود.

پس از اعمال سبک های آهنگ، محدوده ورودی در فایرفاکس.

پس از اعمال سبک های آهنگ، محدوده ورودی در فایرفاکس. (پیش نمایش بزرگ)

یک ظاهر طراحی شده به انگشت شست

استایل دادن به انگشت شست (شستی وسطی که کاربر حرکت می‌دهد) تفاوت‌های ظریف بیشتری دارد که باید در نظر گرفته شود، زیرا ناهماهنگی‌های بیشتری بین مرورگرها در آن قسمت از ورودی محدوده وجود دارد.

در زیر شبه عناصری هستند که برای هدف قرار دادن انگشت شست استفاده خواهیم کرد:

  • ::-webkit-slider-thumb
    را هدف قرار می دهد شست در Chrome، Safari، و Edge Chromium.
  • ::-moz-range-thumb
    را هدف قرار می دهد شست در فایرفاکس

از آنجایی که مرورگرهای فایرفاکس و Webkit مشکلات سبک متفاوتی دارند، من به هر موضوع به صورت جداگانه پرداخته و نحوه مدیریت هر یک از پیش‌فرض‌های عجیب و غریب را که روی انگشت شست اعمال می‌شود، نشان می‌دهم.

Chrome، Safari، Edge Chromium (Webkit)

اولین سبکی که باید روی آن اعمال کنیم ::-webkit-slider-thumb شبه عنصر است -webkit-appearance: none; پیشوند فروشنده ما از این ویژگی در بخش «سبک‌های پایه» استفاده کردیم تا سبک‌های پیش‌فرض کلی را که توسط مرورگر اعمال می‌شود لغو کنیم و هدف مشابهی را در نظر داریم.

محدوده ورودی در Chrome بعد از <code>-webkit-appearance: none;</code> اعمال می شود”/></p>
<p>    </a><figcaption class=

Range Input در کروم بعد -webkit-appearance: none; اعمال می شود. (پیش نمایش بزرگ)

هنگامی که سبک های پیش فرض حذف شدند، می توانیم سبک های سفارشی خود را اعمال کنیم. با فرض اینکه الف را اعمال کنیم height، width و background-color برای مثال، در اینجا نمونه ای از آنچه تا کنون داشته ایم آورده شده است:

ورودی محدوده در Chrome با سبک‌های شست سفارشی.

ورودی محدوده در Chrome با سبک‌های شست سفارشی. (پیش نمایش بزرگ)

به طور پیش‌فرض، مرورگرهای WebKit انگشت شست را طوری نمایش می‌دهند که در مرکز مسیر قرار نگیرد.

برای اینکه انگشت شست را به درستی در مسیر قرار دهیم، می‌توانیم از فرمول زیر استفاده کرده و آن را روی آن اعمال کنیم margin-top ویژگی:

margin-top = (ارتفاع آهنگ بر حسب پیکسل / 2) – (ارتفاع انگشت شست بر حسب پیکسل /2)

گرفتن استایل هایی که در قسمت های قبل اعمال کردیم و تبدیل rems به پیکسل، ارتفاع آهنگ 8 پیکسل و ارتفاع انگشت شست 32 پیکسل خواهیم داشت. این بدان معنی است که:

margin-top = (8/2) – (32/2) = 4 – 16 = -12px

بر این اساس، سبک های نهایی شده ما برای مرورگرهای وب کیت مانند بلوک کد زیر است:

/***** Thumb Styles *****/
/***** Chrome, Safari, Opera, and Edge Chromium *****/
input[type="range"]::-webkit-slider-thumb {
   -webkit-appearance: none; /* Override default look */
   appearance: none;
   margin-top: -12px; /* Centers thumb on the track */
   background-color: #5cd5eb;
   height: 2rem;
   width: 1rem;    
}

پس از اعمال همه سبک‌ها، محدوده را در Chrome وارد کنید.

پس از اعمال همه سبک‌ها، محدوده را در Chrome وارد کنید. (پیش نمایش بزرگ)

فایرفاکس

هنگام اعمال استایل ها روی انگشت شست در فایرفاکس، باید از آن استفاده کنید ::-moz-range-thumb شبه عنصر خوشبختانه، فایرفاکس از مشکل مرکزی مانند مرورگرهای Webkit رنج نمی برد. با این حال، یک گوچا در اطراف شعاع مرزی و مرز خاکستری پیش‌فرض است که روی انگشت شست اعمال می‌شود.

ورودی محدوده در فایرفاکس با حاشیه خاکستری و شعاع حاشیه به طور پیش فرض اعمال می شود.

(پیش نمایش بزرگ)

به منظور اصلاح حاشیه خاکستری پیش فرض، می توانیم آن را اضافه کنیم border: none; ویژگی. برای حذف شعاع مرزی پیش‌فرض که اعمال می‌شود، می‌توانیم آن را اضافه کنیم border-radius: 0 ویژگی و اکنون انگشت شست در تمام مرورگرها ثابت به نظر می رسد.

بر این اساس استایل های نهایی شده ما برای مرورگرهای وب کیت به شکل زیر است:

                     /***** Thumb Styles *****/
/***** Firefox *****/
input[type="range"]::-moz-range-thumb {
    border: none; /*Removes extra border that FF applies*/
    border-radius: 0; /*Removes default border-radius that FF applies*/
    background-color: #5cd5eb;
    height: 2rem;
    width: 1rem;
}

توجه داشته باشید: مرورگرهای Webkit به طور خودکار این شعاع را به حاشیه اعمال نمی کنند، بنابراین اگر متوجه شدید که می خواهید نوعی از شعاع حاشیه را به انگشت شست اعمال کنید، برخلاف لغو آن همانطور که در بالا انجام دادیم، باید اعمال کنید. مطلوب border-radius ابعاد به هر دو -webkit-slider-thumb و ::-moz-range-thumb شبه عناصر

سبک های تمرکز

از آنجا که ورودی محدوده یک عنصر تعاملی است، اضافه کردن سبک‌های تمرکز برای مطابقت با بهترین شیوه‌ها و استانداردهای دسترسی ضروری است. هنگامی که سبک های فوکوس اعمال می شوند، یک نشانگر بصری برای کاربران فراهم می کند و به ویژه برای کسانی که از صفحه کلید برای پیمایش یک صفحه استفاده می کنند مهم است.

بر اساس WAI-ARIA: اسناد لغزنده، توصیه می شود:

فوکوس بر روی نوار لغزنده قرار می گیرد (شئی بصری که کاربر ماوس را حرکت می دهد، همچنین به عنوان انگشت شست شناخته می شود).

اولین کاری که می خواهیم انجام دهیم این است که سبک های تمرکز پیش فرض را حذف کنیم تا بتوانیم با سبک های سفارشی آنها را لغو کنیم. برای هدف قرار دادن سبک‌های فوکوس انگشت شست، می‌توانیم از آن استفاده کنیم ::-webkit-slider-thumb و ::-moz-range-thumb شبه عناصری که در قسمت قبل استفاده کردیم و آنها را با the ترکیب می کنیم :focus شبه کلاس. سپس می توانیم از CSS استفاده کنیم طرح کلی و طرح آفست ویژگی هایی که آن را به شکلی که می خواهیم استایل کنیم.

/***** Focus Styles *****/
/* Removes default focus */
input[type="range"]:focus {
  outline: none;
}

/***** Chrome, Safari, Opera, and Edge Chromium *****/
input[type="range"]:focus::-webkit-slider-thumb {
  border: 1px solid #053a5f;
  outline: 3px solid #053a5f;
  outline-offset: 0.125rem;
}

/******** Firefox ********/
input[type="range"]:focus::-moz-range-thumb {
  border: 1px solid #053a5f;
  outline: 3px solid #053a5f;
  outline-offset: 0.125rem;     
}

توجه داشته باشید: اگر یک border-radius به انگشت شست اعمال می شود، فایرفاکس یک طرح کلی را در قسمت نمایش می دهد شکل انگشت شست در حالی که سایر مرورگرها یک طرح کلی بلوکی را نمایش می دهند. متأسفانه، یک اصلاح CSS ساده برای این وجود ندارد و این تنها ناهماهنگی است که وجود خواهد داشت. با این حال، هدف اصلی از افزودن این سبک ها برای اهداف دسترسی است و هدف اصلی، ارائه یک نشانگر بصری در هنگام تمرکز عنصر، همچنان محقق می شود.

محدوده ورودی در Chrome با سبک‌های تمرکز سفارشی اعمال شده.

محدوده ورودی در Chrome با سبک‌های تمرکز سفارشی اعمال شده. (پیش نمایش بزرگ)

همه اش را بگذار کنار هم

اکنون که تمام سبک‌های مورد نیاز برای یکنواخت کردن ورودی محدوده را پوشش داده‌ایم، در اینجا نحوه ظاهر نهایی CSS به شرح زیر است:

/********** Range Input Styles **********/
/*Range Reset*/
input[type="range"] {
   -webkit-appearance: none;
    appearance: none;
    background: transparent;
    cursor: pointer;
    width: 15rem;
}

/* Removes default focus */
input[type="range"]:focus {
  outline: none;
}

/***** Chrome, Safari, Opera and Edge Chromium styles *****/
/* slider track */
input[type="range"]::-webkit-slider-runnable-track {
   background-color: #053a5f;
   border-radius: 0.5rem;
   height: 0.5rem;  
}

/* slider thumb */
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; /* Override default look */
   appearance: none;
   margin-top: -12px; /* Centers thumb on the track */

   /*custom styles*/
   background-color: #5cd5eb;
   height: 2rem;
   width: 1rem;
}

input[type="range"]:focus::-webkit-slider-thumb {   
  border: 1px solid #053a5f;
  outline: 3px solid #053a5f;
  outline-offset: 0.125rem; 
}

/******** Firefox styles ********/
/* slider track */
input[type="range"]::-moz-range-track {
   background-color: #053a5f;
   border-radius: 0.5rem;
   height: 0.5rem;
}

/* slider thumb */
input[type="range"]::-moz-range-thumb {
   border: none; /*Removes extra border that FF applies*/
   border-radius: 0; /*Removes default border-radius that FF applies*/

   /*custom styles*/
   background-color: #5cd5eb;
   height: 2rem;
   width: 1rem;
}

input[type="range"]:focus::-moz-range-thumb {
  border: 1px solid #053a5f;
  outline: 3px solid #053a5f;
  outline-offset: 0.125rem; 
}

نتیجه

علاوه بر روش هایی که در طول مقاله ذکر شده است، می توانید از مزایای آن نیز استفاده کنید مولد CSS ورودی محدوده من ایجاد کردم به نام range-input.css. هدف اصلی این پروژه ایجاد ابزاری بود که این فرآیند را برای توسعه دهندگان ساده تر می کند. مولد CSS به شما امکان می دهد تا به سرعت ویژگی های رایج CSS را استایل دهید و یک نوار لغزنده نمایشی ارائه می دهد که پیش نمایش بلادرنگ سبک هایی را که می خواهید اعمال کنید نمایش می دهد.

امیدواریم ورودی‌های محدوده استایل در آینده ساده‌تر شوند. با این حال، تا آن روز، دانستن اینکه کدام شبه عناصر و پیشوندهای فروشنده را هدف قرار دهید، به شما کمک می‌کند تا به خوبی در مسیر اسلایدرهای استایل‌سازی متناسب با نیازهایتان پیش بروید.

منابع بیشتر در مجله Smashing

سرمقاله Smashing
(vf، yk، او)

Read More

اصلاح سرصفحه ها در درخواست های HTTP در تست اتوماسیون رابط کاربری – مجله Smashing

خلاصه سریع ↬

اینکه بتوانید هدرها را در یک محیط آزمایشی تغییر دهید یک چیز عالی است. این امکان کنترل بر برنامه شما را فراهم می کند زیرا می توانید احراز هویت را دور بزنید، کوکی ها را تنظیم کنید و غیره. در این مقاله، Nafees Nehar به بررسی روش هایی می پردازد که امکان اصلاح هدرها را در تنظیمات تست اتوماسیون فراهم می کند.

روش های مختلفی برای اصلاح هدرها وجود دارد. می‌توانید سرصفحه‌ها را با استفاده از برنامه‌های افزودنی مرورگر یا برنامه‌های پراکسی (مانند چارلز و پروکسیمن) تغییر دهید که درخواست را قطع می‌کنند و به شما اجازه می‌دهند پاسخ را با اضافه کردن سرصفحه‌ها تغییر دهید.

اما ابتدا اجازه دهید از ابتدا شروع کنیم.

هدرهای HTTP جفت های کلید-مقدار هستند که می توانند توسط کلاینت یا سرور برای ارسال اطلاعات اضافی به همراه درخواست یا پاسخ HTTP استفاده شوند. آنها اطلاعات بیشتری در مورد داده های ارسال شده در اختیار دارند. هدر HTTP (ها) از یک نام حساس به حروف کوچک و بزرگ و به دنبال آن یک دونقطه تشکیل شده است (:) سپس با ارزش آن. نام فیلدها به حروف بزرگ و کوچک حساس هستند اما مقادیر فیلدها به حروف بزرگ و کوچک حساس هستند. یک هدر می تواند چندین مقدار داشته باشد که با کاما از هم جدا می شوند.

من روی برنامه‌ای کار می‌کردم که صفحه وب ارائه‌شده را باز می‌کرد و سپس به کاربر امکان تغییر عناصر، اضافه کردن رویدادها، افزودن تجزیه و تحلیل و غیره را می‌داد. بدون نیاز به کدنویسی این کار با بارگذاری صفحه انجام می شد iframe و در بالای آن گزینه های مختلفی به کاربر می دهد. من با تعداد زیادی از وب سایت ها سعی کردم ببینم آنها چگونه رفتار می کنند iframe. مشاهده کردم که اکثر وب سایت ها در آن کار نمی کنند iframe به واسطه x-frame-options و content-security-policy سرصفحه ها

تقریباً همه وب سایت ها دارای سربرگ هستند X-frame-options تنظیم کنید deny یا sameorigin به همین دلیل مرورگر اجازه بارگذاری صفحه وب در یک را نمی دهد iframe یا وقتی هر درخواست متقاطع سعی می کند آن را در یک بارگذاری کند، انجام نمی دهد iframe. همچنین content-security-policy هدر دارد frame-ancestors بخشنامه ای که از این امر جلوگیری می کند.

بارگذاری صفحه در آن بسیار مهم بود iframe، داشتم در اینترنت پرسه می زدم تا راهی برای بارگذاری آن پیدا کنم. بدیهی بود که من باید این را نادیده بگیرم X-frame-options سربرگ به allowall یا کلا حذفش کن آن موقع بود که به طور تصادفی به آن برخورد کردم Requestly برنامه افزودنی که به من این ویژگی را داد تا آن را تغییر دهم X-frame-options هدر با تطبیق URL صفحه و از این رو به من اجازه می دهد تا آن را لغو کنم X-frame-options هدر هنگام اشکال زدایی

این زمانی بود که من برای اولین بار شاهد قدرت هدرهای شبکه بودم. آنها داده های مربوط به داده های در حال انتقال را حمل می کنند. امکان تغییر هدرهای ترافیکی که از مرورگر شما عبور می کند، ابزار بسیار خوبی است. علاوه بر نادیده گرفتن X-frame-options، می توانید هدرها را حذف کنید تا ردیابی آنلاین را به حداقل برسانید content-security-policy هدر، سایت های تست در حال تولید و غیره.

هنگام آزمایش برنامه های وب، اصلاح هدرها یک هک عالی را فراهم می کند:

  • برای آزمایش حالت مهمان یک برنامه؛
  • می تواند کوکی ها را با استفاده از هدر تنظیم کند.
  • برای تست بخش‌های خاصی از یک برنامه که به‌طور پیش‌فرض غیرفعال هستند و می‌توان آن‌ها را با ارسال یک هدر درخواست سفارشی فعال کرد.
  • برای تست موارد تست مختلف مرتبط با هدرها.
  • برای دور زدن جریان احراز هویت در برنامه خود با عبور از هدر مجوز.

وقتی با آزمایش خودکار برنامه‌های وب آشنا شدم، به ذهنم رسید که به دلیل کاربرد بسیار زیاد آن در آزمایش برنامه‌های وب، تغییر هدرها باید یک ویژگی باشد. بنابراین تصمیم گرفتم این قطعه را بنویسم تا راههای اصلاح هدرها در تست خودکار را روشن کنم.

بیشتر بعد از پرش! ادامه مطلب زیر ↓

سلنیوم

سلنیوم به طور گسترده ای به عنوان یک چارچوب اتوماسیون آزمایشی برای آزمایش انتها به انتها برنامه های کاربردی وب استفاده می شود. در سال 2004 توسعه یافت. در ابتدا از Selenium IDE استفاده می شد اما فقط از فایرفاکس پشتیبانی می کرد و سپس Selenium RC برای فعال کردن تست بین مرورگر توسعه یافت. اکنون از Selenium WebDriver استفاده می شود زیرا از تجربه تلفن همراه و وب سایت های پویا پشتیبانی می کند. این یک کاربر واقعی در تعامل با صفحه وب را تقلید می کند.

مزایای استفاده از Selenium WebDriver

  • Selenium WebDriver منبع باز است.
  • این اتصالات برای هر زبان برنامه نویسی اصلی ارائه می دهد.
  • در چندین سیستم عامل کار می کند. تست نوشته شده در ویندوز به راحتی روی مک کار می کند.
  • شبیه سازی صفحه کلید و مکان نما پشتیبانی می شود.
  • افزونه ها قابل نصب هستند.

محدودیت های Selenium WebDriver

  • بدون پشتیبانی برای تغییر هدر.
  • بدون پشتیبانی برای افزودن پارامترهای درخواست.
  • نمی توان یک درخواست را مسدود کرد.

همانطور که گفته شد، توانایی تغییر هدرها به آزمایش برنامه ها کمک شایانی می کند، اما Selenium WebDriver از آن پشتیبانی نمی کند. آنها اخیراً قصد ندارند آن را بگنجانند.

این مقاله بر روی رویکردهای مختلف برای اصلاح هدرها در تنظیمات اتوماسیون سلنیوم تمرکز دارد.

رویکرد 1: سیم سلنیوم (پایتون)

سیم سلنیوم اتصالات Selenium Python را گسترش می دهد تا به شما امکان دسترسی به درخواست های اساسی که توسط مرورگر ارائه می شود را بدهد. شما کد خود را به همان روشی که با Selenium انجام می دهید می نویسید، اما API های اضافی برای بررسی درخواست ها و پاسخ ها و ایجاد تغییرات در آنها در لحظه دریافت می کنید.

این اجازه می دهد تا درخواست ها و پاسخ ها را در حال حرکت با استفاده از رهگیرها تغییر دهید. همچنین می‌تواند درخواست‌ها، پاسخ‌های ساختگی، اضافه کردن پارامترهای درخواست در URL را مسدود کند.

استفاده

# interceptor function intercepts the network request
# If one arg is provided, requests are intercepted
# and can be modified
def interceptor(request):
    request.headers['New-Header'] = 'Some Value'
# setting the driver's request_interceptor to equal
# the customised interceptor
driver.request_interceptor = interceptor
driver.get(<URL_where_to_modify_the_header>)

# All requests will now contain New-Header

نام‌های هدر تکراری در درخواست HTTP مجاز است، بنابراین قبل از تنظیم سرصفحه جایگزین، ابتدا باید هدر موجود را با استفاده از آن حذف کنید. del در غیر این صورت دو هدر به همین نام وجود خواهد داشت.

# A response interceptor takes two args which
# then allows to tinker with the response
def interceptor(request, response):  
    if request.url == 'https://server.com/some/path':
        response.headers['New-Header'] = 'Some Value'
driver.response_interceptor = interceptor
driver.get(<URL_where_to_modify_the_header)

# Responses from https://server.com/some/path will now contain 
# the New-Header

یک رهگیر پاسخ باید دو آرگومان را بپذیرد، یکی برای درخواست مبدأ و دیگری برای پاسخ.

محدودیت ها

  • این فقط به عنوان یک ماژول پایتون در دسترس است.
  • از زبان های دیگر پشتیبانی نمی کند.

ابزارهایی مانند درخواست کنید که یک ابزار یک مرحله ای برای اشکال زدایی و اصلاح درخواست های شبکه است. Requestly به کاربران اجازه می‌دهد تا سرصفحه‌ها را تغییر دهند، آدرس‌های اینترنتی را تغییر دهند، میزبان‌ها را تغییر دهند، پاسخ API ساختگی، درخواست‌های شبکه را به تاخیر بیاندازند، اسکریپت‌های سفارشی را درج کنند، و غیره. این بسته npm آماده به کار را فراهم می‌کند که بسته‌بندی در اطراف افزونه است که امکان استفاده از برنامه افزودنی را در سلنیوم فراهم می‌کند. کروم، فایرفاکس و اج را پشتیبانی می کند.

استفاده از Requestly در سلنیوم

Requestly به شما این امکان را می دهد که کارهای بسیار بیشتری غیر از اصلاح هدرها انجام دهید. همه این موارد را می توان در یک رابط وب تنظیم کرد و لیست مشترک را می توان در برنامه بارگذاری کرد که به کاربر اجازه می دهد تا قوانین را به راحتی در یک برنامه وب ویرایش کند.

برای نصب: npm i @requestly/selenium

استفاده

یک قانون Modify Headers را می توان در آن ایجاد کرد app.requestly.io/rules پس از نصب افزونه

افزودن سربرگ به تمام درخواست ها

افزودن سربرگ به تمام درخواست ها (پیش نمایش بزرگ)

پس از ایجاد URL، بر روی آن کلیک کنید Share دکمه ایجاد پیوند برای URL.

URL برای موارد بالا ایجاد شد sharedList است اینجا.

این URL یک قانون Requestly است که اضافه می کند Access-Control-Allow-Origin سربرگ تمام درخواست ها

این قانون را می توان در Selenium WebDriver با استفاده از sharedList URL که در زیر توضیح داده شده است:

require("chromedriver");
const { Builder } = require("selenium-webdriver");
const chrome = require("selenium-webdriver/chrome");
const { getRequestlyExtension, importRequestlySharedList } = require("@requestly/selenium");

const options = new chrome.Options().addExtensions(getRequestlyExtension("chrome"));
const driver = new Builder()
    .forBrowser("chrome")
    .setChromeOptions(options)
    .build();

// Imports Rules in Selenium using Requestly sharedList feature
// importRequestlySharedList(driver, <sharedList_URL>);

importRequestlySharedList(driver, 'https://app.requestly.io/rules/#sharedList/1626984924247-Adding-Headers-Example');

اطلاعات بیشتر را می توان یافت اینجا.

محدودیت ها

  • این یک بسته npm ارائه می دهد که ماژول را فقط به جاوا اسکریپت محدود می کند.
  • برای استفاده از قوانین در سلنیوم، فهرست‌های مشترک باید به صورت دستی ایجاد شوند، بنابراین قوانین را نمی‌توان از طریق کد نوشته شده برای تست اتوماسیون سلنیوم کنترل کرد.

رویکرد 3: استفاده از Puppeteer

عروسک گردان یک کتابخانه Node است که توسط Google ایجاد شده است که یک API سطح بالا برای کنترل Chrome یا Chromium بدون هد بر روی پروتکل DevTools ارائه می دهد. همچنین می‌توان آن را برای استفاده کامل (غیر هد) Chrome یا Chromium پیکربندی کرد.

وقتی صحبت از راه اندازی اتوماسیون مرورگر می شود، سلنیوم به طور خودکار به ذهن خطور می کند، اما از زمان ظهور Puppeteer به طور گسترده برای خراش دادن وب استفاده می شود. احتمالاً به دلیل پشتیبانی گوگل از آن، کنترل بیشتری بر روی کروم نسبت به سلنیوم ارائه می دهد. همچنین به همین دلیل، نیاز به درایور خارجی برای اجرای مرورگر را رد می کند.

استفاده

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto('<https://example.com>');
    await page.screenshot({ path: 'example.png' });
    await browser.close();
})();

در page.setExtraHTTPHeaders(headers) روش را می توان برای تنظیم هدر استفاده کرد.

همچنین می تواند هدرهای موجود را اصلاح و حذف کند. هنگامی که درخواست ها با استفاده از ترکیبی از page.setRequestInterception(true) و page.on().

await page.setRequestInterception(true);
page.on('request', request => {
// Override headers
    const headers = Object.assign({}, request.headers(), {
    foo: 'bar', // set "foo" header
    origin: undefined, // remove "origin" header
});

request.continue({headers});

});

منبع کد

محدودیت ها

  • Puppeteer در حال حاضر به کروم محدود شده است. نمی توان از آن برای آزمایش بین مرورگر استفاده کرد.
  • در مقایسه با سلنیوم جامعه کوچک تری دارد. به نظر می رسد حمایت بیشتری از سلنیوم در جامعه وجود دارد.
  • این فقط از جاوا اسکریپت پشتیبانی می کند.

نتیجه

اصلاح هدرهای شبکه ابزار بسیار قدرتمندی در یک محیط آزمایشی است. چیزهای بیشتری نسبت به آنچه که در این مقاله می توان به آن پرداخته شده است. من سعی کرده‌ام برخی از ساده‌ترین روش‌ها را برای اصلاح هدرها در تست اتوماسیون UI پوشش دهم.

هر روشی بر اساس کاربرد و زبانی که استفاده می کنید دارای مزایایی است. در اینجا برخی از ترجیحات وجود دارد:

  • اگر می خواهید از سلنیوم در پایتون استفاده کنید، Selenium-Wire را ترجیح دهید زیرا ویژگی های زیادی را در بالای Selenium-Webdriver ارائه می دهد.
  • اگر می‌خواهید فقط روی کروم تست کنید، Puppeteer را به دلیل پشتیبانی گوگل و پشتیبانی خارج از جعبه از همه ویژگی‌ها از جمله اصلاح هدرها ترجیح دهید.
  • اگر با سلنیوم کار می‌کنید و می‌خواهید آزمایش بین مرورگر انجام دهید، ترجیح می‌دهید پسوندها را برای شبیه‌سازی آزمایش در Selenium-Webdriver اضافه کنید. اگر مورد استفاده شما نیاز به تزریق اسکریپت یا تغییر مسیر منابع شبکه در زمان اجرا دارد (علاوه بر اصلاح هدرها)، پس Requestly یک انتخاب ایده آل است.

امیدواریم این مقاله به شما بینشی در مورد اصلاح هدرها در یک تنظیم خودکار تست برنامه کاربردی وب بدهد.

منابع بیشتر

سرمقاله Smashing
(vf، yk، او)

Read More

چگونه از کلید API خود در تولید با Next.js API Route محافظت کنیم — مجله Smashing

خلاصه سریع ↬

ایجاد برنامه های Jamstack در وب چالش بزرگی وجود دارد. در این مقاله، Caleb Olojo توضیح می دهد که چگونه می توانید از Next.js برای بوت استرپ ایمن برنامه خود استفاده کنید.

توسعه دهندگان فرانت اند باید با API های خصوصی یا عمومی که روش مجوز آنها به یک کلید مخفی/کلید API نیاز دارد که توسعه دهندگان را قادر می سازد از این API ها استفاده کنند، تعامل داشته باشند. کلید(های) مهم هستند، از این رو نیاز به ذخیره/حفاظت از کلید(ها) بوجود می آید. ایجاد یک متغیر محیطی که کلید را ذخیره می‌کند، راه‌حلی است که بیشتر توسعه‌دهندگان از آن استقبال می‌کنند، اما یک نکته وجود دارد. متغیر محیطی از کلید(های) محافظت نمی کند از هر کسی که راه خود را در مورد ابزارهای توسعه دهنده مرورگر خود می داند. به همین دلیل است که وقتی در حال نوشتن تماس های API خود هستیم، باید از کلیدهای خود در سمت سرور استفاده کنیم.

در این مقاله، ما از Next.js برای بوت استرپ برنامه خود استفاده خواهیم کرد. این بدان معنا نیست که create-react-app کتابخانه کار نخواهد کرد می توانید از هر کدام که راحت می دانید استفاده کنید. ما از Next.js به دلیل مزایای زیادی که به همراه دارد استفاده می کنیم. (می توانید درباره Next.js بیشتر بخوانید اینجا.)

اجازه دهید با نصب وابستگی هایی که در این پروژه نیاز داریم شروع کنیم. ما با ایجاد یک برنامه Next.js شروع می کنیم. دستور زیر این کار را برای ما انجام می دهد:

npx create-next-app [name-of-your-app]

ما از جاوا اسکریپت بومی استفاده خواهیم کرد "Fetch API" کتابخانه برای دریافت داده از API. ما در این مقاله خیلی از جنبه های ظاهری را پوشش نمی دهیم. (اگر می خواهید به پروژه نمونه ای که من با استفاده از الگوی مسیر Next.js API ساخته ام نگاهی بیندازید، می توانید مخزن را پیدا کنید. اینجا.)

حال بیایید نگاهی به ساختار فایل برنامه بیندازیم. ما بر روی فایل های مهم مورد نیاز در این برنامه تمرکز خواهیم کرد، بنابراین مختصر خواهد بود.

|--pages
|   |-- api
|   |   |-- serverSideCall.js  
|   |-- _app.js
|   |-- index.js
|__ .env.local

تفکیک فایل ها در ساختار برنامه

در این قسمت فایل های مختلف تشکیل دهنده معماری این پروژه و عملکردهای مربوط به آنها را در زیر مشاهده می کنیم.

در pages دایرکتوری جایی است که تمام مسیریابی برنامه انجام می شود. این یک ویژگی خارج از جعبه Next.js است. از استرس سخت کدگذاری مسیرهای مستقل شما جلوگیری می کند.

  • pages/api
    دایرکتوری api به شما این امکان را می دهد که به جای روش معمول ایجاد مخازن جداگانه برای API های REST یا GraphQL خود و استقرار آنها در پلتفرم های میزبانی پشتیبان مانند Heroku و غیره، یک Backend برای برنامه Next.js خود، در داخل همان پایگاه کد داشته باشید.

    با api دایرکتوری، هر فایل به عنوان یک نقطه پایانی API در نظر گرفته می شود. اگر به api پوشه، متوجه خواهید شد که ما یک فایل به نام داریم user.js در آن

    آن فایل به نقطه پایانی تبدیل می شود، به این معنی که یک فراخوانی API را می توان با استفاده از مسیر فایل به عنوان URL پایه انجام داد.

const getData = async() => {
  fetch("/api/users")
   .then(response => response())
   .then(response => console.log(response.data))
   .catch(err => console.log(err)
}
  • pages/_app.js
    جایی است که تمام اجزای ما به DOM متصل می شوند. اگر به ساختار کامپوننت نگاهی بیندازید، خواهید دید که تمام اجزا به عنوان ارسال می شوند pageProps به Component لوازم جانبی نیز
function MyApp({ Component, pageProps }) {
  return (
    <React.Fragment>
      <Head>
        <meta name="theme-color" content="#73e2a7" />
        <link rel="icon" type="image/ico" href="" />
      </Head>
      <Component {...pageProps} />
    </React.Fragment>
  );
}

export default MyApp;

اگر با Next.js تازه کار هستید، لطفاً این مقاله را دنبال کنید تا شما را در این فرآیند راهنمایی کند.

  • index.js
    این مسیر پیش فرض در پوشه pages است. هنگامی که دستور زیر را اجرا می کنید، سرور توسعه و محتویات آن را راه اندازی می کند index.js در صفحه وب ارائه می شوند.
npm run dev
  • .env.local
    این جایی است که ما کلید API را ذخیره می کنیم که به ما امکان می دهد این API را مصرف کنیم.

بیشتر بعد از پرش! ادامه مطلب زیر ↓

فراخوانی API سمت سرور

بخش قبلی شما را در معرض فایل هایی قرار داد که با آنها تعامل خواهیم داشت و عملکردهای خاص آنها. در این بخش به نحوه مصرف API می پردازیم.

دلیل اینکه ما در حال نوشتن فراخوانی API در سمت سرور هستیم، ایمن کردن کلید API خود است و Next.js در حال حاضر این کار را برای ما آسان کرده است. با مسیرهای API در Next.js، می‌توانیم تماس‌های API خود را بدون ترس از آشکار شدن کلیدهای API در سمت کلاینت انجام دهیم.

ممکن است از خود پرسیده باشید که جوهر متغیر محیطی در چیست .env فایل است، در این سناریو.

متغیر محیطی (که کلید API ما است) فقط می تواند در دسترس باشد development حالت

به همین دلیل است که ما می توانیم کاری مشابه انجام دهیم process.env.api_keyو به متغیر محیطی دسترسی پیدا کنید.

اما، لحظه ای که برنامه خود را روی پلتفرم هایی مانند Netlify یا Vercel مستقر می کنید، حالت به تغییر می کند production، که Node.js را می سازد process شی در سمت مشتری در دسترس نیست.

اکنون که دلیل نیاز به نوشتن یک فراخوانی API سمت سرور را دیدید. بیایید فوراً به آن برسیم.

export default async function serverSideCall(req, res) {
    const {
      query: { firstName, lastName },
    } = req;

    const baseUrl = `https://api.example-product.com/v1/search?
        lastName=${lastName}&firstName=${firstName}
        &apiKey=${process.env.KEY}
    `;
    const response = await fetch (baseUrl);
    res.status(200).json({
    data: response.data,
  });
}

در قطعه بالا، یک تابع ناهمزمان ایجاد کردیم به نام: serverSideCall. این در دو استدلال می گیرد، req که مخفف “درخواست” به طور کامل است، و res که به طور کامل “پاسخ” است.

در req آرگومان دارای برخی ویژگی ها است (یا به قول اسناد Next.js “middleware”) که زمانی که ما API خود را مصرف می کنیم می توان به آنها دسترسی داشت، یکی از آنها این است. req.query.

متوجه خواهید شد که ما آن را تخریب کردیم query ویژگی موجود در قطعه بالا، بنابراین اکنون باید بتوانیم آن متغیرها را به عنوان مقادیر به خصوصیات query نقطه پایانی API منتقل کنیم. در زیر به آن نگاهی بیندازید.

توجه داشته باشید: می‌توانید درباره میان‌افزارهای داخلی که همراه با آن‌ها ارائه می‌شوند، اطلاعات بیشتری کسب کنید req بحث و جدل اینجا.

const {
  query: { firstName, lastName },
} = req;

URL پایه خصوصیات پرس و جوی تخریب شده را به عنوان مقادیر و apiKey از .env فایل از طریق Node.js process هدف – شی.

خصوصیات پرس و جوی ساختاریافته به عنوان درخواست هایی در نظر گرفته می شوند که از مقادیر ورودی مؤلفه فرم (که در بخش بعدی ایجاد خواهیم کرد) به API ارسال می شوند، پس از دریافت، پاسخی مطابق با درخواست دریافت می کنیم. ما درست کردیم، ما ساختیم.

const baseUrl = `https://api.kelvindata.com/rest/v1/searchv2?  lastName=${lastName}&firstName=${firstName}&apiKey=${process.env.KEY}`;

فرآیند بعدی که تابع باید تکمیل کند، پاسخ از فراخوانی API ناهمزمان است. قطعه زیر تماس API را که با آن انجام می‌دهیم اختصاص می‌دهد axios کتابخانه به یک متغیر، response.

در خط بعدی، res آرگومان از status روشی که برای ارسال پاسخ JSON به ما استفاده می شود، سپس می توانیم متغیر پاسخ را به عنوان یک ویژگی اختصاص دهیم data.

const response = await axios.get(baseUrl);
res.status(200).json({
  data: response.data,
});

می‌توانید درباره کدهای مختلف وضعیت HTTP اطلاعات بیشتری کسب کنید اینجا.

استفاده عملی از عملکرد API سمت سرور

در این بخش، نگاهی به نحوه استفاده از فراخوانی API سمت سرور با ایجاد فرمی با دو فیلد ورودی خواهیم داشت. مقادیر ورودی به عنوان پارامترهای پرس و جو به نقطه پایانی API ارسال می شود.

import React from "react";

const Index = () => {
  const [data, setData] = React.useState([]);
  const [firstName, setFirstName] = React.useState("");
  const [lastName, setLastName] = React.useState("");

  const getuserData = async () => {
    // api call goes here
  };

  const handleSubmit = (e) => {
     e.preventDefault();
     getuserData();
  };

  return (
     <React.Fragment>
       <form onSubmit={handleSubmit}>
          <label htmlFor="firstname">First name</label>
          <input
            type="text"
            name="firstname"
            value={firstName}
            placeholder="First Name"
            onChange={(e) => setFirstName(e.target.value)}
          />
          <label htmlFor="lastname">Lastname</label>
          <input
            type="text"
            name="lastname"
            value={lastName}
            placeholder="Lastname"
            onChange={(e) => setLastName(e.target.value)}
          />
           <button>Search</button>
        </form>
        <div className="results-from-api"></div>
    </React.Fragment>
 );
};

export default Index;

از آنجایی که این یک جزء React است که داده‌ها را از یک نقطه پایانی API دریافت می‌کند، باید یک حالت داخلی خودش را داشته باشد. قطعه زیر نشان می دهد که چگونه متغیرهای حالت مختلف را با React Hooks تعریف کردیم.

const [userData, setUserData] = React.useState([]);
const [firstName, setFirstName] = React.useState("");
const [lastName, setLastName] = React.useState("");

در firstName و lastName متغیرها مقادیر متنی را که توسط هر کسی در فیلد ورودی تایپ می شود را در متغیرهای حالت محلی ذخیره می کند.

در data متغیر state به ما کمک می کند پاسخی را که از فراخوانی API دریافت می کنیم در یک آرایه ذخیره کنیم، بنابراین می توانیم از جاوا اسکریپت استفاده کنیم. map() روش ارائه پاسخ در صفحه وب

در زیر، ما استفاده می کنیم axios برای دریافت داده از نقطه پایانی API. اما در اینجا، URL پایه معمولی نیست https:// URL، در عوض، مسیر فایلی است که قبلاً تماس API سمت سرور را انجام داده بودیم.

const getuserData = async () => {
fetch(`/api/usersfirstName=${firstName}&lastName=${lastName}`, {
       headers: {
         Accept: "application/json",
       },
})
  .then((response) => response)
  .then((response) => {
    setData(response.data.data); 
    console.log(response.data.data);
  })
  .catch((err) => console.log(err));
};

همین روند در serverSideCall.js فایل تکرار می شود، اما این بار با هدرهای API لازم واکشی و تخصیص متغیرهای حالت ورودی به پارامترهای پرس و جوی API.

نتیجه

رویکردهای دیگری نیز وجود دارد که می تواند به دستیابی به این شاهکار کمک کند. در اینجا به برخی از آنها اشاره می کنیم:

  • ایجاد توابع Netlify Lambda که به محافظت از کلیدهای API شما در سمت سرویس گیرنده کمک می کند.
    این روش تقریباً این کار را برای شما انجام می دهد، اما اگر طرفدار نوشتن کدهای زیادی نیستید، به شما کمک می کند کارهای کوچک را انجام دهید. مسیر Next.js API بهترین گزینه برای حل این مشکل است.
  • ارائه سرور با Next.js برای پنهان کردن کلیدهای API.
    در این ویدئو، ایجما اونوزولیکه توضیحی در مورد چگونگی انجام این کار با رندر سمت سرور ارائه می دهد. توصیه می کنم آن را بررسی کنید.

برای خواندن این مقاله از شما تشکر می کنم. لطفاً آن را به اشتراک بگذارید و همچنین با خیال راحت به یک پروژه مثال عملی که با استفاده از مسیر Next.js API ساخته‌ام نگاهی بیندازید. اینجا.

خواندن بیشتر در مجله Smashing

سرمقاله Smashing(vf، yk، او)

Read More

سه بعدی CSS Flippy Snaps با React و GreenSock — مجله Smashing

خلاصه سریع ↬

یکی از مانتراهای اصلی Jhey سرگرم کردن یادگیری است. در این مقاله، او راه‌هایی را به شما نشان می‌دهد تا با زنده کردن ایده‌هایتان، مهارت‌های خود را ارتقا دهید – بدون هیچ فشاری و فراموش کردن بازیگوشی در کد. با این طرز فکر، هر ایده به فرصتی تبدیل می شود تا چیز جدیدی را امتحان کنید.

نامگذاری چیزها سخت است، درست است؟ خوب، “Flippy Snaps” بهترین چیزی بود که می توانستم به آن برسم. 😂 یه شب یه شب یه همچین افکتی تو تلویزیون دیدم و یه یادداشتی برای خودم گذاشتم که همچین چیزی درست کنم.

اگرچه این چیزی نیست که بخواهم به این زودی در یک وب سایت قرار دهم، اما ایجاد آن یک چالش کوچک است. برای یادگیری با کل موضع من در مورد “سربازی در کد” مطابقت دارد. به هر حال چند روز بعد نشستم پشت کیبورد و چند ساعت بعد اینو داشتم:

نسخه آزمایشی نهایی من یک برنامه React است، اما برای توضیح مکانیزم ساخت این کار نیازی به استفاده از React نداریم. ما برنامه React را زمانی ایجاد خواهیم کرد که نحوه کار کردن را مشخص کنیم.

توجه داشته باشید: قبل از اینکه شروع کنیم شایان ذکر است که عملکرد این نسخه آزمایشی تحت تأثیر اندازه شبکه قرار دارد و نمایش‌های نمایشی به بهترین وجه در مرورگرهای مبتنی بر Chromium مشاهده می‌شوند.

بیایید با ایجاد یک شبکه شروع کنیم. فرض کنید ما یک شبکه 10 در 10 می خواهیم. این 100 سلول است (به همین دلیل است که React برای چنین چیزی مفید است). هر سلول از یک عنصر تشکیل شده است که شامل قسمت جلو و پشت یک کارت قابل چرخش است.

<div class="flippy-snap">
  <!-- 100 of these -->
  <div class="flippy-snap__card flippy-card">
    <div class="flippy-card__front></div>
    <div class="flippy-card__rear></div>
  </div>
</div>

سبک های شبکه ما کاملاً ساده هستند. ما میتوانیم استفاده کنیم display: grid و از یک ویژگی سفارشی برای اندازه شبکه استفاده کنید. در اینجا ما به طور پیش فرض به 10.

.flippy-snap {
  display: grid;
  grid-gap: 1px;
  grid-template-columns: repeat(var(--grid-size, 10), 1fr);
  grid-template-rows: repeat(var(--grid-size, 10), 1fr);
}

استفاده نخواهیم کرد grid-gap در نسخه ی نمایشی نهایی، اما برای دیدن آسان تر سلول ها در حین توسعه خوب است.

قلم را ببینید [1. Creating a Grid](https://codepen.io/smashingmag/pen/porXNzB) توسط JHEY

قلم را ببینید 1. ایجاد یک شبکه توسط JHEY

در مرحله بعد، باید به کناره‌های کارت‌هایمان استایل بدهیم و تصاویر را نمایش دهیم. ما می توانیم این کار را با استفاده از خصوصیات سفارشی CSS درون خطی انجام دهیم. بیایید با به روز رسانی نشانه گذاری شروع کنیم. ما باید هر کارتی را بدانیم x و y موقعیت در شبکه

<div class="flippy-snap">
  <div class="flippy-snap__card flippy-card" style="--x: 0; --y: 0;">
    <div class="flippy-card__front"></div>
    <div class="flippy-card__rear"></div>
  </div>
  <div class="flippy-snap__card flippy-card" style="--x: 1; --y: 0;">
    <div class="flippy-card__front"></div>
    <div class="flippy-card__rear"></div>
  </div>
  <!-- Other cards -->
</div>

برای نسخه ی نمایشی، من استفاده می کنم Pug تا این را برای من تولید کند. شما می توانید HTML کامپایل شده را با کلیک بر روی “مشاهده HTML کامپایل شده” در نسخه نمایشی مشاهده کنید.

- const GRID_SIZE = 10
- const COUNT = Math.pow(GRID_SIZE, 2)
.flippy-snap
  - for(let f = 0; f 

سپس به چند سبک نیاز داریم.

.flippy-card {
  --current-image: url("https://random-image.com/768");
  --next-image: url("https://random-image.com/124");
  height: 100%;
  width: 100%;
  position: relative;
}
.flippy-card__front,
.flippy-card__rear {
  position: absolute;
  height: 100%;
  width: 100%;
  backface-visibility: hidden;
  background-image: var(--current-image);
  background-position: calc(var(--x, 0) * -100%) calc(var(--y, 0) * -100%);
  background-size: calc(var(--grid-size, 10) * 100%);
}
.flippy-card__rear {
  background-image: var(--next-image);
  transform: rotateY(180deg) rotate(180deg);
}

پشت کارت با استفاده از ترکیبی از چرخش ها موقعیت خود را به دست می آورد transform. اما، بخش جالب این است که چگونه قسمت تصویر را برای هر کارت نشان می دهیم. در این دمو، ما از یک ویژگی سفارشی برای تعریف URL برای دو تصویر استفاده می کنیم. و سپس آنها را به عنوان background-image برای هر چهره کارت

بیشتر بعد از پرش! ادامه مطلب زیر ↓

اما ترفند این است که چگونه ما را تعریف می کنیم background-size و background-position. با استفاده از خواص سفارشی --x و --y مقدار را ضرب می کنیم -100%. و سپس تنظیم می کنیم background-size به --grid-size ضربدر 100%. این قسمت صحیح تصویر را برای یک کارت مشخص نمایش می دهد.

قلم را ببینید [2. Adding an Image](https://codepen.io/smashingmag/pen/gOxNLPz) توسط JHEY

قلم را ببینید 2. اضافه کردن یک تصویر توسط JHEY

شاید متوجه شده باشید که ما داشتیم --current-image و --next-image. اما در حال حاضر هیچ راهی برای دیدن تصویر بعدی وجود ندارد. برای آن، ما به راهی برای برگرداندن کارت‌هایمان نیاز داریم. برای این کار می توانیم از یک ویژگی سفارشی دیگر استفاده کنیم.

بیایید یک را معرفی کنیم --count خاصیت و مجموعه a transform برای کارت های ما:

.flippy-snap {
  --count: 0;
  perspective: 50vmin;
}
.flippy-card {
  transform: rotateX(calc(var(--count) * -180deg));
  transition: transform 0.25s;
  transform-style: preserve-3d;
}

ما می توانیم تنظیم کنیم --count ویژگی روی عنصر حاوی محدوده به این معنی است که همه کارت ها می توانند آن مقدار را دریافت کرده و از آن استفاده کنند transform چرخش آنها روی محور x ما هم باید تنظیم کنیم transform-style: preserve-3d به طوری که ما پشت کارت ها را می بینیم. تنظیم a perspective آن چشم انداز سه بعدی را به ما می دهد.

این نسخه ی نمایشی به شما امکان می دهد تا به روز رسانی کنید --count ارزش ملک، بنابراین می توانید تأثیر آن را ببینید.

قلم را ببینید [3. Turning Cards](https://codepen.io/smashingmag/pen/LYjKbZW) توسط JHEY

قلم را ببینید 3. کارت های چرخشی توسط JHEY

در این مرحله، می توانید آن را در آنجا بپیچید و یک کنترل کننده کلیک ساده تنظیم کنید که افزایش می یابد --count با یک کلیک در هر کلیک

const SNAP = document.querySelector('.flippy-snap')
let count = 0
const UPDATE = () => SNAP.style.setProperty('--count', count++)
SNAP.addEventListener('click', UPDATE)

را حذف کنید grid-gap و شما این را دریافت خواهید کرد. روی ضربه محکم و ناگهانی کلیک کنید تا آن را برگردانید.

قلم را ببینید [4. Boring Flips](https://codepen.io/smashingmag/pen/eYEwBdN) توسط JHEY

قلم را ببینید 4. تلنگرهای خسته کننده توسط JHEY

اکنون ما مکانیک های اولیه را کار کرده ایم، زمان آن رسیده است که آن را به یک برنامه React تبدیل کنیم. اینجا کمی برای شکستن وجود دارد.

const App = () => {
  const [snaps, setSnaps] = useState([])
  const [disabled, setDisabled] = useState(true)
  const [gridSize, setGridSize] = useState(9)
  const snapRef = useRef(null)

  const grabPic = async () => {
    const pic = await fetch('https://source.unsplash.com/random/1000x1000')
    return pic.url
  }

  useEffect(() => {
    const setup = async () => {
      const url = await grabPic()
      const nextUrl = await grabPic()
      setSnaps([url, nextUrl])
      setDisabled(false)
    }
    setup()
  }, [])

  const setNewImage = async count => {
    const newSnap = await grabPic()
    setSnaps(
      count.current % 2 !== 0 ? [newSnap, snaps[1]] : [snaps[0], newSnap]
    )
    setDisabled(false)
  }

  const onFlip = async count => {
    setDisabled(true)
    setNewImage(count)
  }

  if (snaps.length !== 2) return <h1 className="loader">Loading...</h1>

  return (
    <FlippySnap
      gridSize={gridSize}
      disabled={disabled}
      snaps={snaps}
      onFlip={onFlip}
      snapRef={snapRef}
    />
  )
}

ما App جزء دسته گرفتن تصاویر و ارسال آنها به ما است FlippySnap جزء. این بخش عمده ای از آنچه در اینجا اتفاق می افتد است. برای این نسخه ی نمایشی، ما در حال گرفتن تصاویر از پاشیدن.

const grabPic = async () => {
  const pic = await fetch('https://source.unsplash.com/random/1000x1000')
  return pic.url
}

// Initial effect grabs two snaps to be used by FlippySnap
useEffect(() => {
  const setup = async () => {
    const url = await grabPic()
    const nextUrl = await grabPic()
    setSnaps([url, nextUrl])
    setDisabled(false)
  }
  setup()
}, [])

اگر دو عکس برای نمایش وجود نداشته باشد، پیام “در حال بارگیری…” را نشان می دهیم.

if (snaps.length !== 2) return <h1 className="loader">Loading...</h1>

اگر در حال گرفتن یک تصویر جدید هستیم، باید آن را غیرفعال کنیم FlippySnap بنابراین ما نمی توانیم بر روی هرزنامه کلیک کنیم.

<FlippySnap
  gridSize={gridSize}
  disabled={disabled} // Toggle a "disabled" prop to stop spam clicks
  snaps={snaps}
  onFlip={onFlip}
  snapRef={snapRef}
/>

ما اجازه می دهیم App عکس هایی را که توسط آنها نمایش داده می شود را دیکته کنید FlippySnap و به کدام ترتیب در هر تلنگر، یک تصویر جدید می گیریم و بسته به تعداد دفعاتی که ورق زده ایم، عکس های درست را تنظیم می کنیم. گزینه جایگزین این است که snaps ها را تنظیم کنید و به کامپوننت اجازه دهید ترتیب را مشخص کند.

const setNewImage = async count => {
  const newSnap = await grabPic() // Grab the snap
  setSnaps(
    count.current % 2 !== 0 ? [newSnap, snaps[1]] : [snaps[0], newSnap]
  ) // Set the snaps based on the current "count" which we get from FlippySnap
  setDisabled(false) // Enable clicks again
}

const onFlip = async count => {
  setDisabled(true) // Disable so we can't spam click
  setNewImage(count) // Grab a new snap to display
}

چگونه ممکن است FlippySnap نگاه کن اصلا چیز زیادی برای آن وجود ندارد!

const FlippySnap = ({ disabled, gridSize, onFlip, snaps }) => {
  const CELL_COUNT = Math.pow(gridSize, 2)
  const count = useRef(0)

  const flip = e => {
    if (disabled) return
    count.current = count.current + 1
    if (onFlip) onFlip(count)
  }

  return (
    <button
      className="flippy-snap"
      ref={containerRef}
      style={{
        '--grid-size': gridSize,
        '--count': count.current,
        '--current-image': `url('${snaps[0]}')`,
        '--next-image': `url('${snaps[1]}')`,
      }}
      onClick={flip}>
      {new Array(CELL_COUNT).fill().map((cell, index) => {
        const x = index % gridSize
        const y = Math.floor(index / gridSize)
        return (
          <span
            key={index}
            className="flippy-card"
            style={{
              '--x': x,
              '--y': y,
            }}>
            <span className="flippy-card__front"></span>
            <span className="flippy-card__rear"></span>
          </span>
        )
      })}
    </button>
  )
}

کامپوننت رندر تمام کارت ها و تنظیم خصوصیات سفارشی درون خطی را انجام می دهد. در onClick کنترل کننده ظرف را افزایش می دهد count. همچنین باعث می شود onFlip پاسخ به تماس اگر ایالت در حال حاضر است disabled، هیچ کاری نمی کند. آن تلنگر از disabled حالت و گرفتن یک ضربه محکم و ناگهانی جدید، هنگامی که کامپوننت دوباره رندر می شود، فلیپ را فعال می کند.

قلم را ببینید [5. React Foundation](https://codepen.io/smashingmag/pen/wvqLdGY) توسط JHEY

قلم را ببینید 5. React Foundation توسط JHEY

ما یک مؤلفه React داریم که اکنون تا زمانی که بخواهیم تصاویر جدید را درخواست کنیم، تصاویر را ورق می‌زند. اما، آن انتقال تلنگر کمی خسته کننده است. برای چاشنی آن، ما می خواهیم از آن استفاده کنیم GreenSock و امکانات آن به ویژه، “توزیع کردن” مفید. این به ما این امکان را می‌دهد تا از هر کجا که کلیک می‌کنیم، تأخیر برگرداندن کارت‌هایمان را به صورت پشت سر هم شبکه‌ای توزیع کنیم. برای انجام این کار، از GreenSock برای متحرک سازی استفاده می کنیم --count ارزش روی هر کارت

شایان ذکر است که ما در اینجا یک انتخاب داریم. می‌توانیم سبک‌ها را با GreenSock اعمال کنیم. به جای متحرک کردن --count ارزش دارایی، ما می توانیم متحرک سازی کنیم rotateX. ما می توانیم این کار را بر اساس count ref ما داریم و این همچنین برای هر چیز دیگری که در این مقاله برای انیمیشن با GreenSock انتخاب می کنیم صدق می کند. این به اولویت و موارد استفاده بستگی دارد. ممکن است احساس کنید که به‌روزرسانی ارزش ویژگی سفارشی منطقی است. مزیت این است که برای داشتن یک رفتار سبک متفاوت، نیازی به به روز رسانی هیچ جاوا اسکریپتی ندارید. ما می توانیم CSS را برای استفاده تغییر دهیم rotateY مثلا.

ما به روز شد flip تابع می تواند شبیه به این باشد:

const flip = e => {
  if (disabled) return
  const x = parseInt(e.target.parentNode.getAttribute('data-snap-x'), 10)
  const y = parseInt(e.target.parentNode.getAttribute('data-snap-y'), 10)
  count.current = count.current + 1
  gsap.to(containerRef.current.querySelectorAll('.flippy-card'), {
    '--count': count.current,
    delay: gsap.utils.distribute({
      from: [x / gridSize, y / gridSize],
      amount: gridSize / 20,
      base: 0,
      grid: [gridSize, gridSize],
      ease: 'power1.inOut',
    }),
    duration: 0.2,
    onComplete: () => {
      // At this point update the images
      if (onFlip) onFlip(count)
    },
  })
}

توجه داشته باشید که چگونه یک را دریافت می کنیم x و y ارزش با خواندن ویژگی های کارت کلیک شده است. برای این نسخه ی نمایشی، ما برخی از آنها را انتخاب کرده ایم data ویژگی های هر کارت این ویژگی ها موقعیت یک کارت را در شبکه ارتباط می دهند. ما همچنین از یک جدید استفاده می کنیم ref تماس گرفت containerRef. این به این دلیل است که ما فقط به کارت های a اشاره می کنیم FlippySnap به عنوان مثال هنگام استفاده از GreenSock.

{new Array(CELL_COUNT).fill().map((cell, index) => {
  const x = index % gridSize
  const y = Math.floor(index / gridSize)
  return (
    <span
      className="flippy-card"
      data-snap-x={x}
      data-snap-y={y}
      style={{
        '--x': x,
        '--y': y,
      }}>
      <span className="flippy-card__front"></span>
      <span className="flippy-card__rear"></span>
    </span>
  )
})}

هنگامی که ما آنها را دریافت کنید x و y ارزش ها، ما می توانیم از آنها در انیمیشن خود استفاده کنیم. استفاده كردن gsap.to ما میخواهیم آن را متحرک کنیم --count دارایی سفارشی برای هر .flippy-card این یک فرزند از containerRef.

برای توزیع تاخیر از جایی که کلیک می کنیم، مقدار را تعیین می کنیم delay برای استفاده gsap.utils.distribute. در from ارزش از distribute تابع یک آرایه حاوی نسبت هایی در امتداد محور x و y می گیرد. برای بدست آوردن این، تقسیم می کنیم x و y توسط gridSize. در base ارزش مقدار اولیه است. برای این، ما می خواهیم 0 تاخیر روی کارتی که کلیک می کنیم. در amount بزرگترین ارزش است. ما رفته ایم برای gridSize / 20 اما شما می توانید با مقادیر مختلف آزمایش کنید. چیزی بر اساس gridSize هر چند ایده خوبی است در grid مقدار به GreenSock می‌گوید که اندازه شبکه باید در هنگام محاسبه توزیع استفاده شود. آخرین اما نه کم اهمیت ترین، ease سهولت را تعریف می کند delay توزیع

gsap.to(containerRef.current.querySelectorAll('.flippy-card'), {
  '--count': count.current,
  delay: gsap.utils.distribute({
    from: [x / gridSize, y / gridSize],
    amount: gridSize / 20,
    base: 0,
    grid: [gridSize, gridSize],
    ease: 'power1.inOut',
  }),
  duration: 0.2,
  onComplete: () => {
    // At this point update the images
    if (onFlip) onFlip(count)
  },
})

در مورد بقیه انیمیشن ها، ما از مدت زمان تلنگر استفاده می کنیم 0.2 ثانیه و از آن استفاده می کنیم onComplete برای فراخوانی تماس ما. تلنگر را پاس می کنیم count به callback تا بتواند از این برای تعیین ترتیب فوری استفاده کند. مواردی مانند مدت زمان تلنگر را می توان با عبور دادن در موارد مختلف پیکربندی کرد props اگر ما بخواهیم

از کنار هم قرار دادن همه اینها به این نتیجه میرسیم:

قلم را ببینید [6. Distributed Flips with GSAP](https://codepen.io/smashingmag/pen/VwzJbpM) توسط JHEY

قلم را ببینید 6. تلنگرهای توزیع شده با GSAP توسط JHEY

کسانی که دوست دارند کمی چیزها را تحت فشار قرار دهند، ممکن است متوجه شده باشند که ما همچنان می‌توانیم روی اسنپ کلیک کنیم. و این به این دلیل است که ما غیرفعال نمی کنیم FlippySnap تا زمانی که GreenSock تکمیل شود. برای رفع این مشکل، می‌توانیم از یک مرجع داخلی استفاده کنیم که در ابتدا و انتهای استفاده از GreenSock آن را تغییر می‌دهیم.

const flipping = useRef(false) // New ref to track the flipping state

const flip = e => {
  if (disabled || flipping.current) return
  const x = parseInt(e.target.parentNode.getAttribute('data-snap-x'), 10)
  const y = parseInt(e.target.parentNode.getAttribute('data-snap-y'), 10)
  count.current = count.current + 1
  gsap.to(containerRef.current.querySelectorAll('.flippy-card'), {
    '--count': count.current,
    delay: gsap.utils.distribute({
      from: [x / gridSize, y / gridSize],
      amount: gridSize / 20,
      base: 0,
      grid: [gridSize, gridSize],
      ease: 'power1.inOut',
    }),
    duration: 0.2,
    onStart: () => {
      flipping.current = true
    },
    onComplete: () => {
      // At this point update the images
      flipping.current = false
      if (onFlip) onFlip(count)
    },
  })
}

و اکنون دیگر نمی توانیم هرزنامه خود را کلیک کنیم FlippySnap!

قلم را ببینید [7. No Spam Clicks](https://codepen.io/smashingmag/pen/jOLjmXE) توسط JHEY

قلم را ببینید 7. بدون کلیک اسپم توسط JHEY

اکنون زمان آن رسیده است که چند لمس اضافی داشته باشیم. در حال حاضر، هیچ علامت بصری وجود ندارد که بتوانیم روی خود کلیک کنیم FlippySnap. اگر وقتی ماوس را نگه می‌داریم، کارت‌ها به سمت ما بلند شوند چه؟ می توانستیم استفاده کنیم onPointerOver و دوباره از ابزار توزیع استفاده کنید.

const indicate = e => {
  const x = parseInt(e.currentTarget.getAttribute('data-snap-x'), 10)
  const y = parseInt(e.currentTarget.getAttribute('data-snap-y'), 10)
  gsap.to(containerRef.current.querySelectorAll('.flippy-card'), {
    '--hovered': gsap.utils.distribute({
      from: [x / gridSize, y / gridSize],
      base: 0,
      amount: 1,
      grid: [gridSize, gridSize],
      ease: 'power1.inOut'
    }),
    duration: 0.1,
  })
}

در اینجا، ما در حال تنظیم یک ویژگی سفارشی جدید برای هر کارت نامگذاری شده هستیم --hovered. این به یک مقدار از تنظیم شده است 0 به 1. سپس در CSS خود، می‌خواهیم سبک‌های کارت خود را به‌روزرسانی کنیم تا مقدار آن را بررسی کنیم.

.flippy-card {
  transform: translate3d(0, 0, calc((1 - (var(--hovered, 1))) * 5vmin))
             rotateX(calc(var(--count) * -180deg));
}

در اینجا می گوییم که یک کارت حداکثر بر روی محور z حرکت می کند 5vmin.

سپس این را با استفاده از هر کارت اعمال می کنیم onPointerOver تکیه گاه

{new Array(CELL_COUNT).fill().map((cell, index) => {
  const x = index % gridSize
  const y = Math.floor(index / gridSize)
  return (
    <span
      onPointerOver={indicate}
      className="flippy-card"
      data-snap-x={x}
      data-snap-y={y}
      style={{
        '--x': x,
          '--y': y,
      }}>
      <span className="flippy-card__front"></span>
      <span className="flippy-card__rear"></span>
    </span>
  )
})}

و هنگامی که اشاره گر ما از ما خارج می شود FlippySnap ما می خواهیم موقعیت کارت خود را بازنشانی کنیم.


const reset = () => {
  gsap.to(containerRef.current.querySelectorAll('.flippy-card'), {
    '--hovered': 1,
    duration: 0.1,
  })
}

و ما می توانیم این را با استفاده از onPointerLeave تکیه گاه

<button
  className="flippy-snap"
  ref={containerRef}
  onPointerLeave={reset}
  style={{
    '--grid-size': gridSize,
    '--count': count.current,
    '--current-image': `url('${snaps[0]}')`,
    '--next-image': `url('${snaps[1]}')`,
  }}
  onClick={flip}>

همه اینها را کنار هم بگذارید و به چیزی شبیه این می رسیم. نشانگر خود را روی آن حرکت دهید.

قلم را ببینید [8. Visual Inidication with Raised Cards](https://codepen.io/smashingmag/pen/wvqLdZL) توسط JHEY

قلم را ببینید 8. Visual Inidication با کارت های برجسته توسط JHEY

بعدش چی؟ چگونه در مورد یک نشانگر بارگذاری، بنابراین ما می دانیم زمانی که ما App در حال گرفتن تصویر بعدی است؟ ما می توانیم یک اسپینر بارگیری را در زمانی که ما انجام دهیم رندر کنیم FlippySnap است disabled.

{disabled && <span className="flippy-snap__loader"></span>}

او سبک هایی که می تواند یک دایره چرخان بسازد.

.flippy-snap__loader {
  border-radius: 50%;
  border: 6px solid #fff;
  border-left-color: #000;
  border-right-color: #000;
  position: absolute;
  right: 10%;
  bottom: 10%;
  height: 8%;
  width: 8%;
  transform: translate3d(0, 0, 5vmin) rotate(0deg);
  animation: spin 1s infinite;
}
@keyframes spin {
  to {
    transform: translate3d(0, 0, 5vmin) rotate(360deg);
  }
}

و این به ما نشانگر بارگذاری هنگام گرفتن یک تصویر جدید می دهد.

قلم را ببینید [9. Add Loading Indicator](https://codepen.io/smashingmag/pen/qBXzmzx) توسط JHEY

قلم را ببینید 9. نشانگر بارگذاری را اضافه کنید توسط JHEY

خودشه!

به این ترتیب ما می توانیم یک را ایجاد کنیم FlippySnap با React و GreenSock. ساختن چیزهایی که ممکن است به صورت روزانه نسازیم، سرگرم کننده است. نسخه‌های نمایشی مانند این می‌توانند چالش‌های مختلفی را ایجاد کنند و بازی حل مشکل شما را ارتقا دهند.

من آن را کمی جلوتر بردم و یک افکت اختلاف منظر به همراه مقداری صدا اضافه کردم. شما همچنین می توانید اندازه شبکه را پیکربندی کنید! (گرچه شبکه های بزرگ بر عملکرد تأثیر می گذارند.)

قلم را ببینید [3D CSS Flippy Snaps v2 (React && GSAP)](https://codepen.io/smashingmag/pen/QWMXgLb) توسط JHEY

قلم را ببینید 3D CSS Flippy Snaps v2 (React &&GSAP) توسط JHEY

شایان ذکر است که این نسخه نمایشی در مرورگرهای مبتنی بر Chromium بهترین عملکرد را دارد.

بنابراین، بعد آن را کجا می برید؟ می‌خواهم ببینم می‌توانم آن را با Three.js دوباره بسازم یا نه. که به عملکرد می پردازد. 😅

عالی بمان! ʕ•ᴥ•ʔ

سرمقاله Smashing(vf، yk، او)

Read More

زمستان 2021 – مجله Smashing

خلاصه سریع ↬

وضعیت CSS، Vue.js و Next.js چگونه است؟ الگوهای جدید و هوشمند طراحی رابط کاربری که می توانیم استفاده کنیم چیست؟ بیایید آن را بفهمیم. با ما کارگاه های آنلاین UX، جلویی و طراحی.

برای بسیاری از ما، فضای کاری شخصی می‌تواند کاملاً راحت و راحت باشد، اما هیچ‌کس واقعاً نمی‌خواهد برای یک روز کامل دیگر با تمرکز روی صفحه نمایش ثبت‌نام کند. به همین دلیل ما خودمان را می شکنیم کارگاه های آنلاین Smashing به جلسات 2.5 ساعته – با یک جلسه در روز. به این ترتیب، شما همیشه زمان کافی برای همه چیز دارید، چیزهایی را امتحان کنید، یک جلسه را دوباره تماشا کنید یا در بین جلسات سوالاتی را مطرح کنید.

ما بسیار هیجان زده هستیم که برنامه کامل کارگاه های آموزشی ماه های آینده را اعلام کنیم:

کارگاه های آنلاین ما برگزار می شود زنده و دهانه چند روز در هفته در هر جلسه، همیشه زمان کافی برای طرح سؤالات یا صرف یک فنجان چای وجود دارد. ما در محتوا عجله نمی کنیم، اما در عوض، سعی می کنیم یک استقبال ایجاد کنیم، محیطی دوستانه و فراگیر برای همه وقت برای فکر کردن، بحث کردن و گرفتن بازخورد داشته باشید.

چیزهای زیادی از یک کارگاه Smashing انتظار می رود، اما مهمترین آنها تمرکز روی مثال ها و تکنیک های عملی است. کارگاه ها گفتگو نیستند. آنها تعاملی هستند، با گفتگوهای زنده با شرکت کنندگان، گاهی اوقات با چالش ها، تکالیف و کار تیمی. البته تمام مواد کارگاهی و ضبط های ویدئویی همچنین، بنابراین اگر جلسه ای را از دست دادید، می توانید در همان روز دوباره آن را تماشا کنید.

SmashingConf سانفرانسیسکو 2022

بله رسمیه! سال آینده، ما یک SmashingConf را در هر یک از این شهرها برگزار خواهیم کرد: سانفرانسیسکو، فرایبورگ، نیویورک و آستین! در کنار کارگاه های داخلی، اولین سخنرانان قبلاً اعلام شده اند با صحبت های کارشناسان در مورد دسترسی، فرانت اند، سیستم های طراحی، عملکرد و طراحی رابط.

ما دوست داریم به صورت حضوری با شما ملاقات کنیم 28 تا 31 مارس، 2022، در اسکله در کنار پل نمادین گلدن گیت. دو روز گفتگو، تک آهنگ، دو روز کارگاه و بارهای از حوادث جانبی (همه در بلیط شما گنجانده شده است). هم برای گفتگوها و هم برای کارگاه ها، ما طیف خوبی از موضوعات داریم، از Figma تا عملکرد وب و از انیمیشن SVG تا ویژگی های سفارشی CSS. پرش به همه سخنرانان و موضوعات →


SmashingConf سانفرانسیسکو 2022
کنفرانسی دوستانه و فراگیر برای طراحان و توسعه دهندگان. بیا با هم جاز کنیم!

کنفرانس بزرگ بعدی در شهر نزدیک

کنفرانس های عالی همه در مورد یادگیری مهارت های جدید و ایجاد ارتباطات جدید هستند. به همین دلیل است که ما یک زن و شوهر راه اندازی کرده ایم ماجراهای جدید برای سال 2022 – جلسات عملی، فرمت‌های جدید، گفتگوهای جدید رعد و برق، جلسات عصرانه و مکالمات واقعی و جالب – با شبکه‌ای دوستانه!

آستین، ایالات متحده آمریکا

SmashingConf آستین 2022ما بسیار هیجان‌زده هستیم که SmashingConf را دوباره به آستین می‌آوریم 27 تا 30 ژوئن 2022. ما بررسی خواهیم کرد که چگونه فن‌آوری‌های جدید وب و تکنیک‌های در حال ظهور front-end/UX می‌توانند همه ما را طراحان و توسعه‌دهندگان بهتری کنند. جزئیات بیشتر به زودی اعلام خواهد شد – حتما در خبرنامه SmashingConf مشترک شوید یکی از اولین کسانی باشد که می داند! 🌮

فرایبورگ، آلمان

SmashingConf فرایبورگ 2022ما به زادگاه خود باز خواهیم گشت SmashingConf فرایبورگ بر روی 5-7 سپتامبر 2022. ما قلب خود را برای ایجاد رویدادهای دوستانه و فراگیر که بر مشکلات و راه حل های دنیای واقعی متمرکز هستند می ریزیم. تمرکز ما روی front-end و UX است، اما همه چیزهای تحت وب را پوشش می‌دهیم – طراحی UI یا یادگیری ماشین. نسخه فرایبورگ البته از این قاعده مستثنی نیست! 🥨

نیویورک، ایالات متحده آمریکا

SmashingConf NYC 2022هر یک از کنفرانس های Smashing ما یک رویداد دوستانه و فراگیر برای افرادی است که به کار خود اهمیت می دهند. بدون کرک، بدون پرکننده، بدون تجربه چند مسیری – فقط بینش عملی که فوراً در کار شما قابل اجرا است. برای SmashingConf NYC in به ما بپیوندید اکتبر 2022 – رویدادی که همیشه بسیار محبوب است! smashingconf@ را در توییتر دنبال کنید برای اینکه به محض ریختن لوبیا روی Who، When و Where مطلع شوید! ✨

متشکرم!

یک مخلص متشکرم برای مهربانی، حمایت مداوم و سخاوت شما – برای بودن درهم شکستن، اکنون و همیشه. با افتخار از شما استقبال می کنیم

Read More

Next.js Wildcard Subdomains — Smashing Magazine

خلاصه سریع ↬

میزبانی با یک زیر دامنه به کاربران شما امکان می دهد از سایت شما در هر زیر دامنه دامنه شما بازدید کنند (*.example.com، و همانطور که می توانید تصور کنید، ما می توانیم از این برای ایجاد تجربیات کاربری منحصر به فرد استفاده کنیم که در این مقاله از طریق لنز Next.js بررسی خواهیم کرد.

یک “کارت عام”؟ در دنیا چه؟ سوال بزرگ، این نوع دامنه ها از آن سرچشمه می گیرند سوابق DNS Wildcard که شبیه به این هستند:

*.example.               3600     TXT   "Wild! You have found a wildcard."

هنگامی که از این رکورد DNS استفاده می شود، هر زیردامنه ای که با علامت عام مطابقت دارد، یک را نگه می دارد TXT ارزش: «وحشی! شما یک وایلدکارت پیدا کرده اید.»

به عنوان مثال، اگر این روی دامنه تنظیم شده باشد smashingmagazine.com، apples.example.smashingmagazine.com و oranges.example.smashingmagazine.com هر دو مقدار TXT بالا را برمی گرداند. همین اصل را می توان برای رکوردهای CNAME و A نیز اعمال کرد.

موارد استفاده وحشی برای وایلدکارت

از وایلد کارت ها می توان برای طیف وسیعی از موارد استفاده کرد. در حال حاضر، بیایید روی جایی که می توان آنها را در ترکیب با Next.js اعمال کرد تمرکز کنیم:

  1. ارائه خدمات میزبانی شده
    رایج ترین استفاده از دامنه های wildcard این است که به کاربران سرویس های میزبانی شده فضای خود را با یک زیر دامنه منحصر به فرد ارائه می دهد. به عنوان مثال، اگر من پلتفرمی برای رستوران ها می ساختم تا پلتفرم های سفارش دیجیتال با دامنه را میزبانی کنند menus.abc، من می توانم پیتزا فروشی Dom را ارائه دهم domspizzeria.menus.abc و دامنه جادویی پراتا magicalprata.menus.abc. مزیت این کار این است که به هر یک از این مؤسسات فضای محصور خود را می دهد که می توانند آن را سفارشی کرده و بسازند. این فضا می‌تواند به‌عنوان وب‌سایت خود عمل کند – به هیچ چیز وابسته نیست.
  2. میزبانی محتوا و نمونه کارها شخصی
    Wildcards همچنین می تواند به عنوان فضایی برای میزبانی محتوا در نمونه کارها مورد استفاده قرار گیرد، که به این نمونه کارها احساس فردیت می بخشد، نمونه ای از آن نحوه ارائه زیر دامنه ها برای نویسندگان است.
  3. وایلدر موارد استفاده خلاقانه تر
    شما نمی توانید این موارد استفاده را تعریف کنید، اما موارد استفاده خلاقانه زیادی از این سبک از دامنه ها وجود دارد. به عنوان مثال، در ادامه این مقاله، ما یک اسباب‌بازی تحت وب را توسعه خواهیم داد که یک صفحه وب را وارونه می‌کند و برای استرالیایی‌ها قابل خواندن است.

هشدارهای Wildcards با Next.js

آه متأسفانه، استفاده از حروف عام کامل نیست، چند اشکال دارد:

  • بدون ایجاد سایت استاتیک (و ISR)
    متأسفانه، هیچ سیستم خاصی برای ارائه صفحات سفارشی ایستا برای زیردامنه های مختلف وایلد کارد مانند شما با مسیریابی پویا وجود ندارد (در جایی که شما دارید [slug].js فایل ها).
  • مشکلات توسعه
    هنگام توسعه محلی، شبیه‌سازی دامنه‌های wildcard می‌تواند دردسرساز باشد و ما کمی بعداً در این مقاله به این موضوع خواهیم پرداخت، اما نکته مهمی است که باید در نظر داشت.
  • پلتفرم های استقرار محدود
    Vercel از دامنه‌های Wildcard پشتیبانی می‌کند، با این حال، سایر پلتفرم‌های Jamstack گرا همه از دامنه‌های Wildcard پشتیبانی نمی‌کنند. به عنوان مثال، Netlify این ویژگی را به گروهی از کاربران در برنامه Pro محدود می کند.

ساختمان با حروف وحشی

با این همه صحبت، به ساختن با این دامنه ها می پردازیم. ما روی سه مکان تمرکز خواهیم کرد که می‌توانید عام را دریافت کنید:

  1. سمت سرور getServerSideProps،
  2. سمت مشتری با useEffect،
  3. سمت سرور در مسیرهای API و عملکردهای لبه.

سمت سرور getServerSideProps

این رایج ترین موردی است که در آن نیاز به استخراج عام دارید، می توانید از آن در صفحاتی استفاده کنید که باید محتوای کاملاً متفاوتی را برای ویلدکارت های مختلف ارائه کنید. همانطور که در بالا توضیح داده شد، این کار را نمی توان از طریق تولید سایت ایستا انجام داد، بنابراین باید آن را در صفحات رندر شده سمت سرور انجام دهیم.

در getServerSideProps یک شی متن ارسال می شود، در این شی می توانید با استفاده از شی درخواست HTTP دسترسی داشته باشید context.req. در این شی درخواست، می توانید به نام میزبان در دسترسی داشته باشید headers.host، که رشته ای مانند example.yourdomain.com. می‌توانیم رشته را به آرایه‌ای در هر نقطه تقسیم کنیم و سپس به اولین مورد در آرایه مذکور دسترسی پیدا کنیم. در کد، به شکل زیر است:

export async function getServerSideProps(context) {
  let wildcard = context.req.headers.host.split(".")[0];
  wildcard =
    wildcard != "yourdomain"
      ? process.env.NODE_ENV != "development"
        ? wildcard
        : process.env.TEST_WILDCARD
      : "home";
  return { props: { wildcard } };
}

همانطور که در این قطعه کد می بینید، اگر دامنه پایه ای باشد که ما wildcard را روی آن تنظیم می کنیم، یک پردازش مجموعه اضافی روی wildcard انجام می دهیم. home (اگر ورودی کاربر را دریافت می کنید، این موردی است که شما باید رسیدگی کنید) و اگر ما در حال آزمایش روی لوکال هاست هستیم، می توانیم حروف عام دیگر را آزمایش کنیم. در تابع صادرات پیش‌فرض ما، که صفحه ما را رندر می‌کند، می‌توانیم از دستور switch برای مدیریت حروف عام استفاده کنیم:

export default function App(props) {
  switch(props.wildcard) {
    case "home":
      return <div>Welcome to the home page!</div>;
      break;
    default:
      return <div>The wild card is: {props.wildcard}.</div>;
  }
}

سمت مشتری با useEffect

اگر فقط می خواهید تغییرات کوچکی در هر صفحه در یک علامت عام متفاوت ایجاد کنید، می توانید با استفاده از useEffect قلاب در سمت مشتری این رویکرد تقریباً شبیه روشی است که ما در آن انجام دادیم getServerSideProps، جز اینکه ما به آن تکیه خواهیم کرد window.location.hostname. استفاده كردن window به این معنی است که رندر اولیه سرور قادر به دسترسی به اطلاعات نخواهد بود، بنابراین باید آن را در a قرار دهیم useEffect قلابی که در سمت کلاینت اجرا می شود. این کد به شکل زیر است:

// useEffect and useState must be imported from 'react'

const [wildcard, setWildcard] = useState("")
  useEffect(() => {
    setWildcard(window.location.hostname.split(".")[0])
  }, [])

با این حال، این رویکرد به دور از ایده‌آل بودن است، زیرا بین اولین رندر صفحه و در دسترس بودن علامت عام تاخیر وجود دارد. بنابراین، اگر تغییرات شدیدی را بر اساس عام ایجاد می‌کنید، تغییرات برای کاربر شما آزاردهنده خواهد بود. این همچنین ممکن است به اندازه گیری تغییر چیدمان تجمعی شما در موارد حیاتی وب شما آسیب برساند. با در نظر گرفتن این موضوع، من به شدت توصیه می‌کنم استفاده از این رویکرد را به اقتباس‌هایی محدود کنید که در بارگذاری اولیه از دید بیننده دور باشند. به عنوان مثال می توان یک پاورقی مارک دار، در صفحه مستندات فنی را نام برد. البته دانستن آن هنوز هم مفید است.

سمت سرور در مسیرهای API و عملکردهای لبه

مسیرهای API منطقه دیگری است که ممکن است بخواهید از آن به یک علامت عام دسترسی داشته باشید. خوشبختانه، همان شی درخواستی که در بخش بالا در مورد آن بحث کردیم getServerSideProps همچنین هنگام استفاده از مسیر API Node.js با Next.js در دسترس است. ما می توانیم به این شکل دسترسی داشته باشیم:

export default (req, res) => {
  let wildcard = req.headers.host.split(".")[0];
  wildcard =
    wildcard != "yourdomain"
      ? process.env.NODE_ENV != "development"
        ? wildcard
        : process.env.TEST_WILDCARD
      : "home";
  res.json({ wildcard: wildcard })
}

پس از این، می‌توانیم اقدامات خاصی مانند واکشی داده‌های مختلف از پایگاه داده شما بسته به حروف عام انجام دهیم و آن را از API برگردانیم.

همین منطق را می‌توان برای توابع Edge/Middleware جدید Next.js اعمال کرد. این به شما امکان می‌دهد تا از حروف عام در بیش از یک مسیر بدون تکرار کد استفاده کنید و همچنین سرعت پردازش را افزایش می‌دهد زیرا اجرای کد در لبه اتفاق می‌افتد. در حالی که عملکرد هنوز در نسخه بتا است، مطمئناً باید مراقب آن بود.

// _middleware.js
export function middleware(req) {
  let wildcard = req.headers.get("host").split(".")[0];
  console.log(wildcard);
  wildcard =
    wildcard != "yourdomain"
      ? process.env.NODE_ENV != "development"
        ? wildcard
        : process.env.TEST_WILDCARD
      : "home";
  console.log(process.env.TEST_WILDCARD);
  return new Response(JSON.stringify({ wildcard: wildcard }), {
    status: 200,
    headers: { "Content-Type": "application/json" },
  });
}

🦘Aussie-izer

اکنون که نظریه این استراتژی را بررسی کردیم، بیایید نحوه اجرای آن را بررسی کنیم. در این بخش، ما از این رویکرد برای ساختن پروژه ای استفاده می کنیم که وب سایت ها را وارونه می کند (خوب، وب سایت هایی که از دامنه com استفاده می کنند و زیر دامنه نیستند) به نام 🦘Aussie-izer.

برای شروع، می خواهیم اجرا کنیم yarn init و سپس yarn add next react react-dom، و با افزودن این اسکریپت های استاندارد به کار خود پایان دهید package.json:

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
}

به محض اینکه یک پروژه استاندارد Next.js را راه اندازی کردیم، می خواهیم تنها فایل کدی را که برای این پروژه نیاز داریم ایجاد کنیم: pages/index.js.

اول، ما می خواهیم اضافه کنیم getServerSideProps تابعی که در آن علامت عام را استخراج می کنیم (همانطور که من این را در آن میزبانی می کنم aussieizer.sampoder.com) این چیزی است که من به آن ارزیابی خواهم کرد home مانند:

export async function getServerSideProps(context) {
  let wildcard = context.req.headers.host.split(".")[0];
  wildcard =
    wildcard != "aussieizer"
      ? wildcard != "localhost:3000"
        ? wildcard
        : process.env.TEST_WILDCARD
      : "home";
  return { props: { wildcard } };
}

سپس از آن wildcard استفاده می کنیم تا یک iFrame برای پر کردن آن صفحه (با چرخاندن iFrame برای ایجاد افکت) با src تنظیم شده است {`https://${props.wildcard}.com`}. همانطور که در بالا توضیح دادیم، از یک سوئیچ برای ارائه یک صفحه کمکی کوچک در صورت بازدید از صفحه اصلی استفاده خواهیم کرد:

export default function App(props) {
  switch (props.wildcard) {
    case "home":
      return (
        <div>
          Welcome to the Aussie-izer! This only works for .com domains. If you
          want to Aussie-ize{" "}
          <a href="https://example.com">https://example.com</a> visit{" "}
          <a href="https://example.aussieizer.sampoder.com">
            https://example.aussieizer.sampoder.com
          </a>.
        </div>
      );
      break;
    default:
      return (
        <iframe
          src={`https://${props.wildcard}.com`}
          style={{
            transform: "rotate(180deg)",
            border: "none",
            height: "100vh",
            width: "100%",
            overflow: "hidden",
          }}
          frameBorder="0"
          scrolling="yes"
          seamless="seamless"
          height="100%"
          width="100%"
        ></iframe>
      );
  }
}

و ما آماده رفتن هستیم! نسخه زنده در دسترس است https://aussieizer.sampoder.com و کد منبع را می توان در یافت https://github.com/sampoder/aussie-izer/.

میزبانی / استقرار

اگر روی یک سرور سفارشی میزبانی می‌کنید، راه‌اندازی دامنه‌های wildcard از طریق DNS آسان خواهد بود. با این حال، بخش بزرگی از استفاده از Jamstack امکان میزبانی در سرویس هایی مانند Vercel یا Netlify است. این سرویس ها سیستم های مدیریت دامنه خود را دارند.

Vercel

Vercel از دامنه های wildcard خارج از جعبه – برای همه حساب ها پشتیبانی می کند. برای استفاده از آنها ابتدا به سایت مراجعه کنید Domains بخش استقرار شما Settings زبانه در مرحله بعد، باید با استفاده از a وارد دامنه خود شوید * برای نشان دادن حروف.

برای مثال بالا وارد کردم:

*.aussieizer.sampoder.com

شما به احتمال زیاد می خواهید دامنه ریشه خود را نیز اضافه کنید (aussieizer.sampoder.com، در مورد من) برای اینکه بتوان یک صفحه اصلی یا برخی دستورالعمل ها را ارائه داد، با این حال، می تواند یک پایگاه کد جداگانه باشد.

Netlify

Netlify ویژگی های wildcard خود را به حساب های حرفه ای محدود می کند. اگر یک حساب حرفه ای دارید، باید به کارکنان پشتیبانی آنها ایمیل بزنید تا سپس این گزینه را در حساب شما فعال کنند. پس از فعال شدن در صفحه تنظیمات دامنه نشان داده می شود.

ارائه دادن

Render همچنین دامنه های wildcard را به همه کاربران ارائه می دهد. به سادگی یک دامنه با یک وارد کنید * (به معنی علامت عام شما) در Add Custom Domain ورودی را در بخش دامنه های سفارشی صفحه تنظیمات سایت خود وارد کنید که عام را فعال می کند. لطفاً توجه داشته باشید که Render از شما می‌خواهد که رکوردهای اضافی را به DNS خود اضافه کنید تا آنها بتوانند a LetsEncrypt گواهی SSL (دستورالعمل‌های دقیق زمانی که دامنه حروف عام خود را وارد می‌کنید به شما نشان داده می‌شود).

خودشه!

دامنه های Wildcard اغلب تحت رادار قرار می گیرند – امیدوارم از کاوش آنها با من لذت برده باشید. متشکرم!

همچنین: FYI استرالیایی ها در واقع وارونه نمی بینند.

خواندن بیشتر در مجله Smashing

سرمقاله Smashing(vf، yk، او)

Read More