Category: طراحی سایت

روشی هوشمند برای کنترل و همگام سازی اشتباهات تایپی و فضا – مجله Smashing

اگر بتوانیم اندازه های مشارکت طراحان را بدون دردسر پیاده سازی کنیم چه؟ اگر بتوانیم نقاط لنگر سفارشی را تنظیم کنیم تا یک مقدار کاملاً پاسخگو ایجاد کنیم و با رویکرد اندازه سیال، گزینه های بیشتری به ما بدهد؟ اگر یک فرمول جادویی داشتیم که کل پروژه را کنترل و هماهنگ می کرد، چه می شد؟

اغلب اتفاق می افتد که من دو قالب را از طراح دریافت می کنم: یکی برای موبایل و دیگری برای دسکتاپ. اخیراً از خودم می‌پرسم چگونه می‌توانم فرآیند را خودکار کنم و نتیجه را بهینه کنم. چگونه اندازه های مشخص شده را به بهترین نحو پیاده سازی کنم؟ چگونه از یک نمای تبلت راحت اطمینان حاصل کنم؟ چگونه می توانم خروجی را برای صفحه نمایش های بزرگ بهینه کنم؟ چگونه می توانم به نسبت های شدید واکنش نشان دهم؟

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

من دوست دارم بتوانم دو مقدار اندازه های مختلف (فونت، فاصله و غیره) را در پیکسل بخوانم و آنها را به عنوان آرگومان در تابعی وارد کنم که همه کارها را برای من انجام دهد. من می‌خواهم فرمول جادویی پاسخگو، FabUnit خود را ایجاد کنم.

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

چگونه می توانم قالب های طراحی را به بهترین نحو پیاده سازی کنم؟

من از نوشتن درخواست های رسانه ای برای هر مقدار خسته شده ام و می خواهم از جهش های طراحی جلوگیری کنم. تعمیر و نگهداری و نتیجه رضایت بخش نیست. بنابراین بهترین راه برای اجرای مشارکت طراح چیست؟

پرسش های رسانه ای با نقاط شکست
پرسش های رسانه ای با نقاط شکست. (پیش نمایش بزرگ)

در مورد اندازه مایعات چطور؟ ماشین حساب های دستی مانند وجود دارد اتوپیا یا حداقل – حداکثر – ماشین حساب.

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

اما برای پروژه هایم، معمولاً به گزینه های تنظیمات بیشتری نیاز دارم. نمای تبلت اغلب خیلی کوچک به نظر می رسد و من نه می توانم به درگاه های دید بزرگتر و نه نسبت تصویر واکنش نشان دهم.

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

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

خط سفارشی پاسخگو بر اساس نقاط لنگر
خط سفارشی پاسخگو بر اساس نقاط لنگر. (پیش نمایش بزرگ)

محاسبات ما باید بر اساس چه ثابت هایی از مشخصات طراحی باشد؟

بیایید نگاهی دقیق تر به مثال قبلی خود بیندازیم:

ورودی از یک طراح با مشخصات اندازه و صفحه نمایش
ورودی از یک طراح با مشخصات اندازه و صفحه نمایش. (پیش نمایش بزرگ)

اندازه فونت بدنه باید باشد 16px روی موبایل و 22px روی دسکتاپ (در ادامه با راهنمای سبک کامل می پردازیم). اندازه تلفن همراه باید از شروع شود 375px و به طور مداوم به 1024px. تا 1440px، اندازه ها باید به صورت ایستا در حد مطلوب باقی بمانند. پس از آن، مقادیر باید به صورت خطی تا مقیاس بندی شوند 2000px، پس از آن max-wrapper اعمال می شود.

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

این به ما ثابت های زیر را می دهد که برای کل پروژه اعمال می شود:

Xf  375px       global      screen-min      
Xa  1024px      global      screen-opt-start
Xb  1440px      global      screen-opt-end
Xu  2000px      global      screen-max

اندازه فونت بدنه باید حداقل باشد 16px، در حالت ایده آل 22px. حداکثر اندازه فونت در 2000px باید به طور خودکار محاسبه شود:

Yf  16px        local       size-min        
Ya  22px
Yb  22px        local       size-opt
Yu  auto

بنابراین، در پایان روز، تابع من باید بتواند دو آرگومان بگیرد – در این مورد، 16 و 22.

fab-unit(16, 22);

محاسبات

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

بنابراین، بیایید شروع کنیم!

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

گیره های اصلی را تعریف کنید

ابتدا باید بفهمیم که کدام گیره اصلی را می خواهیم تنظیم کنیم.

clamp1: clamp(Yf, slope1, Ya)
clamp2: clamp(Yb, slope2, Yu)
تعریف گیره های اصلی بر اساس نقاط لنگر مشخص شده
تعریف گیره های اصلی بر اساس نقاط لنگر مشخص شده. (پیش نمایش بزرگ)

گیره ها را ترکیب و لانه کنید

حالا باید دو گیره را با هم ترکیب کنیم. این ممکن است کمی مشکل باشد. باید در نظر بگیریم که دو خط، slope1 و slope2، بسته به میزان شیب آنها می توانند روی یکدیگر بازنویسی کنند. از آنجایی که ما می دانیم slope2 باید 45 درجه یا 100٪ (m = 1) باشد، ما می توانیم پرس و جو کنیم که آیا slope1 بالاتر از 1 است. به این ترتیب بسته به نحوه تلاقی خطوط می توانیم یک گیره متفاوت تنظیم کنیم.

تجسم دو خط متقاطع
بسته به تفاوت بین دو اندازه، خطوط شیب می توانند قطع شوند – دو گیره می توانند در تضاد باشند. (پیش نمایش بزرگ)

اگر slope1 تندتر از slope2، گیره ها را به این صورت ترکیب می کنیم:

clamp(Yf, slope1, clamp(Yb, slope2, Yu))

اگر slope1 صاف تر از slope2، این محاسبه را انجام می دهیم:

clamp(clamp(Yf, slope1, Ya), slope2, Yu)

ترکیب شده:

steep-slope
  ? clamp(Yf, slope1, clamp(Yb, slope2, Yu))
  : clamp(clamp(Yf, slope1, Ya), slope2, Yu)

Maximum Wrapper را به صورت اختیاری تنظیم کنید

اگر ماکزیمم لفافی نداشته باشیم که طرح را بالاتر از عرض معینی منجمد کند چه؟

اگر قرار نیست مقدار حداکثری تنظیم شود، عملیات را تنظیم کنید
اگر قرار نیست مقدار حداکثری تنظیم شود، عملیات را تنظیم کنید. (پیش نمایش بزرگ)

ابتدا باید بفهمیم که کدام گیره اصلی را می خواهیم تنظیم کنیم.

clamp1: clamp(Yf, slope1, Ya)
max: max(Yb, slope2)

اگر slope1 تندتر از slope2:

clamp(Yf, slope1, max(Yb, slope2))

اگر slope1 صاف تر از slope2:

max(clamp(Yf, slope1, Ya), slope2)

محاسبه بدون لفاف – الاستیک به سمت بالا:

steep-slope
  ? clamp(Yf, slope1, max(Yb, slope2))
  : max(clamp(Yf, slope1, Ya), slope2)

ترکیبی، با بسته بندی حداکثر اختیاری (اگر صفحه نمایش حداکثر باشد Xu تنظیم شده است):

Xu
  ? steep-slope
    ? clamp(Yf, slope1, clamp(Yb, slope2, Yu))
    : max(clamp(Yf, slope1, Ya), Yu)
  : steep-slope
    ? clamp(Yf, slope1, max(Yb, slope2))
    : max(clamp(Yf, slope1, Ya), slope2)

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

مقادیر گمشده را محاسبه کنید

بیایید ببینیم که کدام مقادیر را به عنوان آرگومان دریافت می کنیم و اکنون باید کدام مقادیر را محاسبه کنیم:

steep-slope
  ? clamp(Yf, slope1, clamp(Yb, slope2, Yu))
  : max(clamp(Yf, slope1, Ya), Yu)

شیب تند
بله = Yb = 22 پیکسل
Yf = 16 پیکسل
شیب 1 = Mfa
شیب 2 = امبو
یو

برای تکمیل خط پاسخگو باید دو شیب و یک نقطه لنگر به طور خودکار محاسبه شود
برای تکمیل خط پاسخگو باید دو شیب و یک نقطه لنگر به طور خودکار محاسبه شود. (پیش نمایش بزرگ)
  • steep-slope
    بررسی کنید که آیا شیب Yf → Ya بالای شیب است Yb → Yu (m = 1) :
((Ya - Yf) / (Xa - Xf)) * 100 > 1
  • Mfa
    درون یابی خطی، از جمله محاسبه شیب Yf → Ya:
Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf)
  • Mbu
    درون یابی خطی بین Yb و Yu (شیب m = 1):
100vw / Xb * Yb
  • Yu
    محاسبه موقعیت Yu:
(Xu / Xb) * Yb

همه را با هم قرار دهید

Xu
  ? ((Ya - Yf) / (Xa - Xf)) * 100 > 1
    ? clamp(Yf, Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf), clamp(Yb, 100vw / Xb * Yb, (Xu / Xb) * Yb))
    : max(clamp(Yf, Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf), Ya), (Xu / Xb) * Yb)
  : ((Ya - Yf) / (Xa - Xf)) * 100 > 1
    ? clamp(Yf, Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf), max(Yb, 100vw / Xb * Yb))
    : max(clamp(Yf, Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf), Ya), 100vw / Xb * Yb)

بهتر است برخی از محاسبات را در متغیرها ذخیره کنیم:

steep-slope = ((Ya - Yf) / (Xa - Xf)) * 100 > 1
slope1 = Yf + (Ya - Yf) * (100vw - Xf) / (Xa - Xf)
slope2 = 100vw / Xb * Yb
Yu = (Xu / Xb) * Yb

Xu
  ? steep-slope
    ? clamp(Yf, slope1, clamp(Yb, slope2, Yu))
    : max(clamp(Yf, slope1, Ya), Yu)
  : steep-slope
    ? clamp(Yf, slope1, max(Yb, slope2))
    : max(clamp(Yf, slope1, Ya), slope2)

شامل نسبت ابعاد

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

تجسم تأثیر منفی نسبت های شدید بر روی طرح رندر شده با صلیب در کادر قرمز
نسبت های بسیار زیاد می تواند تأثیر منفی بر طراحی رندر شده داشته باشد. (پیش نمایش بزرگ)

پس چه می شود اگر بتوانیم نسبت تصویر را در محاسبات خود لحاظ کنیم؟ در این مثال، می خواهیم اندازه ها را زمانی که صفحه نمایش از نسبت تصویر 16:9 عریض تر است، کوچک کنیم.

aspect-ratio = 16 / 9
screen-factor = min(100vw, 100vh * aspect-ratio)

در هر دو درونیابی شیب، ما به سادگی جایگزین می کنیم 100vw با فاکتور صفحه نمایش جدید

slope1 = Yf + (Ya - Yf) * (screen-factor - Xf) / (Xa - Xf)
slope2 = screen-factor / Xb * Yb

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

فرمول

screen-factor = min(100vw, 100vh * aspect-ratio)
steep-slope = ((Ya - Yf) / (Xa - Xf)) * 100 > 1
slope1 = Yf + (Ya - Yf) * (screen-factor - Xf) / (Xa - Xf)
slope2 = screen-factor / Xb * Yb
Yu = (Xu / Xb) * Yb

Xu
  ? steep-slope
    ? clamp(Yf, slope1, clamp(Yb, slope2, Yu))
    : max(clamp(Yf, slope1, Ya), Yu)
  : steep-slope
    ? clamp(Yf, slope1, max(Yb, slope2))
    : max(clamp(Yf, slope1, Ya), slope2)
FabUnit Visualizer که مقادیر تعریف شده توسط کاربر را می پذیرد، حداکثر اندازه محاسبه شده به صورت خودکار را نمایش می دهد و خط پاسخگوی مربوطه را ترسیم می کند.
یک دستی FabUnit Visualizer که مقادیر تعریف شده توسط کاربر را می پذیرد، حداکثر اندازه محاسبه شده به صورت خودکار را نمایش می دهد و خط پاسخگوی مربوطه را ترسیم می کند. (پیش نمایش بزرگ)

عملکرد

اکنون می توانیم فرمول را در راه اندازی خود ادغام کنیم. در این مقاله به نحوه پیاده سازی آن در Sass خواهیم پرداخت. دو تابع کمکی تضمین می‌کنند که مقادیر rem را به درستی خروجی می‌دهیم (من به جزئیات آن نمی‌پردازم). سپس نقاط لنگر و نسبت ابعاد را به عنوان ثابت (به ترتیب متغیرهای Sass) قرار می دهیم. در نهایت، نقاط مختصات فرمول خود را با نام متغیرها جایگزین می کنیم و FabUnit آماده استفاده است.

_fab-unit.scss

@use "sass:math";


/* Helper functions */

$rem-base: 10px;

@function strip-units($number) {
  @if (math.is-unitless($number)) {
      @return $number;
    } @else {
      @return math.div($number, $number * 0 + 1);
  }
}

@function rem($size){
  @if (math.compatible($size, 1rem) and not math.is-unitless($size)) {
    @return $size;
  } @else {
    @return math.div(strip-units($size), strip-units($rem-base)) * 1rem;
  }
}


/* Default values fab-unit 🪄 */

$screen-min: 375;
$screen-opt-start: 1024;
$screen-opt-end: 1440;
$screen-max: 2000;  // $screen-opt-end | int > $screen-opt-end | false
$aspect-ratio: math.div(16, 9);  // smaller values for larger aspect ratios


/* Magic function fab-unit 🪄 */

@function fab-unit(
    $size-min, 
    $size-opt, 
    $screen-min: $screen-min, 
    $screen-opt-start: $screen-opt-start, 
    $screen-opt-end: $screen-opt-end, 
    $screen-max: $screen-max,
    $aspect-ratio: $aspect-ratio
  ) {
  $screen-factor: min(100vw, 100vh * $aspect-ratio);
  $steep-slope: math.div(($size-opt - $size-min), ($screen-opt-start - $screen-min)) * 100 > 1;
  $slope1: calc(rem($size-min) + ($size-opt - $size-min) * ($screen-factor - rem($screen-min)) / ($screen-opt-start - $screen-min));
  $slope2: calc($screen-factor / $screen-opt-end * $size-opt);
  @if $screen-max {
    $size-max: math.div(rem($screen-max), $screen-opt-end) * $size-opt;
    @if $steep-slope {
      @return clamp(rem($size-min), $slope1, clamp(rem($size-opt), $slope2, $size-max));
    } @else {
      @return clamp(clamp(rem($size-min), $slope1, rem($size-opt)), $slope2, $size-max);
    }
  } @else {
    @if $steep-slope {
      @return clamp(rem($size-min), $slope1, max(rem($size-opt), $slope2));
    } @else {
      @return max(clamp(rem($size-min), $slope1, rem($size-opt)), $slope2);
    }
  }
}

چگونه از FabUnit استفاده کنیم؟

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

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

ما مقادیر مرتبط را از راهنمای سبک می خوانیم و آنها را به عنوان آرگومان به FabUnit ارسال می کنیم: fab-unit(16, 22).

style.scss

@import "fab-unit";


/* overwrite default values 🪄 */
$screen-max: 1800;


/* Style guide variables fab-unit 🪄 */

$fab-font-size-body: fab-unit(16, 22);
$fab-font-size-body-small: fab-unit(14, 16);

$fab-font-size-h1: fab-unit(60, 160);
$fab-font-size-h2: fab-unit(42, 110);
$fab-font-size-h3: fab-unit(28, 60);

$fab-space-s: fab-unit(20, 30);
$fab-space-m: fab-unit(40, 80);
$fab-space-l: fab-unit(60, 120);
$fab-space-xl: fab-unit(80, 180);


/* fab-unit in action 🪄 */

html {
  font-size: 100% * math.div(strip-units($rem-base), 16);
}

body {
  font-size: $fab-font-size-body;
}

.wrapper {
  max-width: rem($screen-max);
  margin-inline: auto;
  padding: $fab-space-m;
}

h1 {
  font-size: $fab-font-size-h1;
  border-block-end: fab-unit(2, 10) solid plum;
}

…

p {
  margin-block: $fab-space-s;
}

…
/* other use cases for calling fab-unit 🪄 */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(fab-unit(200, 500), 1fr));
  gap: $fab-space-m;
}

.thing {
  flex: 0 0 fab-unit(20, 30);
  height: fab-unit(20, 36, 660, 800, 1600, 1800);  /* min, opt, … custom anchor points */
}

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

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

بیایید به خروجی کامپایل شده نگاهی بیندازیم:

…
font-size: clamp(clamp(1.3rem, 1.3rem + 2 * (min(100vw, 177.7777777778vh) - 37.5rem) / 649, 1.5rem), min(100vw, 177.7777777778vh) / 1440 * 15, 2.0833333333rem);
…

و خروجی محاسبه شده:

font-size: 17.3542px

نگرانی های دسترسی

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

نتیجه

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

FabUnit ارائه شده در اینجا بر اساس تجربه شخصی من است و برای اکثر پروژه های من بهینه شده است. من در زمان زیادی صرفه جویی می کنم و از نتیجه راضی هستم. ممکن است شما و تیمتان رویکرد دیگری داشته باشید و بنابراین نیازهای دیگری برای FabUnit داشته باشید. خیلی خوب است اگر اکنون بتوانید FabUnit خود را مطابق با نیاز خود ایجاد کنید.

خوشحال می شوم اگر رویکرد من ایده های جدیدی را به شما القا کند. مفتخرم اگر مستقیماً از آن استفاده کنید بسته npm از FabUnit از این مقاله برای پروژه های شما.

متشکرم! 🙏🏻

مرسی الی، رومن، پاتریک، فیدی.

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

چه چیزی در Next.js 13 جدید است؟ – مجله Smashing

اکتبر آمد و رفت، و با آن، Next.js یک نسخه اصلی جدید را منتشر کرد که دارای چندین ویژگی جدید است – برخی از آنها را می توان به طور یکپارچه از برنامه Next.js 12 خود استفاده کرد، در حالی که برخی دیگر نه چندان زیاد. .

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

چه اطلاعات غلط

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

در نسخه 13، نسخه های آزمایشی بزرگ بودند و کانون توجه را به خود اختصاص دادند. این باعث شد که بسیاری از مردم کل نسخه را ناپایدار و آزمایشی بدانند – اما اینطور نیست. Next.js 13 در واقع کاملاً پایدار است و امکان ارتقای روان از نسخه 12 را فراهم می کند اگر قصد ندارید از هیچ API آزمایشی استفاده کنید. اکثر تغییرات را می توان به صورت تدریجی پذیرفت که در ادامه این پست به جزئیات آن خواهیم پرداخت.

خلاصه انتشار

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

تجربی

  • فهرست برنامه؛
  • باندلر جدید (Turbopack);
  • بهینه سازی فونت

پایدار

  • مولفه تصویر “جدید” برای جایگزینی قدیمی Image جزء به عنوان پیش فرض؛
  • پشتیبانی از ماژول ES برای next.config.mjs;
  • “جدید” Link جزء.

فهرست برنامه

این ویژگی در واقع یک بازنویسی بزرگ معماری است. این React Server Components را در جلو و مرکز قرار می دهد، از یک سیستم مسیریابی کاملاً جدید و قلاب های روتر (تحت زیر next/navigation بجای next/router) و کل داستان واکشی داده را برگرداند.

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

در نتیجه، این تغییر مدل ذهنی بزرگی را در نحوه طراحی برنامه Next.js خود ایجاد می کند.

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

بیایید مقایسه کنیم که چگونه چیزها در فهرست برنامه کار می کنند. هنگام استفاده از /pages دایرکتوری (معماری که ما تاکنون از آن استفاده کرده ایم)، داده ها از سطح صفحه واکشی می شوند و به سمت اجزای برگ آبشاری می شوند.

تجسم معماری ویژگی App Directory
(پیش نمایش بزرگ)

در مقابل، با توجه به اینکه دایرکتوری برنامه توسط مؤلفه های سرور تأمین می شود، هر جزء مسئول داده های خود است، یعنی اکنون می توانید واکشی سپس رندر هر مؤلفه ای را که نیاز دارید و آنها را به صورت جداگانه ذخیره کرده و اجرا کنید بازسازی استاتیک افزایشی (ISR) در سطح بسیار دانه ای تر.

تجسم نحوه عملکرد fetch-and-render
(پیش نمایش بزرگ)

به‌علاوه، Next.js بهینه‌سازی‌ها را انجام خواهد داد: به لطف تغییر در نحوه درخواست، درخواست‌ها حذف می‌شوند (به اجزای مختلف اجازه نمی‌دهند یک درخواست را به صورت موازی اجرا کنند). fetch روش زمان اجرا با کش کار می کند. به طور پیش‌فرض، همه درخواست‌ها از اکتشافات کش قوی (“Force-cache”) استفاده می‌کنند که می‌توان از طریق پیکربندی از آن خارج شد.

درست خواندی Next.js و React Server Components هر دو با آن تداخل دارند fetch استاندارد به منظور ارائه بهینه سازی های واکشی منابع.

شما نیازی به رفتن به “All-In” ندارید

ذکر این نکته ضروری است که انتقال از /pages معماری به /app می تواند به صورت تدریجی انجام شود، و هر دو راه حل می توانند تا زمانی که مسیرها با هم تداخل نداشته باشند، همزیستی داشته باشند. در حال حاضر وجود دارد هیچ اشاره در نقشه راه Next.js درباره منسوخ شدن پشتیبانی از /pages.

خواندن توصیه می شود: ISR در مقابل DPR: کلمات بزرگ، توضیح سریع توسط کسیدی ویلیامز

باندلر و معیارهای جدید

از اولین انتشار خود، Next.js استفاده کرده است بسته وب در زیر کاپوت. امسال، نسل جدیدی از باندلرها را مشاهده کرده‌ایم که به زبان‌های سطح پایین نوشته شده‌اند، مانند ESBuild (که Vite را تامین می‌کند)، Parcel 2 (Rust) و غیره. ما همچنین شاهد آماده‌سازی Vercel برای تغییر بزرگ در Next.js بوده‌ایم. در نسخه 12 اضافه کردند SWC به فرآیند ساخت و انتقال آنها به عنوان گامی برای جایگزینی هر دو بابل و ترسر.

در نسخه 13، آنها Turbopack را معرفی کردند، باندلر جدیدی که در Rust با خیلی نوشته شده است ادعاهای عملکرد جسورانه. بله، در توییتر بحث‌هایی در مورد اینکه کدام باندلر سریع‌ترین است و این معیارها چگونه اندازه‌گیری شده‌اند، وجود داشته است. با این حال، این که Turbopack واقعاً چقدر می تواند به پروژه های بزرگ نوشته شده در Next.js با ارگونومی بهتر از هر ابزار دیگری (برای شروع، با پیکربندی داخلی) کمک کند، فراتر از بحث است.

این ویژگی نه تنها آزمایشی است، بلکه در واقع فقط با آن کار می کند next dev. شما نباید (و از هم اکنون نمی تواند ) از آن برای ساخت تولید استفاده کنید.

بهینه سازی فونت

جدید @next/font ماژول امکان بهینه سازی عملکرد فونت های وب خود را در طول زمان ساخت فراهم می کند. دارایی های فونت را در طول زمان ساخت بارگیری می کند و آنها را در خود میزبانی می کند /public پوشه این کار باعث صرفه جویی در سفر رفت و برگشت به سرور دیگری می شود، از دست دادن اضافی جلوگیری می کند، و در نهایت فونت شما را به سریع ترین شکل ممکن تحویل می دهد و آن را به درستی با بقیه منابع ذخیره می کند.

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

علاوه بر این، @next/font دارای یک ماژول ویژه برای فونت های وب گوگل است که به راحتی در دسترس است زیرا آنها به طور گسترده استفاده می شوند:

import { Jost } from '@next/font/google';
// get an object with font styles:
const jost = Jost();
// define them in your component:
<html className={jost.className}>

ماژول همچنین در صورت استفاده از فونت های سفارشی کار می کند:

import localFont from '@next/font/local';
const myFont = localFont({ src: './my-font.woff2' });
<html className={myFont.className}>

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

مسلماً مهم‌ترین مؤلفه‌های بسته Next.js اصلاحات جزئی دریافت کرده‌اند. بعد Image از Next.js 12 اینچ زندگی دوگانه ای داشته است @next/image و @next/future/image. در Next.js 13، مؤلفه پیش‌فرض تغییر می‌کند:

  • next/image حرکت می کند به next/legacy/image;
  • next/future/image حرکت می کند به next/image.

این تغییر با یک کد مد همراه است، دستوری که سعی می‌کند کد را به طور خودکار در برنامه شما منتقل کند. این اجازه می دهد تا هنگام ارتقای Next.js، یک مهاجرت روان انجام شود:

npx @next/codemod next-image-to-legacy-image ./pages

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

برای مؤلفه پیوند جدید، تغییر نیز باید صاف باشد. این <a> عنصر درون <Link> ضروری نیست و نه توصیه می شود دیگر کد مود یا آن را حذف می کند یا a اضافه می کند legacyBehavior به مولفه خود کمک کنید.

npx @next/codemod new-link ./pages

در صورت از کار افتادن کد مد، یک اخطار درز در توسعه دهنده دریافت خواهید کرد، بنابراین مراقب ترمینال خود باشید!

ماژول های ES و انتقال خودکار ماژول

دو ارتقاء برای اکثراً تحت رادار قرار گرفته است، اما من آنها را در نظر می‌گیرم به ویژه برای افرادی که با Monorepos کار می کنند مفید است. تا به حال، اشتراک گذاری پیکربندی بین فایل های پیکربندی و سایر فایل هایی که ممکن است در زمان اجرا استفاده شوند، خیلی ارگونومیک نبود. به این دلیل است next.config.js با CommonJS به عنوان سیستم ماژول نوشته شده است، که نمی تواند از فایل های ESM وارد شود. اکنون Next.js به سادگی با افزودن از ESM پشتیبانی می کند type: "module" به شما package.json و تغییر نام next.config.jsnext.config.mjs.

توجه داشته باشید: “m” مخفف “module” است و بخشی از مشخصات Node.js برای پشتیبانی از ESM است.

برای Monorepos که از بسته‌های داخلی استفاده می‌کند (بسته‌های جاوا اسکریپت که در NPM منتشر نمی‌شوند، اما در عوض توسط برنامه‌های خواهر و برادر در monorepo از منبع مصرف می‌شوند)، یک پلاگین ویژه برای انتقال آن ماژول‌ها در زمان ساخت هنگام مصرف آنها ضروری بود. از Next.js 13 به بعد، این را می توان بدون پلاگین مرتب کرد به سادگی با ارسال یک ویژگی (تجربی) به شما next.config.mjs:

const nextConfig = {
  experimental: {
    transpilePackages: ['@my-org/internal-package'],
  },
};

شما می توانید یک نمونه را در قالب Apex-Monorepo. با این تنظیمات، می‌توانید هم مؤلفه وابستگی و هم برنامه خود را به طور همزمان بدون انتشار یا راه‌حل توسعه دهید.

چه بعد?

اگر هنوز علاقه مند به بازی در اطراف و صحبت بیشتر در مورد این ویژگی ها هستید، من یک را اجرا خواهم کرد Advanced Next.js Masterclass از 30 نوامبر – 15 دسامبر 2022 – بسیار خوشحالم که در آنجا به شما خوش آمد بگویم و به همه سؤالات شما پاسخ دهم!

کارگاه Smashing توسط آتیلا فاسینا

تا آن زمان، در نظرات زیر به من اطلاع دهید یا برای من توییت کنید @AtilaFassina در مورد چگونگی مهاجرت شما و افکار شما در مورد ویژگی های آزمایشی.

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

نحوه ایجاد انیمیشن های پیشرفته با CSS – مجله Smashing

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

ایجاد انیمیشن های پیشرفته موضوع سختی به نظر می رسد، اما خبر خوب این است که در CSS، می توانید چندین انیمیشن ساده را پشت سر هم قرار دهید تا یک انیمیشن پیچیده تر ایجاد کنید!

در این پست وبلاگ موارد زیر را خواهید آموخت:

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

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

Beziers مکعبی: آنها چیست؟

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

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

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

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

اما عملکرد تسهیل کننده چیست؟

بیایید با یک منحنی خطی شروع کنیم

دو نقطه را تصور کنید پ0 و پ1، جایی که پ0 نقطه شروع انیمیشن است و پ1 نقطه پایان است حال یک نقطه دیگر را به صورت خطی بین دو نقطه تصور کنید:

انیمیشن یک منحنی خطی بزیه
منبع: ویکیپدیا

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

بعدی: منحنی Bezier درجه دوم

تصور کنید سه امتیاز دارید: پ0، پ1 و پ2. شما می خواهید انیمیشن از آن جابجا شود پ0 به پ2. در این مورد، پ1 یک نقطه کنترل است که منحنی انیمیشن را کنترل می کند.

ساخت منحنی بزیه درجه دوم
منبع: ویکیپدیا (پیش نمایش بزرگ)

ایده Bezier درجه دوم به شرح زیر است:

  1. خطوط خیالی را بین آنها وصل کنید پ0 و پ1 و بین پ1 و پ2 (با خطوط خاکستری نشان داده شده است).
  2. نقطه س0 در امتداد خط بین حرکت می کند پ0 و پ1. در همان زمان، نقطه س1 در امتداد خط بین حرکت می کند پ1 و پ2.
  3. یک خط خیالی بین آن وصل کنید س0 و س1 (نماینده خط سبز).
  4. همزمان س0 و س1 شروع به حرکت، نقطه ب شروع به حرکت در امتداد خط سبز می کند. مسیر که نقطه ب طول می کشد مسیر انیمیشن است.
انیمیشن منحنی بزیه درجه دوم، t in [0,1]
منبع: ویکیپدیا

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

در نهایت: منحنی مکعب بزیر

منحنی مکعب بزیر از 4 نقطه تشکیل شده است: پ0، پ1، پ2 و پ3. انیمیشن در شروع می شود پ0 و به پایان می رسد پ3. پ1 و پ2 نقاط کنترل ما هستند

ساخت منحنی بزیه مکعبی
منبع: ویکیپدیا (پیش نمایش بزرگ)

بزیر مکعبی به صورت زیر عمل می کند:

  1. خطوط خیالی را بین (پ0، پ1)، (پ1، پ2) و (پ2، پ3). این با خطوط خاکستری نشان داده شده است.
  2. نکته ها س0، س1 و س2 حرکت در امتداد خطوط (پ0، پ1)، (پ1، پ2) و (پ2، پ3) به ترتیب.
  3. خطوط خیالی را بین (س0، س1) و (س1، س2). آنها با خطوط سبز نشان داده شده اند.
  4. نکته ها آر0 و آر1 حرکت در امتداد خطوط (س0، س1) و (س1، س2) به ترتیب.
  5. خط بین را وصل کنید آر0 و آر1 (با خط آبی نشان داده شده است).
  6. در نهایت، نقطه ب در امتداد خط اتصال بین حرکت می کند آر0 و آر1. این نقطه در طول مسیر انیمیشن حرکت می کند.
انیمیشن یک منحنی مکعبی Bezier، t in [0,1]
منبع: ویکیپدیا

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

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

انباشتن انیمیشن ها

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

مثلا:

animation: movePointLeft 4s linear forwards, movePointDown 3s linear forwards;

در اینجا، ما دو انیمیشن داریم، movePointLeft و movePointDown. تاخیر انیمیشن برای movePointLeft صفر خواهد بود زیرا این انیمیشنی است که می خواهیم ابتدا اجرا کنیم. با این حال، تاخیر انیمیشن برای movePointDown چهار ثانیه خواهد بود زیرا movePointLeft پس از آن زمان انجام خواهد شد.

بنابراین، animation-delay اموال به شرح زیر خواهد بود:

animation-delay: 0s, 4s;

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

مثلا:

animation: x 4s linear forwards, y 4s linear forwards, jump 2s linear forwards;

فرض کنید می خواهیم شروع کنیم x و y همزمان. در این مورد، تاخیر انیمیشن برای هر دو x و y صفر خواهد بود، در حالی که تاخیر انیمیشن برای انیمیشن پرش چهار ثانیه (نه هشت!) خواهد بود.

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

ایجاد ترن هوایی

اکنون که اصول اولیه را پوشش داده ایم، وقت آن است که آموخته هایمان را اعمال کنیم!

درک انیمیشن

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

  1. قسمت کشویی،
  2. قسمت حلقه،
  3. همچنین تعدادی انیمیشن برای ایجاد فضای افقی بین دو انیمیشن بالا وجود خواهد داشت.
مسیر ترن هوایی
(پیش نمایش بزرگ)

تنظیم چیزها

ما با ایجاد یک توپ ساده شروع خواهیم کرد که “سبد” ما برای ترن هوایی خواهد بود.

1. این را به بدنه فایل HTML جدید خود اضافه کنید:

<div id="the-cart" class="cart"></div>

2. این را به فایل CSS خود اضافه کنید:

.cart {
  background-color: rgb(100, 210, 128);
  height: 50px;
  width: 50px;
  border: 1px solid black;
  border-radius: 50px;
  position: absolute;
  left: 10vw;
  top: 30vh;
}

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

قسمت کشویی

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

@keyframes x {
  to {
    left: 40vw;
  }
}

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

animation: x 4s linear forwards

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

@keyframes y {
  to {
    top: 29.99vh;
  }
}}

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

تابع مکعب بیزیر
(پیش نمایش بزرگ)
  • حرکت آهسته به سمت راست به این معنی است که $P1$ در امتداد خواهد بود x-محور. بنابراین، ما می دانیم که در (V، 0).
    • باید یک V مناسب انتخاب کنیم که باعث شود انیمیشن ما به آرامی به سمت راست برود اما نه بیش از حد به طوری که کل فضا را اشغال کند. در این مورد متوجه شدم که 0.55 بهترین تناسب دارد.
  • برای رسیدن به اثر لغزشی، باید حرکت کنیم P2 پایین y-axis (مقدار منفی) بنابراین P2=(X, -Y).
    • Y باید ارزش زیادی داشته باشد در این مورد من انتخاب کردم Y=5000.
    • برای بدست آوردن 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, -5000) forwards;

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

animation-delay: 0s, 0s;

قلم را ببینید [Rollercoaster sliding part [forked]](https://codepen.io/smashingmag/pen/VwxXBQb) توسط یسرا عماد.

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

اضافه کردن فضای افقی

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

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

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

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

قلم را ببینید [Rollercoaster horizontal space [forked]](https://codepen.io/smashingmag/pen/dyemExY) توسط یسرا عماد.

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

قسمت حلقه

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

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

خود حلقه

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

  • یک فریم کلیدی ایجاد کنید که توپ را به موقعیت قبلی برگرداند و سپس توپ را بچرخاند:
@keyframes loop {
  from {
    transform: rotate(0deg) translateY(10vh) rotate(0deg);
  }
  to {
    transform: rotate(-360deg) translateY(10vh) rotate(360deg);
  }
}
  • فریم های کلیدی حلقه را به ویژگی انیمیشن اضافه کنید:
animation: x 4s linear forwards,
    y 4s cubic-bezier(0.55, 0, 0.2, -5000) 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;

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

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

اضافه کردن فضای افقی (دوباره)

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

@keyframes x3 {
  to {
    left: 70vw;
  }
}
  • فریم های کلیدی را به ویژگی انیمیشن اضافه کنید:
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.5s:
animation-delay: 0s, 0s, 4s, 4.5s, 4.5s, 7.5s;

خروجی نهایی

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

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

نتیجه

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

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

کارگاه های جدید Smashing Front-End & UX — مجله Smashing

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

یک گربه کوبنده دوستانه در نقش کاپیتان، در حال قایقرانی در اقیانوس.
ملاقات کارگاه های آموزشی آنلاین: جلسات زنده و تعاملی در frontend و UX.

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

کارگاه های زنده آینده (نوامبر 2022 – آوریل 2023)

کارگاه ها چگونه هستند؟

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

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

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

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

TL; DR

  • کارگاه ها گستره دارند چند روزه، تقسیم می شود جلسات 2.5 ساعته.
  • زمان کافی برای پرسش و پاسخ زنده هر روز.
  • ده ها نمونه های عملی و تکنیک ها
  • همه مطالب و موارد ضبط شده کارگاه را دریافت خواهید کرد.
  • تمامی کارگاه ها بر روی frontend و UX متمرکز هستند.
  • بسته کارگاهی بگیرید و 250 دلار صرفه جویی کنید کاهش قیمت

با رویدادهای آنلاین آتی ما در بحث‌های پیرامون سیستم‌های دسترسی و طراحی عمیق باشید – رایگان برای همهپس لطفا دوستان خود را همراه خود بیاورید

Smashing Hour
از SVG تا عملکرد، و ترجیحات رنگی به رویه پیتزا – به ویتالی و سارا بپیوندید در گفتگوهای پر جنب و جوش و تأمل برانگیزشان.
Smashing Meets
ملاقات Smashing Meets: Design Systems (سه‌شنبه، 15 نوامبر)، گردهمایی آنلاین منظم ما – این بار در سراسر سیستم‌های طراحی.

متشکرم!

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

از اینکه سرحال ماندید و به خوبی از یکدیگر مراقبت کنید متشکرم!

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

قرار دادن نمودار در GraphQL با کتابخانه Neo4j GraphQL – مجله Smashing

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

در این مقاله، روش‌هایی را بیان می‌کنم که می‌توانید با استفاده از یک پایگاه داده گراف به عنوان پشتیبان برای GraphQL API بعدی خود، با بهره‌گیری از قابلیت‌های ارائه‌شده توسط منبع باز، این مشکلات را کاهش دهید. کتابخانه Neo4j GraphQL.

نمودارها چیست و چرا به پایگاه داده نیاز دارند

اساساً، یک نمودار یک ساختار داده است که از گره ها (موجودات موجود در مدل داده) به همراه روابط بین گره ها تشکیل شده است. نمودارها همه در مورد اتصالات موجود در داده های شما هستند. به همین دلیل، روابط در مدل داده های گراف، شهروندان درجه یک هستند.

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

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

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

GraphQL به عنوان یک زبان پرس و جو پایگاه داده نیست و هرگز قرار نبوده است. این در واقع یک زبان پرس و جو است، اما فاقد بسیاری از معنایی است که ما از یک زبان جستجوی پایگاه داده واقعی مانند SQL یا Cypher انتظار داریم. این از عمد است. شما نمی خواهید کل پایگاه داده ما را در معرض همه برنامه های مشتری خود در سراسر جهان قرار دهید.

در عوض، GraphQL یک زبان پرس و جوی API برای مدل سازی است داده های برنامه به عنوان یک گراف و برای نمایش و پرس و جوی آن نمودار داده، دقیقاً همانطور که SQL و Cypher به ترتیب برای کار با پایگاه‌های داده رابطه‌ای و نموداری به‌طور هدفمند ساخته شدند. از آنجایی که یکی از عملکردهای اصلی یک برنامه API تعامل با پایگاه داده است، منطقی است که ادغام پایگاه داده GraphQL باید به ساخت API های GraphQL که توسط یک پایگاه داده پشتیبانی می شوند کمک کند. این دقیقاً همان کاری است که کتابخانه Neo4j GraphQL انجام می دهد – ساخت API های GraphQL با پشتیبانی Neo4j را آسان تر می کند.

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

بلافاصله پس از اینکه GraphQL در سال 2015 توسط فیس بوک منبع باز شد، مجموعه ای از ادغام های پایگاه داده GraphQL ظاهر شد، ظاهراً در تلاش برای رسیدگی به مشکلات n+1 معما و مشکلات مشابه Neo4j GraphQL Library یکی از این ادغام ها بود.

تجسم ارتباط بین GraphQL Client، GraphQL API و Neo4j
(پیش نمایش بزرگ)

مشکلات رایج پیاده سازی GraphQL

ساخت یک سرویس GraphQL API مستلزم انجام دو مرحله است:

  1. طرحواره را تعریف کنید و تعاریف را تایپ کنید.
  2. توابع حل‌کننده را برای هر نوع و فیلد در طرح ایجاد کنید که مسئول واکشی یا به‌روزرسانی داده‌ها در لایه داده ما خواهد بود.

ترکیب این توابع طرحواره و حل‌کننده، یک شی طرح اجرایی GraphQL را به شما می‌دهد. سپس می‌توانید شی schema را به یک لایه شبکه، مانند یک وب سرور Node.js یا تابع lambda، متصل کنید تا GraphQL API را در معرض دید مشتریان قرار دهید. اغلب توسعه‌دهندگان از ابزارهایی مانند Apollo Server یا GraphQL Yoga برای کمک به این فرآیند استفاده می‌کنند، اما انجام دو مرحله اول هنوز به عهده آنهاست.

اگر تا به حال توابع حل‌کننده را نوشته‌اید، به‌خاطر می‌آورید که ممکن است کمی خسته‌کننده باشند، زیرا معمولاً با کد واکشی داده‌های دیگ بخار پر می‌شوند. اما حتی بدتر از از دست دادن بهره وری توسعه دهندگان است مخوف n+1 مشکل پرس و جو. به دلیل روش تو در تو که توابع حل‌کننده GraphQL فراخوانی می‌شوند، یک درخواست GraphQL می‌تواند منجر به درخواست‌های رفت و برگشت متعدد به پایگاه داده شود. پرداختن به این مورد معمولاً مستلزم استراتژی دسته‌بندی و ذخیره‌سازی است که پیچیدگی بیشتری را به برنامه GraphQL شما اضافه می‌کند.

دوبرابر کردن توسعه GraphQL-First

در اصل، اصطلاح GraphQL-First Development یک فرآیند مشارکتی را توصیف کرد. تیم‌های Frontend و Backend بر روی یک طرح GraphQL به توافق می‌رسند، سپس به طور مستقل مشغول ساختن قطعات مربوطه خود از پایگاه کد می‌شوند. ادغام پایگاه داده ایده توسعه GraphQL-First را با اعمال این مفهوم در پایگاه داده نیز گسترش می دهد. تعاریف نوع GraphQL اکنون می توانند پایگاه داده را هدایت کنند.

می توانید نمونه کدهای کامل ارائه شده در اینجا را بیابید GitHub.

فرض کنید شما در حال ساختن یک برنامه بررسی کسب و کار هستید که می خواهید کسب و کارها، کاربران و نظرات کاربران را ردیابی کنید. تعاریف نوع GraphQL برای توصیف این API ممکن است چیزی شبیه به این باشد:

type Business {
  businessId: ID!
  name: String!
  city: String!
  state: String!
  address: String!
  location: Point!
  reviews: [Review!]! @relationship(type: "REVIEWS", direction: IN)
  categories: [Category!]!
    @relationship(type: "IN_CATEGORY", direction: OUT)
}

type User {
  userID: ID!
  name: String!
  reviews: [Review!]! @relationship(type: "WROTE", direction: OUT)
}

type Review {
  reviewId: ID!
  stars: Float!
  date: Date!
  text: String
  user: User! @relationship(type: "WROTE", direction: IN)
  business: Business! @relationship(type: "REVIEWS", direction: OUT)
}

type Category {
  name: String!
  businesses: [Business!]!
    @relationship(type: "IN_CATEGORY", direction: IN)
}

به استفاده از دستورالعمل طرحواره GraphQL توجه کنید @relationship در تعاریف نوع ما دستورالعمل های طرحواره GraphQL مکانیزم داخلی داخلی زبان و اجزای کلیدی برای گسترش و پیکربندی GraphQL APIها هستند – به ویژه با ادغام پایگاه داده مانند Neo4j GraphQL Library. در این مورد، @relationship دستورالعمل نوع رابطه و جهت (داخل یا خارج) را برای جفت گره ها در پایگاه داده کد می کند.

سپس از تعاریف نوع برای تعریف مدل داده های نمودار ویژگی در Neo4j استفاده می شود. به جای حفظ دو طرحواره (یکی برای پایگاه داده ما و دیگری برای API ما)، اکنون می توانید از تعاریف نوع برای تعریف API و مدل داده پایگاه داده استفاده کنید. علاوه بر این، از آنجایی که Neo4j طرحی اختیاری است، استفاده از GraphQL برای هدایت پایگاه داده، لایه ای از نوع ایمنی را به برنامه شما اضافه می کند.

مدل داده های نمودار ویژگی در Neo4j
(پیش نمایش بزرگ)

از تعاریف نوع GraphQL تا طرحواره های API کامل

در GraphQL، شما از فیلدهای مربوط به انواع خاص (Query، Mutation و Subscription) برای تعریف نقاط ورودی برای API استفاده می کنید. علاوه بر این، ممکن است بخواهید آرگومان های فیلدی را تعریف کنید که می توانند در زمان پرس و جو ارسال شوند، به عنوان مثال، برای مرتب سازی یا فیلتر کردن. کتابخانه Neo4j GraphQL با ایجاد نقاط ورودی در GraphQL API برای انجام این کار create، read، update، و delete عملیات برای هر نوع، و همچنین آرگومان های فیلد برای مرتب سازی و فیلتر کردن.

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

{
  businesses(options: { limit: 10, sort: { name: ASC } }) {
    name
  }
}

شاید بخواهید به کاربران اجازه دهید تا با جستجوی شرکت ها بر اساس نام یا کلمه کلیدی، این لیست از مشاغل را فیلتر کنند. را where بحث و جدل این نوع فیلتر را مدیریت می کند:

{
  businesses(where: { name_CONTAINS: "Brew" }) {
    name
    address
  }

سپس می توانید این آرگومان های فیلتر را برای بیان عملیات بسیار پیچیده ترکیب کنید. مثلاً می‌خواهید کسب‌وکارهایی را پیدا کنید که در دسته قهوه یا صبحانه هستند و نظرات حاوی کلمه کلیدی «ساندویچ صبحانه»:

{
  businesses(
    where: {
      OR: [
        { categories_SOME: { name: "Coffee" } }
        { categories_SOME: { name: "Breakfast" } }
      ]
    }
  ) {
    name
    address
    reviews(where: { text_CONTAINS: "breakfast sandwich" }) {
    stars
    text
  }
 }
}

برای مثال، با استفاده از داده‌های مکان، حتی می‌توانید کسب‌وکارهایی را در 1 کیلومتری مکان فعلی‌مان جستجو کنید:

{
  businesses(
    where: {
      location_LT: {
        distance: 1000
        point: { latitude: 37.563675, longitude: -122.322243 }
      }
    }
  ) {
  name
  address
  city
  state
  }
}

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

ما به حل کننده های بدبو نیاز نداریم

همانطور که قبلاً اشاره کردیم، پیاده سازی سرور GraphQL به توابع حل کننده نیاز دارد که در آن منطق تعامل با لایه داده وجود دارد. با ادغام های پایگاه داده مانند Neo4j GraphQL Library، در زمان پرس و جو برای شما برای ترجمه درخواست های GraphQL دلخواه به پرس و جوهای پایگاه داده محصور شده و تکی، حل کننده ها برای شما ایجاد می شوند. این یک پیروزی بزرگ در بهره‌وری توسعه‌دهندگان است (نیازی نیست کد واکشی داده‌های دیگ بخاری را بنویسیم – بله!). همچنین به آن می پردازد n+1 مشکل پرس و جو با ایجاد یک درخواست رفت و برگشت واحد به پایگاه داده.

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

const { ApolloServer } = require("apollo-server");
const neo4j = require("neo4j-driver");
const { Neo4jGraphQL } = require("@neo4j/graphql");

// Connect to your Neo4j instance.
const driver = neo4j.driver(
  "neo4j+s://my-neo4j-db.com",
  neo4j.auth.basic("neo4j", "letmein")
);

// Pass our GraphQL type definitions and Neo4j driver instance.
const neoSchema = new Neo4jGraphQL({ typeDefs, driver });

// Generate an executable GraphQL schema object and start
// Apollo Server.
neoSchema.getSchema().then((schema) => {
  const server = new ApolloServer({
    schema,
  });
  server.listen().then(({ url }) => {
    console.log(`GraphQL server ready at ${url}`);
  });
});

خودشه! هیچ حل کننده ای وجود ندارد.

GraphQL را با قدرت Cypher گسترش دهید

تا اینجا ما فقط در مورد پایه صحبت کردیم create، read، update، و delete عملیات چگونه می توانید منطق سفارشی را با Neo4j GraphQL Library مدیریت کنید؟

فرض کنید می‌خواهید کسب‌وکارهای توصیه‌شده را بر اساس سابقه جستجو یا بررسی به کاربران خود نشان دهید. یکی از راه‌ها این است که تابع حل‌کننده خود را با منطق ایجاد آن توصیه‌های شخصی‌سازی شده پیاده‌سازی کنید. با این حال، راه بهتری برای حفظ ضمانت عملکرد یک به یک، GraphQL به پایگاه داده وجود دارد: می‌توانید از قدرت استفاده کنید. زبان پرس و جو Cypher با استفاده از @cypher دستورالعمل طرحواره GraphQL تا منطق سفارشی خود را در تعاریف نوع GraphQL خود تعریف کنید.

Cypher یک زبان فوق العاده قدرتمند است که شما را قادر می سازد تا الگوهای گراف پیچیده را با استفاده از نحو اعلانی هنر مانند ASCII بیان کنید. من در این مقاله به جزئیات Cypher نمی پردازم، اما بیایید ببینیم چگونه می توانید وظیفه توصیه شخصی ما را با افزودن یک فیلد جدید به تعاریف نوع GraphQL خود انجام دهید:

extend type Business {
  recommended(first: Int = 1): [Business!]!
    @cypher(
      statement: """
        MATCH (this)<-[:REVIEWS]-(:Review)<-[:WROTE]-(u:User)
        MATCH (u)-[:WROTE]->(:Review)-[:REVIEWS]->(rec:Business)
        WITH rec, COUNT(*) AS score
        RETURN rec ORDER BY score DESC LIMIT $first
      """
    )
}

اینجا کسب و کار نوع دارای الف است توصیه شده فیلد، که از پرس و جوی Cypher تعریف شده در بالا برای نشان دادن مشاغل توصیه شده در زمان درخواست GraphQL استفاده می کند. برای انجام این کار نیازی به نوشتن یک حل کننده سفارشی ندارید. کتابخانه Neo4j GraphQL هنوز هم می تواند یک درخواست پایگاه داده واحد را حتی در صورت استفاده از یک سفارشی ایجاد کند توصیه شده رشته.

ادغام پایگاه داده GraphQL Under The Hood

ادغام های پایگاه داده GraphQL مانند Neo4j GraphQL Library توسط GraphQLResolveInfo هدف – شی. این شی به همه حل‌کننده‌ها، از جمله مواردی که توسط Neo4j GraphQL Library برای ما تولید شده‌اند، ارسال می‌شود. این شامل اطلاعاتی در مورد طرحواره GraphQL و عملیات GraphQL است که حل می شود. با بازرسی دقیق این شی، ادغام های پایگاه داده GraphQL می توانند پرس و جوهای پایگاه داده را در زمان قرارگیری کوئری ها ایجاد کنند.

تجسم شی GraphQLResolveInfo
(پیش نمایش بزرگ)

اگر علاقه دارید، من اخیراً در GraphQL Summit سخنرانی کردم که به جزئیات بسیار بیشتری می رود.

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

مثلا، GraphQL Mesh از Neo4j GraphQL Library برای فعال کردن Neo4j به عنوان منبع داده برای فدراسیون داده ها استفاده می کند. آیا نمی خواهید کد لازم برای ساخت یک GraphQL API برای آزمایش و توسعه را بنویسید؟ را جعبه ابزار Neo4j GraphQL یک رابط وب منبع باز و کم کد است که Neo4j GraphQL Library را در بر می گیرد. به این ترتیب، می تواند یک GraphQL API را از پایگاه داده Neo4j موجود با یک کلیک ایجاد کند.

اسکرین شات جعبه ابزار Neo4j GraphQL
(پیش نمایش بزرگ)

کجا از اینجا

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

یک کتاب هم نوشته ام برنامه های Full Stack GraphQLمنتشر شده توسط منینگ، که این موضوع را با عمق بیشتری پوشش می دهد. کتاب من مدیریت مجوز، کار با برنامه frontend و استفاده از سرویس‌های ابری مانند Auth0، Netlify، AWS Lambda، و Neo4j Aura را برای استقرار یک برنامه GraphQL تمام پشته پوشش می‌دهد. در واقع، من از این مقاله به عنوان مثال در کتاب، برنامه بررسی های تجاری را ایجاد کرده ام! به لطف Neo4j، این کتاب اکنون به عنوان یک در دسترس است دانلود رایگان.

آخرین اما نه کم‌اهمیت‌ترین، من یک جلسه زنده با عنوان «ایجاد حس داده‌های مکانی با نمودارهای دانش» در کنفرانس مجازی NODES 2022 در چهارشنبه، 16 نوامبر، تولید شده توسط Neo4j ارائه خواهم کرد. ثبت نام برای تمامی شرکت کنندگان رایگان است.

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

کنترل حرکت در مرورگر – مجله Smashing

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

در اینجا یک مثال است:

قلم را ببینید [Magic Hand – Motion controls for the web [forked]](https://codepen.io/smashingmag/pen/vYrEEYw) توسط یافی.

قلم را ببینید دست جادویی – کنترل حرکت برای وب [forked] توسط یافی.

به هر حال، برای اینکه کنترل‌های حرکتی برای شما کار کنند، به چند عنصر اصلی نیاز دارید:

  1. داده های ویدئویی از یک وب کم؛
  2. یادگیری ماشینی برای ردیابی حرکات دست؛
  3. منطق تشخیص ژست.

توجه داشته باشید: این مقاله آشنایی کلی با HTML، CSS و جاوا اسکریپت را فرض می‌کند، بنابراین اگر آن را دارید، می‌توانیم شروع کنیم. همچنین توجه داشته باشید که در صورتی که پیش‌نمایش‌ها خالی به نظر می‌رسند (مجوزهای دوربین داده نشده است) ممکن است لازم باشد روی دموهای CodePen کلیک کنید.

مرحله 1: داده های ویدئویی را دریافت کنید

اولین قدم برای ایجاد کنترل های حرکتی، دسترسی به دوربین کاربر است. ما می توانیم این کار را با استفاده از مرورگر انجام دهیم getMediaDevices API.

در اینجا یک مثال آورده شده است که داده های دوربین کاربر را دریافت می کند و آن را به a می کشاند <canvas> هر 100 میلی ثانیه:

قلم را ببینید [Camera API test (MediaDevices) [forked]](https://codepen.io/smashingmag/pen/QWxwwbG) توسط یافی.

قلم را ببینید تست API دوربین (MediaDevices) [forked] توسط یافی.

از مثال بالا، این کد داده های ویدیو را به شما می دهد و آن را به بوم می کشد:

const constraints = {
  audio: false, video: { width, height }
};

navigator.mediaDevices.getUserMedia(constraints)
  .then(function(mediaStream) {
    video.srcObject = mediaStream;
    video.onloadedmetadata = function(e) {
      video.play();
      setInterval(drawVideoFrame, 100);
    };
  })
  .catch(function(err) { console.log(err); });

function drawVideoFrame() {
  context.drawImage(video, 0, 0, width, height);
  // or do other stuff with the video data
}

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

داده های دوربین به عنوان یک شی شناخته می شود MediaStream، که سپس می توانید آن را در یک HTML پرتاب کنید <video> عنصر از طریق آن srcObject ویژگی. پس از آماده شدن ویدیو، آن را راه‌اندازی می‌کنید و سپس هر کاری را که می‌خواهید با داده‌های فریم انجام می‌دهید. در این مورد، مثال کد هر 100 میلی ثانیه یک فریم ویدئو را روی بوم می کشد.

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

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

مرحله 2: ردیابی حرکات دست

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

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

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

در اینجا کتابخانه در حال عمل است:

قلم را ببینید [MediaPipe Test [forked]](https://codepen.io/smashingmag/pen/XWYJJpY) توسط یافی.

قلم را ببینید تست MediaPipe [forked] توسط یافی.
مختصات دست بر روی بوم ارائه شده است
مختصات دست بر روی بوم ارائه شده است. (پیش نمایش بزرگ)

در اینجا تعدادی دیگ بخار برای شروع وجود دارد (اقتباس شده از MediaPipe مثال JavaScript API):

<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script>

<video class="input_video"></video>
<canvas class="output_canvas" width="1280px" height="720px"></canvas>

<script>
const videoElement = document.querySelector('.input_video');
const canvasElement = document.querySelector('.output_canvas');
const canvasCtx = canvasElement.getContext('2d');

function onResults(handData) {
  drawHandPositions(canvasElement, canvasCtx, handData);
}

function drawHandPositions(canvasElement, canvasCtx, handData) {
  canvasCtx.save();
  canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
  canvasCtx.drawImage(
      handData.image, 0, 0, canvasElement.width, canvasElement.height);
  if (handData.multiHandLandmarks) {
    for (const landmarks of handData.multiHandLandmarks) {
      drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS,
                     {color: '#00FF00', lineWidth: 5});
      drawLandmarks(canvasCtx, landmarks, {color: '#FF0000', lineWidth: 2});
    }
  }
  canvasCtx.restore();
}

const hands = new Hands({locateFile: (file) => {
  return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
hands.setOptions({
  maxNumHands: 1,
  modelComplexity: 1,
  minDetectionConfidence: 0.5,
  minTrackingConfidence: 0.5
});
hands.onResults(onResults);

const camera = new Camera(videoElement, {
  onFrame: async () => {
    await hands.send({image: videoElement});
  },
  width: 1280,
  height: 720
});
camera.start();

</script>

کد بالا کارهای زیر را انجام می دهد:

  • بارگذاری کد کتابخانه؛
  • شروع به ضبط فریم های ویدئویی کنید.
  • وقتی داده های دست وارد می شوند، نشانه های دست را روی بوم بکشید.

بیایید نگاهی دقیق تر به آن بیندازیم handData اعتراض کنید زیرا جادو در آنجا اتفاق می افتد. داخل handData است multiHandLandmarks، مجموعه ای از 21 مختصات برای قسمت های هر دست که در فید ویدیویی شناسایی شده است. در اینجا نحوه ساختار آن مختصات آمده است:

{
  multiHandLandmarks: [
    // First detected hand.
    [
      {x: 0.4, y: 0.8, z: 4.5},
      {x: 0.5, y: 0.3, z: -0.03},
      // ...etc.
    ],

    // Second detected hand.
    [
      {x: 0.4, y: 0.8, z: 4.5},
      {x: 0.5, y: 0.3, z: -0.03},
      // ...etc.
    ],

    // More hands if other people participate.
  ]
}

چند نکته:

  • دست اول لزوماً به معنای دست راست یا چپ نیست. این فقط هر کدام را که برنامه اول اتفاق می افتد تشخیص دهد. اگر می‌خواهید دست خاصی داشته باشید، باید بررسی کنید که با استفاده از کدام دست شناسایی می‌شود handData.multiHandedness[0].label و اگر دوربین شما آینه نشده باشد، به طور بالقوه مقادیر را عوض کنید.
  • به دلایل عملکرد، می‌توانید حداکثر تعداد دست‌ها را برای ردیابی محدود کنید، که قبلاً با تنظیم انجام دادیم maxNumHands: 1.
  • مختصات در یک مقیاس از تنظیم شده است 0 به 1 بر اساس اندازه بوم.

در اینجا یک نمایش تصویری از مختصات دست است:

نقشه ای از نقاط شماره گذاری شده روی یک دست
نقشه ای از نقاط شماره گذاری شده روی یک دست. (منبع: github.io) (پیش نمایش بزرگ)

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

شما می توانید از آرایه به طور مستقیم مانند این استفاده کنید handData.multiHandLandmarks[0][5]، اما پیگیری آن برای من سخت است، بنابراین ترجیح می دهم مختصات را اینگونه برچسب گذاری کنم:

const handParts = {
  wrist: 0,
  thumb: { base: 1, middle: 2, topKnuckle: 3, tip: 4 },
  indexFinger: { base: 5, middle: 6, topKnuckle: 7, tip: 8 },
  middleFinger: { base: 9, middle: 10, topKnuckle: 11, tip: 12 },
  ringFinger: { base: 13, middle: 14, topKnuckle: 15, tip: 16 },
  pinky: { base: 17, middle: 18, topKnuckle: 19, tip: 20 },
};

و سپس می توانید مختصات را به صورت زیر بدست آورید:

const firstDetectedHand = handData.multiHandLandmarks[0];
const indexFingerCoords = firstDetectedHand[handParts.index.middle];

به نظر من استفاده از حرکت مکان نما با قسمت میانی انگشت اشاره به جای نوک آن خوشایندتر بود زیرا وسط ثابت تر است.

اکنون باید یک عنصر DOM برای استفاده به عنوان مکان نما بسازید. این نشانه گذاری است:

<div class="cursor"></div>

و در اینجا سبک ها وجود دارد:

.cursor {
  height: 0px;
  width: 0px;
  position: absolute;
  left: 0px;
  top: 0px;
  z-index: 10;
  transition: transform 0.1s;
}

.cursor::after {
  content: '';
  display: block;
  height: 50px;
  width: 50px;
  border-radius: 50%;
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
  background-color: #0098db;
}

چند نکته در مورد این سبک ها:

  • مکان نما کاملاً در موقعیتی قرار دارد که می توان آن را بدون تأثیر بر جریان سند جابجا کرد.
  • قسمت بصری مکان نما در ::after شبه عنصر، و transform اطمینان حاصل می کند که قسمت بصری مکان نما حول مختصات مکان نما متمرکز شده است.
  • مکان نما دارای یک است transition برای صاف کردن حرکاتش

اکنون که یک عنصر مکان نما ایجاد کرده ایم، می توانیم با تبدیل مختصات عقربه به مختصات صفحه و اعمال آن مختصات صفحه به عنصر مکان نما، آن را جابه جا کنیم.

function getCursorCoords(handData) {
  const { x, y, z } = handData.multiHandLandmarks[0][handParts.indexFinger.middle];
  const mirroredXCoord = -x + 1; /* due to camera mirroring */
  return { x: mirroredXCoord, y, z };
}

function convertCoordsToDomPosition({ x, y }) {
  return {
    x: `${x * 100}vw`,
    y: `${y * 100}vh`,
  };
}

function updateCursor(handData) {
  const cursorCoords = getCursorCoords(handData);
  if (!cursorCoords) { return; }
  const { x, y } = convertCoordsToDomPosition(cursorCoords);
  cursor.style.transform = `translate(${x}, ${y})`;
}

function onResults(handData) {
  if (!handData) { return; }
  updateCursor(handData);
}

توجه داشته باشید که ما از CSS استفاده می کنیم transform ویژگی برای جابجایی عنصر به جای left و top. این به دلایل عملکردی است. هنگامی که مرورگر یک نما را ارائه می دهد، از طریق a عبور می کند توالی مراحل. هنگامی که DOM تغییر می کند، مرورگر باید دوباره در مرحله رندر مربوطه شروع به کار کند. این transform ویژگی به سرعت به تغییرات پاسخ می دهد زیرا در آخرین مرحله به جای یکی از مراحل میانی اعمال می شود و بنابراین مرورگر کار کمتری برای تکرار دارد.

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

مرحله 3: تشخیص حرکات

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

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

برای تعیین یک خرج کردن در کد، می‌توانیم به زمانی نگاه کنیم x، y، و z مختصات انگشت شست و سبابه به اندازه کافی تفاوت کمی بین آنها دارند. “به اندازه کافی کوچک” بسته به مورد استفاده می تواند متفاوت باشد، بنابراین با خیال راحت دامنه های مختلف را آزمایش کنید. من شخصا پیدا کردم 0.08، 0.08، و 0.11 برای راحت بودن x، y، و z مختصات، به ترتیب. در اینجا به نظر می رسد:

function isPinched(handData) {
  const fingerTip = handData.multiHandLandmarks[0][handParts.indexFinger.tip];
  const thumbTip = handData.multiHandLandmarks[0][handParts.thumb.tip];
  const distance = {
    x: Math.abs(fingerTip.x - thumbTip.x),
    y: Math.abs(fingerTip.y - thumbTip.y),
    z: Math.abs(fingerTip.z - thumbTip.z),
  };
  const areFingersCloseEnough = distance.x < 0.08 && distance.y < 0.08 && distance.z < 0.11;

  return areFingersCloseEnough;
}

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

چه اتفاقی می‌افتد وقتی انگشتان شما در لبه موقعیت نیشگون قرار دارند؟ اگر مراقب نباشیم، پاسخ هرج و مرج است.

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

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

  • هنگامی که انگشتان وارد حالت فشرده شدند، یک تایمر راه اندازی کنید.
  • اگر انگشتان به مدت کافی بدون وقفه در حالت نیشگون باقی مانده اند، تغییر را ثبت کنید.
  • اگر حالت فشرده خیلی زود قطع شد، تایمر را متوقف کنید و تغییری را ثبت نکنید.

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

به زودی به کد بازپرداخت خواهیم رسید، اما ابتدا باید با ردیابی وضعیت حرکات خود آماده شویم:

const OPTIONS = {
  PINCH_DELAY_MS: 60,
};

const state = {
  isPinched: false,
  pinchChangeTimeout: null,
};

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

const PINCH_EVENTS = {
  START: 'pinch_start',
  MOVE: 'pinch_move',
  STOP: 'pinch_stop',
};

function triggerEvent({ eventName, eventData }) {
  const event = new CustomEvent(eventName, { detail: eventData });
  document.dispatchEvent(event);
}

اکنون می توانیم یک تابع برای به روز رسانی حالت pinched بنویسیم:

function updatePinchState(handData) {
  const wasPinchedBefore = state.isPinched;
  const isPinchedNow = isPinched(handData);
  const hasPassedPinchThreshold = isPinchedNow !== wasPinchedBefore;
  const hasWaitStarted = !!state.pinchChangeTimeout;

  if (hasPassedPinchThreshold && !hasWaitStarted) {
    registerChangeAfterWait(handData, isPinchedNow);
  }

  if (!hasPassedPinchThreshold) {
    cancelWaitForChange();
    if (isPinchedNow) {
      triggerEvent({
        eventName: PINCH_EVENTS.MOVE,
        eventData: getCursorCoords(handData),
      });
    }
  }
}

function registerChangeAfterWait(handData, isPinchedNow) {
  state.pinchChangeTimeout = setTimeout(() => {
    state.isPinched = isPinchedNow;
    triggerEvent({
      eventName: isPinchedNow ? PINCH_EVENTS.START : PINCH_EVENTS.STOP,
      eventData: getCursorCoords(handData),
    });
  }, OPTIONS.PINCH_DELAY_MS);
}

function cancelWaitForChange() {
  clearTimeout(state.pinchChangeTimeout);
  state.pinchChangeTimeout = null;
}

در اینجا چیست updatePinchState() انجام می دهد:

  • اگر انگشتان با شروع یا توقف یک پینچ از آستانه پینچ عبور کرده باشند، ما یک تایمر را شروع می کنیم تا منتظر بمانیم و ببینیم آیا می توانیم تغییر حالت پینچ قانونی را ثبت کنیم.
  • اگر انتظار قطع شد، به این معنی است که تغییر فقط یک نوسان بوده است، بنابراین می‌توانیم تایمر را لغو کنیم.
  • با این حال، اگر تایمر باشد نه قطع شد، می‌توانیم حالت پینچ شده را به‌روزرسانی کنیم و رویداد تغییر سفارشی صحیح را راه‌اندازی کنیم، یعنی، pinch_start یا pinch_stop.
  • اگر انگشتان از آستانه تغییر نیشگون گرفتن عبور نکرده اند و در حال حاضر گیر کرده اند، می توانیم سفارشی ارسال کنیم. pinch_move رویداد.

می توانیم بدویم updatePinchState(handData) هر بار که داده های دستی به دست می آوریم تا بتوانیم آنها را در خود قرار دهیم onResults عملکرد مانند این:

function onResults(handData) {
  if (!handData) { return; }
  updateCursor(handData);
  updatePinchState(handData);
}

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

document.addEventListener(PINCH_EVENTS.START, onPinchStart);
document.addEventListener(PINCH_EVENTS.MOVE, onPinchMove);
document.addEventListener(PINCH_EVENTS.STOP, onPinchStop);

function onPinchStart(eventInfo) {
  const cursorCoords = eventInfo.detail;
  console.log('Pinch started', cursorCoords);
}

function onPinchMove(eventInfo) {
  const cursorCoords = eventInfo.detail;
  console.log('Pinch moved', cursorCoords);
}

function onPinchStop(eventInfo) {
  const cursorCoords = eventInfo.detail;
  console.log('Pinch stopped', cursorCoords);
}

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

در اینجا چند نمونه آورده شده است:

قلم را ببینید [Beam Sword – Fun with motion controls! [forked]](https://codepen.io/smashingmag/pen/WNybveM) توسط یافی.

قلم را ببینید شمشیر پرتو – سرگرم کننده با کنترل های حرکت! [forked] توسط یافی.

قلم را ببینید [Magic Quill – Air writing with motion controls [forked]](https://codepen.io/smashingmag/pen/OJEPVJj) توسط یافی.

قلم را ببینید Magic Quill – نوشتن هوا با کنترل حرکت [forked] توسط یافی.

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

نتیجه

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

چه موارد استفاده ای خواهید داشت؟ در نظرات به من اطلاع دهید!

سرمقاله Smashing
(yk, il)

Read More

تأثیرگذاری بر آینده CSS – مجله Smashing

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

نظرسنجی های گذشته

بنابراین، نظرسنجی های گذشته چگونه به توسعه دهندگان وب کمک کرد؟ بیایید به تأثیر کروم نگاه کنیم، همانطور که توسط ما توضیح داده شده است نیکول سالیوان، مدیر محصول برای Chrome در Google:

“من نشان دادم بخش “ویژگی های از دست رفته”. به تیمم قبل از همه گیری و ما باید روی آن کار کنیم. چندین چیز در این لیست در حال انجام است.»

در واقع، به معنای واقعی کلمه همه چیز در آن لیست اکنون در حال کار یا تکمیل است، مگر اینکه هیچ مشخصات (پایدار) برای آن وجود نداشته باشد:

  • پرس و جوهای کانتینر
    پرس و جوهای اندازه دارند در کروم 106 ارسال شد ، پرس و جوهای سبک پشت پرچم.
  • انتخابگر والد/: انتخابگر دارد
    در کروم 105 ارسال شد.
  • لانه سازی
    در حال حاضر در حال انجام است، به دلیل بحث در کارگروه CSS در مورد تغییرات لحظه آخری در نحو، کمی به تعویق افتاد.
  • 🡡 کارکرد
    هنوز مشخصاتی برای پیاده سازی وجود ندارد، اما در CSS WG روی آن کار می شود.
  • محدوده
    اجرای آزمایشی در Chrome 105 پشت پرچم.
  • 🡡 مخلوط ها
    هنوز هیچ مشخصاتی برای پیاده سازی وجود ندارد، اما ایده ها در CSS WG در حال بررسی هستند.
  • زیرشبکه
    اجرا در حال انجام است.

بیایید نگاه کنیم بخش مربوطه در نتایج 2020. همپوشانی زیادی وجود دارد، اما برخی موارد اضافی:

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

و این فقط کروم نیست. تمرکز از اینتروپ 2022 تا حد زیادی توسط این نتایج شکل گرفت.

در حال حاضر در CSS وجود ندارد
(اعتبار تصویر: وضعیت نظرات CSS 2020) (پیش نمایش بزرگ)

بعد چه می شود؟

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

چه چیزی را می خواهید بیشتر در CSS ببینید؟ تایپوگرافی بهتره؟ ویژگی های طرح بندی پاسخگو جدید؟ ویژگی های جدید برای بهبود قابلیت نگهداری؟ چیدمان؟ اجزاء؟ یک چیز دیگر؟ آسمان حد است! مطمئن شوید که رویاهای CSS خود را در نظرسنجی با ما به اشتراک بگذاریدو ممکن است به خوبی شروع به تحقق پیدا کنند.

سرمقاله Smashing
(vf, il)

Read More

CSS آینده نگر – مجله Smashing

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

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

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

اما حدس زدن جالب است. بنابراین امروز، بیایید نگاهی به برخی از ویژگی های CSS بیندازیم که ممکن است روزی به مرورگر راه پیدا کند یا نه!

کلیدهای CSS

هک چک باکس CSS برای مدت زیادی وجود داشته است بیش از ده سالو هنوز هم تنها راه برای دستیابی به هر نوع “تغییر افکت” در CSS خالص باقی می ماند (در واقع خودم اخیراً از آن استفاده کردم تغییر زبان در این صفحه).

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

این دقیقاً همان چیزی است که تب اتکینز و میریام سوزان دارند کلیدهای CSS پیشنهاد می خواهد معرفی کند. این پیشنهاد کاملاً پیچیده است، و تعداد جزئیات و موارد لبه درگیر نشان می دهد که اجرای این امر برای فروشندگان مرورگر چندان بی اهمیت نخواهد بود. اما هی، می توان رویاپردازی کرد، و در واقع، یک اجرای آزمایشی اخیراً در Chrome Canary ظاهر شد!

کلیدهای CSS در حال اجرا در Chrome Canary
کلیدهای CSS در حال اجرا در Chrome Canary. (پیش نمایش بزرگ)

عملکرد سوئیچ CSS

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

می‌توانید ظاهر و احساس سیستم‌عامل مک را به لطف گزینه‌های دسترسی آن تغییر دهید، و همچنین می‌توانید همین کار را با وب‌سایت‌ها به لطف درخواست‌های رسانه‌ای مانند «ترجیح می‌دهد-حرکت کاهش یافته» یا «ترجیح-رنگ-طرح» انجام دهید.
شما می توانید ظاهر و احساس Mac OS را به لطف گزینه های دسترسی آن تغییر دهید و همچنین می توانید همین کار را با وب سایت ها به لطف درخواست های رسانه ای مانند prefers-reduced-motion یا prefers-color-scheme. (پیش نمایش بزرگ)

نتیجه این است که ما اغلب باید این شرایط مختلف را در کد خود هدف قرار دهیم و به آنها واکنش نشان دهیم، و اینجاست که میریام سوزان switch پیشنهاد جلو می آید:

.foo {
  display: grid;
  grid-template-columns: switch(
    auto /
     (available-inline-size > 1000px) 1fr 2fr 1fr 2fr /
     (available-inline-size > 500px) auto 1fr /
   );
}

در حالی که پیشنهاد اولیه بر آزمایش تمرکز دارد available-inline-size به عنوان راهی برای تنظیم طرح های شبکه ای، می توان همین را تصور کرد switch نحوی که برای بسیاری از سناریوهای دیگر نیز به‌عنوان مکملی برای پرسش‌های رسانه و کانتینر استفاده می‌شود.

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

تایپوگرافی ذاتی

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

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

کنترل های تایپوگرافی Typetura
کنترل های تایپوگرافی Typetura. (پیش نمایش بزرگ)

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

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

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

توابع خواهر و برادر

زمانی که می خواهید تعداد زیادی آیتم را بر اساس موقعیت آنها در DOM استایل دهید، در Sass معمول است که حلقه ها را بنویسید. به عنوان مثال، برای تورفتگی تدریجی هر مورد متوالی در یک لیست، می توانید کارهای زیر را انجام دهید:

@for $i from 1 through 10 {
  ul:nth-child(#{$i}) {
    padding-left: #{$i * 5px}
  }
}

سپس معادل 10 اعلان CSS ایجاد می شود. نقطه ضعف آشکار در اینجا این است که شما با ده خط کد مواجه می شوید! همچنین، اگر لیست شما بیش از ده عنصر داشته باشد، چه؟

یک راه حل زیبا که در حال حاضر در دست کار است را sibling-count() و sibling-index() کارکرد. استفاده كردن sibling-index()، مثال قبلی می شود:

ul > li {
  padding-left: calc(sibling-index() * 5px); 
}

این یک راه حل ظریف برای یک نیاز مشترک است!

الگوهای CSS

خیلی وقت پیش، ابزار کوچکی ساختم به نام الگوسازی کنید که به شما امکان می دهد الگوها را بکشید و آنها را به کد base64 صادر کنید تا در کد CSS شما به صورت خطی قرار بگیرند. مفهوم من این بود که به شما اجازه می دادم از الگوهای داخل CSS اما با استفاده کنید CSS Doodle. یوان چوان ایده مخالفی داشت: اگر از CSS استفاده می کردید چه می شد ایجاد کردن الگوها؟

CSS Doodle: یک ابزار فریبنده قدرتمند با یک نحو ساده
CSS Doodle: یک ابزار فریبنده قدرتمند با یک نحو ساده. (پیش نمایش بزرگ)

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

بدیهی است که CSS Doodle احتمالاً بسیار پیچیده‌تر از API الگوی بومی است که تا به حال نیاز داشته باشد، اما هنوز هم جالب است که تصور کنیم تنها با چند ویژگی متمرکز بر الگوی بیشتر چه کاری می‌توانیم انجام دهیم. این @image پیشنهاد ممکن است گامی در این مسیر باشد، زیرا ابزارهایی را در اختیار شما قرار می دهد تا تصاویر را درست در داخل کد CSS خود تعریف یا تغییر دهید.

نمودارهای بومی HTML/CSS

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

اکنون، اکثر نمودارهایی که در وب با آنها روبرو می شوید با استفاده از SVG یا گاهی اوقات Canvas ارائه می شوند. در واقع، این رویکردی است که ما برای نظرسنجی ها از طریق کتابخانه DataViz استفاده می کنیم نیوو.

مشکل بزرگ با این، این است که نه SVG و نه Canvas واقعا پاسخگو نیستند. شما می توانید آنها را به طور متناسب کاهش دهید، اما نمی توانید همان کنترل دقیقی را که چیزی مانند CSS Grid ارائه می دهد، داشته باشید.

به همین دلیل است که برخی سعی کرده‌اند نمودارهایی را با استفاده از HTML و CSS خالص چیدمان کنند کتابخانه نمودار Charts.css.

Charts.css: ایجاد نمودار فقط با HTML و CSS
Charts.css: ایجاد نمودار فقط با HTML و CSS. (پیش نمایش بزرگ)

مشکل اینجاست که وقتی از نمودارهای نوار بلوکی ساده عبور کردید، باید از هک های زیادی و کدهای پیچیده CSS برای رسیدن به آنچه می خواهید استفاده کنید. می تواند کار کند، و کتابخانه ها دوست دارند Charts.css کمک زیادی می کنند، اما به هیچ وجه آسان نیست.

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

<linechart>
  <series id=”series_a”>
    <point x=”0” y=”2”/>
    <point x=”1” y=”4”/>
    <point x=”2” y=”6”/>
  </series>
  <series id=”series_b”>
    <point x=”0” y=”6”/>
    <point x=”1” y=”4”/>
    <point x=”2” y=”2”/>
  </series>
</linechart>

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

البته، این چیزی است که در حال حاضر از طریق مؤلفه های وب امکان پذیر است و بسیاری در حال آزمایش در این مسیر هستند. اما شما نمی توانید سادگی HTML/CSS خالص را شکست دهید.

و همچنین…

در اینجا چند مورد سریع دیگر وجود دارد تا شما را سرپا نگه دارد:

پرس و جوهای سبک کانتینر

شاید قبلاً می‌دانید که کوئری‌های ظرف به شما امکان می‌دهند سبک یک عنصر را بر اساس عرض یا ارتفاع عنصر حاوی آن تعریف کنید. پرس و جوهای سبک ظرف به شما اجازه می دهد همین کار را انجام دهید، اما بر اساس سبک آن کانتینر – حدس زدید -، و در واقع یک پیاده سازی آزمایشی برای آن در Chrome Canary وجود دارد.

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

.posts {
  container-name: posts;
}

@container posts (background-color: #f8a100) {
  /* Change styles when `posts` container has an orange background */
  .post {
    color: #fff;
  }
}

این کمی شبیه است :has()، اگر :has() به شما امکان می‌دهد بر اساس سبک‌ها و نه فقط ویژگی‌ها و ویژگی‌های DOM انتخاب کنید، که حالا که به آن فکر می‌کنم، ممکن است یکی دیگر از ویژگی‌های جالب باشد!

اعداد تصادفی

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

استفاده از تکنیک Cicada Principle برای شبیه سازی الگوهای تصادفی
استفاده از تکنیک “اصل سیکادا” برای شبیه سازی الگوهای تصادفی. (پیش نمایش بزرگ)

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

انتخابگر مختصات شبکه

اگر می‌توانید آیتم‌های شبکه‌ای را بر اساس موقعیت آنها در طرح‌بندی شبکه‌ای یا فلکس‌باکس هدف‌گیری کنید، چه با طراحی یک سطر یا ستون خاص یا حتی با هدف‌گیری یک آیتم خاص از طریق آن x و y مختصات؟

ممکن است در ابتدا یک مورد خاص به نظر برسد، اما همانطور که از Grid و Subgrid بیشتر و بیشتر استفاده می کنیم، ممکن است به روش های جدیدی برای هدف قرار دادن آیتم های شبکه خاص نیز نیاز داشته باشیم.

استایل فرم بهتر

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

و در حالی که همه چیز بهتر شده است، مطمئناً هنوز چیزهای زیادی وجود دارد که می‌توانیم هنگام شکل‌دهی استایل ورودی و به‌طور کلی سبک‌دهی به ویجت‌های بومی بهبود دهیم. جدید <selectmenu> عنصر پیشنهاد در حال حاضر یک شروع عالی در این مسیر است.

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

همه ما با این مواجه شده‌ایم: شما می‌خواهید ارتفاع یک عنصر را متحرک کنید 0 خوب، هر چقدر هم که برای نمایش محتویاتش باید بزرگ باشد، و آن وقت است که متوجه می شوید CSS به شما اجازه نمی دهد متحرک سازی کنید یا به auto.

وجود دارد راه حل ها، اما هنوز هم خوب است که این مشکل در سطح مرورگر برطرف شود. برای اینکه این اتفاق بیفتد، ما همچنین باید بتوانیم از آن استفاده کنیم auto داخل calc، مثلا calc(auto / 2 + 200px / 2).

پیش بینی آینده

حالا بیایید برای لحظه ای واقعی باشیم: شانس اجرای هر یک از این ویژگی ها (چه رسد به اینکه در همه مرورگرهای اصلی پشتیبانی شود) بسیار اندک است، حداقل اگر به چند سال آینده نگاه کنیم.

اما باز هم مردم همین فکر را کردند :has() یا تودرتوی CSS بومی، و به نظر می رسد که ما به خوبی در راه هستیم تا بتوانیم از این دو – و بسیاری دیگر – در کد خود زودتر استفاده کنیم.

پس بیایید پنج سال بعد دوباره بیس را لمس کنیم و ببینیم چقدر اشتباه کردم. تا آن زمان، من به ترسیم مسیر CSS از طریق نظرسنجی های سالانه خود ادامه خواهم داد. و امیدوارم به ما کمک کنید شرکت در نظرسنجی امسال!

با تشکر از Lea Verou و Bramus Van Damme برای کمک به این مقاله.

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

Read More

کتاب Smashing جدید اینجاست – مجله Smashing

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

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

درک حریم خصوصی

درباره کتاب

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

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

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

این کتاب است یک کتابچه راهنمای مرجع قانونی نیست. پس از خواندن آن، درک خود را از دیدگاه منفی نسبت به حریم خصوصی به عنوان یک الزام قانونی ترسناک به یک نگاه مثبت به حریم خصوصی به عنوان فرصتی برای ساخت و طراحی وب بهتر. دانلود یک نمونه PDF رایگان (11 مگابایت).

288 صفحه. نوشته شده توسط هدر برنز طراحی جلد توسط Espen Brunborg. کتاب الکترونیکی اکنون در دسترس است، چاپ در ماه نوامبر ارسال می شود.

یاد خواهید گرفت:

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

این کتاب مال کیه؟

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

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

فهرست مطالب

288 صفحه. کتاب الکترونیکی اکنون در دسترس است، چاپ در ماه نوامبر ارسال می شود. نوشته شده توسط هدر برنز طراحی جلد توسط Espen Brunborg.

درباره نویسنده

هدر برنزهدر برنز (@WebDevLaw) هست یک حرفه ای سیاست فنی و یک مدافع برای اینترنت باز که از حقوق بشر برای حفظ حریم خصوصی، دسترسی و آزادی بیان حمایت می کند. او از زمانی که اولین وب‌سایت خود را در سال 1996 ایجاد کرد، علاقه زیادی به حفظ حریم خصوصی داشت و هزاران متخصص در سراسر جهان را در مورد اصول یک رویکرد سالم برای محافظت از افراد و داده‌های آنها آموزش داده است. او در گلاسکو، اسکاتلند زندگی می کند.

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

بررسی ها و توصیفات

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

مایک لیتل، یکی از بنیانگذاران وردپرس

ناتاشا لوماس«دیگر بهانه ای برای نادیده گرفتن حریم خصوصی وجود ندارد: راهنمای هدر یک راهنما است جعبه ابزار ضروری برای توسعه دهندگان محصول با محوریت کاربر و برای هر کسی که علاقه مند به ساخت یک وب بهتر است. انتظار یک جاروی کامل، از بافت تاریخی و مفاهیم اصلی در عمل حریم خصوصی ایالات متحده و اتحادیه اروپا، را داشته باشید نکات و توصیه های عملی – به سبک بسیار خوانا توزیع شده است.

ناتاشا لوماس، خبرنگار ارشد، Techcrunch.com

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

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

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

رابین برژون، رئیس سابق اداره داده ها در نیویورک تایمز

جزییات فنی

  • شابک: 978-3-945749-64-7 (چاپ)
  • جلد گالینگور با کیفیت، صحافی دوخته شده، نشانگر صفحه روبانی.
  • رایگان در سراسر جهان حمل و نقل از آلمان، از نوامبر 2022 شروع می شود.
  • کتاب الکترونیکی در حال حاضر موجود است به صورت PDF، ePUB و Amazon Kindle.
  • دریافت کتاب (چاپ گالینگور + کتاب الکترونیکی)
از حمایت همیشگی شما بسیار سپاسگزارم، همگی!

تولید یک کتاب زمان زیادی می برد و ما نمی توانستیم بدون حمایت فوق العاده خود آن را به پایان برسانیم. انجمن. یک فریاد بزرگ برای اعضای Smashing برای حمایت مهربان و مداوم. کتاب الکترونیکی رایگان است و همیشه رایگان خواهد بود Smashing Members. بعلاوه، اعضا هنگام خرید نسخه چاپی خود از تخفیف دوستانه برخوردار می شوند. فقط گفتن! 😉

کتاب‌ها و چیزهای شگفت‌انگیز بیشتر

ترویج بهترین شیوه ها و ارائه نکات عملی به شما برای تسلط بر چالش های کدنویسی و طراحی روزانه همیشه بوده (و خواهد بود) هسته اصلی هر کاری که انجام می دهیم در Smashing.

در چند سال گذشته، ما بسیار خوش شانس بودیم که با تعدادی از افراد با استعداد و دلسوز از جامعه وب همکاری کردیم تا تجربیات فراوان خود را به عنوان کتاب های چاپی که در آزمون زمان مقاومت می کنند منتشر کنیم. استیون و استفان دو نفر از این افراد هستند. آیا قبلاً کتابهای آنها را بررسی کرده اید؟

Read More

تایپوگرافی سیال آسان با گیره() با استفاده از توابع Sass – مجله Smashing

تایپوگرافی سیال بسیار محبوب شده است، به ویژه از زمانی که clamp() تابع ریاضی در هر مرورگر همیشه سبز موجود است. اما اگر صادق باشیم، هنوز هم برای رسیدن به این هدف، ریاضیات زیادی است. می توانید از ابزارهایی مانند utopia.fyi، که فوق العاده هستند. اما در پروژه های بزرگ، می تواند خیلی سریع به هم ریخته شود. من از طرفداران پر و پا قرص کدهای قابل خواندن و نگهداری هستم و همیشه می خواهم ببینم کد من در یک نگاه چه می کند. من مطمئن هستم که تعداد بیشتری از شما مانند آن هستند، بنابراین به جای اضافه کردن کامل clamp() عملکرد داخل کد ما، شاید بتوانیم با Sass این را کمی خواناتر کنیم.

چرا باید از تایپوگرافی سیال استفاده کنیم؟

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

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

این در حال حاضر در تمام مرورگرهای همیشه سبز امکان پذیر است زیرا clamp() عملکرد در CSS برای این کار عالی است و نوشتن پرس و جوی رسانه ما را کاهش می دهد، بنابراین مقداری از حجم فایل را در طول مسیر ذخیره می کنیم.

دقیقا چگونه این کار را انجام می دهد clamp() تابع کار برای تایپوگرافی؟

به طور خلاصه، عملکرد گیره به صورت زیر است:

clamp([min-bound], [value-preferred], [max-bound]);

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

اگر می‌خواهید توضیح عمیق‌تری در مورد ریاضیات داشته باشید، پیشنهاد می‌کنم این پست از Adrian Bece «مدرن تایپوگرافی سیال با استفاده از گیره CSS» را بخوانید.

با این حال، کمی مشکل وجود دارد. وقتی آنها را می خوانی clamp توابع داخل CSS شما، هنوز هم دیدن اینکه دقیقا چه اتفاقی می افتد دشوار است. فقط یک فایل پر از اندازه فونت را تصور کنید که شبیه این است:

clamp(1.44rem, 3.44vw + 0.75rem, 2.81rem)

اما با کمک کمی از sass عملکرد، ما می توانیم این اندازه فونت ها را بسیار خواناتر کنیم.

ما می خواهیم با این تابع ساده Sass به چه چیزی برسیم؟

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

حداقل و حداکثر اندازه فونت به راحتی پوشش داده می شود. اگر حداقل اندازه فونت را می خواهیم 16px (یا 1rem) و حداکثر اندازه فونت 32px (یا 2rem، ما قبلاً دو بخش از عملکرد گیره خود را داریم:

clamp(1rem, [?], 2rem)
بیشتر بعد از پرش! ادامه مطلب زیر ↓

ایجاد یک تابع پایه سیال خودکار

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

به طور خلاصه، معادله به صورت زیر است:

(حداکثر اندازه قلم – حداقل اندازه قلم) / (حداکثر نقطه شکست – حداقل نقطه شکست)

بیایید برای انجام برخی ریاضیات آماده شویم تا این اتفاق در Sass رخ دهد، بنابراین بیایید خود را ایجاد کنیم fluid-typography.scss فایل تابع و با اضافه کردن شروع کنید sass:math و تابع با مقادیری که نیاز داریم:

@use "sass:math";

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
 
}

حالا، بیایید محاسبه شیب داخل تابع خود را با مقداری اضافه کنیم sass:math:

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
 $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
}

برای بدست آوردن مقداری که بتوانیم با آن کار کنیم، باید شیب خود را در ضرب کنیم 100:

$slope-to-unit: $slope * 100;

تنها چیزی که باقی می ماند این است که ما رهگیری خود را برای ساختن معادله پیدا کنیم. با تابع زیر می توانیم این کار را انجام دهیم:

$intercept: $min-size - $slope * $min-breakpoint;

و در نهایت تابع ما را برگردانیم:

@return clamp(#{$min-size}, #{$slope-to-unit}#{$unit} + #{$intercept}, #{$max-size});

اگر ایجاد شده را صدا کنیم sass عملکرد در scss ما، اکنون باید تایپوگرافی سیال را دریافت کنیم:

h1 {
   font-size: #{fluid(1rem, 2rem, 25rem, 62.5rem)}
}

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

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

h1 {
   font-size: #{fluid(1rem, 2rem, 25rem, 62.5rem, vh)}
}

به روز رسانی تابع برای طبیعی تر کردن محاسبات

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

اول، ما به یک تابع اضافی برای محاسبه خود نیاز داریم rem مقادیر بر اساس ورودی پیکسل

توجه داشته باشید: اگر پایه خود را تغییر دهید، این کار نمی کند rem ارزش.

@function px-to-rem($px) {
    $rems: math.div($px, 16px) * 1rem;
    @return $rems;
}

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

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: $slope * 100;
    $intercept-rem: px-to-rem($min-size - $slope * $min-breakpoint);
    $min-size-rem: px-to-rem($min-size);
    $max-size-rem: px-to-rem($max-size);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

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

font-size: #{fluid(16px, 32px, 320px, 960px)}

این منجر به موارد زیر خواهد شد:

font-size: clamp(1rem, 2.5vw + 0.5rem, 2rem);

در نگاه اول، این کامل به نظر می رسد، اما بیشتر به این دلیل است که من از مقادیر بسیار ساده استفاده کرده ام. به عنوان مثال، هنگام بستن به حداکثر مقدار از 31px بجای 32px، ما rem مقادیر چندان گرد نخواهند بود و خروجی ما کمی نامرتب خواهد شد.

ورودی:

font-size: #{fluid(16px, 31px, 320px, 960px)}

خروجی:

font-size: clamp(1rem, 2.34375vw + 0.53125rem, 1.9375rem);

اگر شما هم مثل من هستید و این را نیز کمی نامرتب می‌دانید، می‌توانیم مقادیر خود را کمی گرد کنیم تا خوانایی را افزایش دهیم و مقداری بایت را در فایل CSS نهایی خود ذخیره کنیم. همچنین، اگر همیشه مجبور به اضافه کردن viewport باشیم، ممکن است کمی خسته کننده شود، پس چرا برخی از پیش فرض ها را در عملکرد خود اضافه نکنیم؟

گرد کردن ارزش های ما و اضافه کردن برخی از پیش فرض ها

بیایید با اضافه کردن یک تابع گرد کردن به فایل Sass خود شروع کنیم. این هر ورودی را می گیرد و آن را به مقدار مشخصی از اعشار گرد می کند:

@function round($number, $decimals: 0) {
    $n: 1;
    @if $decimals > 0 {
        @for $i from 1 through $decimals {
            $n: $n * 10;
        }
    }
    @return math.div(math.round($number * $n), $n);
}

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

@function fluid($min-size, $max-size, $min-breakpoint, $max-breakpoint, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: round($slope * 100, 2);
    $intercept-rem: round(px-to-rem($min-size - $slope * $min-breakpoint), 2);
    $min-size-rem: round(px-to-rem($min-size), 2);
    $max-size-rem: round(px-to-rem($max-size), 2);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

اکنون همان مثال قبلی نتیجه بسیار تمیزتری به ما می دهد.

ورودی:

font-size: #{fluid(16px, 31px, 320px, 960px)};

خروجی:

font-size: clamp(1rem, 2.34vw + 0.53rem, 1.94rem);

افزودن نقطه انفصال پیش فرض

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

$default-min-bp: 320px;
$default-max-bp: 960px;

@function fluid($min-size, $max-size, $min-breakpoint: $default-min-bp, $max-breakpoint: $default-max-bp, $unit: vw) {
    // ...
}

در حال حاضر، ما نیازی به تکرار این viewport ها همیشه نداریم. ما هنوز هم می توانیم یک نقطه شکست سفارشی اضافه کنیم اما یک ورودی ساده مانند:

font-size: #{fluid(16px, 31px)};

همچنان منجر به:

font-size: clamp(1rem, 2.34vw + 0.53rem, 1.94rem);

در اینجا تابع کامل است:

@use 'sass:math';

$default-min-bp: 320px;
$default-max-bp: 960px;

@function round($number, $decimals: 0) {
    $n: 1;
    @if $decimals > 0 {
        @for $i from 1 through $decimals {
            $n: $n * 10;
        }
    }
    @return math.div(math.round($number * $n), $n);
}

@function px-to-rem($px) {
    $rems: math.div($px, 16px) * 1rem;
    @return $rems;
}

@function fluid($min-size, $max-size, $min-breakpoint: $default-min-bp, $max-breakpoint: $default-max-bp, $unit: vw) {
    $slope: math.div($max-size - $min-size, $max-breakpoint - $min-breakpoint);
    $slope-to-unit: round($slope * 100, 2);
    $intercept-rem: round(px-to-rem($min-size - $slope * $min-breakpoint), 2);
    $min-size-rem: round(px-to-rem($min-size), 2);
    $max-size-rem: round(px-to-rem($max-size), 2);
    @return clamp(#{$min-size-rem}, #{$slope-to-unit}#{$unit} + #{$intercept-rem}, #{$max-size-rem});
}

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

اگر این آموزش کوچک را دنبال کردید و از آن شگفت زده شدید، ممکن است بخواهید این را اضافه کنید clamp() روش برای همه چیز است، اما یک نکته جانبی مهم در مورد دسترسی وجود دارد.

توجه داشته باشید: وقتی استفاده می کنید vw واحدها یا محدود کردن حجم متن clamp()، این احتمال وجود دارد که کاربر نتواند متن را تا 200٪ اندازه اصلی آن مقیاس کند.

اگر این اتفاق بیفتد، خرابی WCAG است. همانطور که آدریان بیس اشاره کرد، 100٪ بی خطا نیست. آدریان روزلی چند نمونه در این مورد نوشته است، که ممکن است برای شما جالب باشد.

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

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

Read More