ایجاد یک ساعت با توابع مثلثاتی () CSS () و cos

ایجاد یک ساعت با توابع مثلثاتی () CSS () و cos

گره منبع: 1999799

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

توابع مثلثاتی دیگری در خط لوله وجود دارد - از جمله tan() - پس چرا فقط روی آن تمرکز کنید sin() و cos()? آنها برای ایده ای که من در ذهن دارم، یعنی قرار دادن متن در امتداد لبه یک دایره، عالی هستند. که در اینجا در CSS-Tricks پوشش داده شده است کریس رویکردی را به اشتراک گذاشت که از یک میکس Sass استفاده می کند. این شش سال پیش بود، پس بیایید درمان لبه خونریزی را به آن بدهیم.

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

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

<div class="clock"> <div class="clock-face"> <time datetime="12:00">12</time> <time datetime="1:00">1</time> <time datetime="2:00">2</time> <time datetime="3:00">3</time> <time datetime="4:00">4</time> <time datetime="5:00">5</time> <time datetime="6:00">6</time> <time datetime="7:00">7</time> <time datetime="8:00">8</time> <time datetime="9:00">9</time> <time datetime="10:00">10</time> <time datetime="11:00">11</time> </div>
</div>

در مرحله بعد، در اینجا چند سبک فوق العاده اساسی برای .clock-face ظرف تصمیم گرفتم از <time> برچسب با a datetime ویژگی. 

.clock { --_ow: clamp(5rem, 60vw, 40rem); --_w: 88cqi; aspect-ratio: 1; background-color: tomato; border-radius: 50%; container-type: inline; display: grid; height: var(--_ow); place-content: center; position: relative; width var(--_ow);
}

من چیزها را کمی در آنجا تزئین کردم، اما فقط برای اینکه شکل اولیه و رنگ پس زمینه را به دست بیاورم تا به ما کمک کند ببینیم چه کار می کنیم. توجه کنید که چگونه ما را ذخیره می کنیم width ارزش در a متغیر CSS. بعداً از آن استفاده خواهیم کرد. تا اینجا چیز زیادی برای نگاه کردن نیست:

دایره رنگی گوجه فرنگی بزرگ با لیست عمودی اعداد 1-12 در سمت چپ.

به نظر نوعی آزمایش هنر مدرن است، درست است؟ بیایید یک متغیر جدید معرفی کنیم، --_r، برای ذخیره دایره شعاع، که برابر با نیمی از عرض دایره است. به این ترتیب، اگر عرض (--_w) تغییر می کند، مقدار شعاع (--_r) نیز به روز می شود - به لطف یکی دیگر از تابع های ریاضی CSS، calc():

.clock { --_w: 300px; --_r: calc(var(--_w) / 2); /* rest of styles */
}

حالا کمی ریاضی. دایره 360 درجه است. ما 12 برچسب روی ساعت خود داریم، بنابراین می خواهیم اعداد را هر 30 درجه قرار دهیم (360 / 12). در سرزمین ریاضی، یک دایره از ساعت 3 شروع می شود، بنابراین در واقع ظهر است منفی 90 درجه از آن، که 270 درجه است (360 - 90).

بیایید یک متغیر دیگر اضافه کنیم، --_d، که می توانیم از آن برای تنظیم a استفاده کنیم درجه مقدار برای هر عدد در صفحه ساعت. برای تکمیل دایره خود، مقادیر را 30 درجه افزایش می دهیم:

.clock time:nth-child(1) { --_d: 270deg; }
.clock time:nth-child(2) { --_d: 300deg; }
.clock time:nth-child(3) { --_d: 330deg; }
.clock time:nth-child(4) { --_d: 0deg; }
.clock time:nth-child(5) { --_d: 30deg; }
.clock time:nth-child(6) { --_d: 60deg; }
.clock time:nth-child(7) { --_d: 90deg; }
.clock time:nth-child(8) { --_d: 120deg; }
.clock time:nth-child(9) { --_d: 150deg; }
.clock time:nth-child(10) { --_d: 180deg; }
.clock time:nth-child(11) { --_d: 210deg; }
.clock time:nth-child(12) { --_d: 240deg; }

خوب، اکنون زمان آن است که دستمان را با آن کثیف کنیم sin() و cos() کارکرد! کاری که می‌خواهیم انجام دهیم این است که از آنها برای بدست آوردن مختصات X و Y برای هر عدد استفاده کنیم تا بتوانیم آنها را به درستی در سراسر ساعت قرار دهیم.

فرمول مختصات X است radius + (radius * cos(degree)). بیایید آن را به جدید خود متصل کنیم --_x متغیر:

--_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));

فرمول مختصات Y است radius + (radius * sin(degree)). ما آنچه را که برای محاسبه نیاز داریم داریم:

--_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));

چند کار خانه داری وجود دارد که برای تنظیم اعداد باید انجام دهیم، بنابراین بیایید یک استایل اولیه روی آنها بگذاریم تا مطمئن شویم که کاملاً در موقعیت و با مختصات ما قرار می گیرند:

.clock-face time { --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d)))); --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d)))); --_sz: 12cqi; display: grid; height: var(--_sz); left: var(--_x); place-content: center; position: absolute; top: var(--_y); width: var(--_sz);
}

اطلاع --_sz، که ما از آن استفاده خواهیم کرد width و height از اعداد در یک لحظه ببینیم تا الان چی داریم

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

این قطعا بیشتر شبیه یک ساعت است! ببینید گوشه سمت چپ بالای هر عدد چگونه در محل درست اطراف دایره قرار گرفته است؟ هنگام محاسبه موقعیت برای هر عدد باید شعاع را "کوچک" کنیم. ما میتوانیم کسر کردن اندازه یک عدد (--_sz) از اندازه دایره (--_wقبل از اینکه شعاع را محاسبه کنیم:

--_r: calc((var(--_w) - var(--_sz)) / 2);
دایره بزرگ رنگی گوجه فرنگی با برچسب ساعت در امتداد لبه گرد آن.

خیلی بهتر! بیایید رنگ ها را تغییر دهیم تا زیباتر به نظر برسد:

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

می توانستیم همین جا توقف کنیم! ما به هدف قرار دادن متن در اطراف یک دایره دست یافتیم، درست است؟ اما یک ساعت بدون بازو برای نشان دادن ساعت، دقیقه و ثانیه چیست؟

بیایید از یک انیمیشن CSS برای آن استفاده کنیم. ابتدا، اجازه دهید سه عنصر دیگر را به نشانه گذاری خود اضافه کنیم،

<div class="clock"> <!-- after <time>-tags --> <span class="arm seconds"></span> <span class="arm minutes"></span> <span class="arm hours"></span> <span class="arm center"></span>
</div>

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

.arm { background-color: var(--_abg); border-radius: calc(var(--_aw) * 2); display: block; height: var(--_ah); left: calc((var(--_w) - var(--_aw)) / 2); position: absolute; top: calc((var(--_w) / 2) - var(--_ah)); transform: rotate(0deg); transform-origin: bottom; width: var(--_aw);
}

ما از همان انیمیشن برای هر سه بازو:

@keyframes turn { to { transform: rotate(1turn); }
}

تنها تفاوت زمانی است که تک تک بازوها برای چرخش کامل صرف می کنند. برای ساعت بازو، طول می کشد ساعت 12 برای انجام یک چرخش کامل این animation-duration ویژگی فقط مقادیر بر حسب میلی ثانیه و ثانیه را می پذیرد. بیایید به ثانیه ها بمانیم که 43,200 ثانیه است (60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

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

animation: turn 3600s steps(60, end) infinite;

La بازوی ثانیه is تقریبا همان به عنوان بازوی دقیقه، اما مدت زمان به جای 60 دقیقه 60 ثانیه است:

animation: turn 60s steps(60, end) infinite;

بیایید ویژگی هایی را که در سبک های رایج ایجاد کرده ایم به روز کنیم:

.seconds { --_abg: hsl(0, 5%, 40%); --_ah: 145px; --_aw: 2px; animation: turn 60s steps(60, end) infinite;
}
.minutes { --_abg: #333; --_ah: 145px; --_aw: 6px; animation: turn 3600s steps(60, end) infinite;
}
.hours { --_abg: #333; --_ah: 110px; --_aw: 6px; animation: turn 43200s linear infinite;
}

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

const time = new Date();
const hour = -3600 * (time.getHours() % 12);
const mins = -60 * time.getMinutes();
app.style.setProperty('--_dm', `${mins}s`);
app.style.setProperty('--_dh', `${(hour+mins)}s`);

من اضافه کرده ام id="app" به صفحه ساعت و دو ویژگی سفارشی جدید روی آن تنظیم کنید که یک منفی تنظیم می کند animation-delayهمانطور که میت مارشالکو انجام داد زمانی که او یک ساعت فقط CSS را به اشتراک گذاشت.  getHours() روش جاوا اسکپت Date شی از فرمت 24 ساعته استفاده می کند، بنابراین ما از آن استفاده می کنیم remainder اپراتور برای تبدیل آن به فرمت 12 ساعته.

در CSS، باید آن را اضافه کنیم animation-delay همچنین:

.minutes { animation-delay: var(--_dm, 0s); /* other styles */
} .hours { animation-delay: var(--_dh, 0s); /* other styles */
}

فقط یه چیز دیگه. استفاده از CSS @supports و ویژگی‌هایی که قبلاً ایجاد کرده‌ایم، می‌توانیم به مرورگرهایی که پشتیبانی نمی‌کنند، بازگشتی ارائه کنیم sin() و cos(). (متشکرم، تمانی عفیف!):

@supports not (left: calc(1px * cos(45deg))) {
  time {
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%,-50%) rotate(var(--_d)) translate(var(--_r)) rotate(calc(-1*var(--_d)))
  }
}

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

دیگر چه کاری می توانیم انجام دهیم؟

فقط اینجا را به هم می زند، اما ما می توانیم به سرعت با جایگزین کردن ساعت خود را به یک گالری تصاویر دایره ای تبدیل کنیم <time> برچسب ها با <img> سپس عرض را به روز کنید (--_w) و شعاع (--_r) ارزش های:

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

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

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

کنترل ها ورودی های محدوده هستند (<input type="range">) که در آن می پیچیم <form> و برای گوش دادن به input رویداد.

<form id="controls"> <fieldset> <label>Number of rings <input type="range" min="2" max="12" value="10" id="rings" /> </label> <label>Dots per ring <input type="range" min="5" max="12" value="7" id="dots" /> </label> <label>Spread <input type="range" min="10" max="40" value="40" id="spread" /> </label> </fieldset>
</form>

ما این روش را روی "input" اجرا خواهیم کرد، که یک دسته از آن ایجاد می کند <li> عناصر با درجه (--_d) متغیری که قبلا استفاده کردیم برای هر کدام اعمال شد. ما همچنین می توانیم متغیر شعاع خود را تغییر کاربری دهیم (--_r).

من همچنین می خواهم نقطه ها رنگ های مختلف داشته باشند. بنابراین، بیایید تصادفی کنیم (خب، نه به طور کامل تصادفی) مقدار رنگ HSL برای هر آیتم لیست و ذخیره آن به عنوان یک متغیر CSS جدید، --_bgc:

const update = () => { let s = ""; for (let i = 1; i <= rings.valueAsNumber; i++) { const r = spread.valueAsNumber * i; const theta = coords(dots.valueAsNumber * i); for (let j = 0; j < theta.length; j++) { s += `<li style="--_d:${theta[j]};--_r:${r}px;--_bgc:hsl(${random( 50, 25 )},${random(90, 50)}%,${random(90, 60)}%)"></li>`; } } app.innerHTML = s;
}

La random() متد یک مقدار را در محدوده مشخصی از اعداد انتخاب می کند:

const random = (max, min = 0, f = true) => f ? Math.floor(Math.random() * (max - min) + min) : Math.random() * max;

و بس. ما از جاوا اسکریپت برای رندر نشانه گذاری استفاده می کنیم، اما به محض رندر شدن، واقعاً به آن نیاز نداریم. این sin() و cos() توابع به ما کمک می کنند همه نقاط را در نقاط درست قرار دهیم.

افکار نهایی

قرار دادن اشیا در اطراف یک دایره یک مثال بسیار ابتدایی برای نشان دادن قدرت توابع مثلثاتی است sin() و cos(). اما این واقعا جالب است که ما در حال دریافت ویژگی های مدرن CSS هستیم که راه حل های جدیدی برای راه حل های قدیمی ارائه می دهد.

تمبر زمان:

بیشتر از ترفندهای CSS