إنشاء ساعة باستخدام وظائف علم المثلثات الجديدة CSS sin () و cos ()

إنشاء ساعة باستخدام وظائف علم المثلثات الجديدة CSS sin () و cos ()

عقدة المصدر: 1999799

وظائف علم المثلثات CSS هنا! حسنًا ، هذا هو الحال إذا كنت تستخدم أحدث إصدارات Firefox و Safari. إن امتلاك هذا النوع من القوة الرياضية في CSS يفتح مجموعة كاملة من الاحتمالات. في هذا البرنامج التعليمي ، اعتقدت أننا سنغمس أصابع قدمنا ​​في الماء لنتعرف على وظيفتين جديدتين: sin() و cos().

هناك وظائف أخرى في علم المثلثات في خط الأنابيب - بما في ذلك tan() - فلماذا التركيز فقط على sin() و cos()؟ تصادف أنها مثالية للفكرة التي تدور في ذهني ، وهي وضع نص على طول حافة الدائرة. تمت تغطية ذلك هنا في CSS-Tricks عندما شارك كريس نهجًا يستخدم Sass mixin. كان ذلك قبل ست سنوات ، لذلك دعونا نعطيها علاج حافة النزيف.

هذا ما يدور في خلدي. مرة أخرى ، يتم دعمه فقط في Firefox و Safari في الوقت الحالي:

لذلك ، فهي ليست تمامًا مثل الكلمات التي تشكل شكلًا دائريًا ، لكننا نضع أحرفًا نصية على طول الدائرة لتشكيل وجه الساعة. إليك بعض الترميز الذي يمكننا استخدامه لبدء الأمور:

<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> علامة ب 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 قيمة في متغير CSS. سنستخدم ذلك لاحقًا. ليس هناك الكثير للنظر إليه حتى الآن:

دائرة كبيرة ملونة بالطماطم مع قائمة عمودية من الأرقام 1-12 على اليسار.

يبدو وكأنه نوع من تجربة الفن الحديث ، أليس كذلك؟ دعنا نقدم متغير جديد ، --_rلتخزين الدوائر radiusوالتي تساوي نصف عرض الدائرة. بهذه الطريقة ، إذا كان العرض (--_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، التي يمكننا استخدامها لتعيين ملف الدرجة العلمية قيمة لكل رقم على وجه الساعة. سنزيد القيم بمقدار 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))));

صيغة الإحداثي ص هي 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;

ثواني الذراع 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;
}

ماذا لو أردنا أن نبدأ في الوقت الحالي؟ نحتاج إلى القليل من JavaScript:

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() طريقة JavaScipt's 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)))
  }
}

و فويلا! لقد انتهت ساعتنا! ها هو العرض النهائي مرة أخرى. مرة أخرى ، يتم دعمه فقط في Firefox و Safari في الوقت الحالي.

ماذا يمكن ان نفعل ايضا؟

مجرد العبث هنا ، ولكن يمكننا تحويل ساعتنا بسرعة إلى معرض صور دائري عن طريق استبدال <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>

سنقوم بتشغيل هذه الطريقة على "الإدخال" ، والتي ستنشئ مجموعة من <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;
}

random() طريقة اختيار قيمة ضمن نطاق محدد من الأرقام:

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

وهذا كل شيء. نستخدم JavaScript لتقديم الترميز ، ولكن بمجرد تقديمه ، لا نحتاج إليه حقًا. ال sin() و cos() الوظائف تساعدنا في وضع كل النقاط في الأماكن الصحيحة.

الأفكار النهائية

يعد وضع الأشياء حول دائرة مثالًا أساسيًا جدًا لإثبات قوى علم المثلثات مثل sin() و cos(). ولكنها في الحقيقة رائع أننا نحصل على ميزات CSS الحديثة التي توفر حلولًا جديدة للحلول القديمة ، أنا متأكد من أننا سنرى حالات استخدام أكثر تشويقًا وتعقيدًا وإبداعًا ، خاصة وأن دعم المتصفح يأتي إلى Chrome و Edge.

الطابع الزمني:

اكثر من الخدع المغلق