יצירת שעון עם פונקציות הטריגונומטריה החדשות של CSS sin() ו-cos().

יצירת שעון עם פונקציות הטריגונומטריה החדשות של CSS sin() ו-cos().

צומת המקור: 1999799

פונקציות טריגונומטריה של CSS נמצאות כאן! ובכן, הם כן אם אתה משתמש בגרסאות האחרונות של Firefox ו-Safari, כלומר. להיות בעל כוח מתמטי מסוג זה ב-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> תג עם 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, כדי לאחסן את המעגלים רַדִיוּס, השווה למחצית מרוחב המעגל. בדרך זו, אם הרוחב (--_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))));

הנוסחה של קואורדינטת 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;

אל האני זרוע שניות 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 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)))
  }
}

וכן, וואלה! השעון שלנו גמור! הנה ההדגמה הסופית פעם נוספת. שוב, זה נתמך רק בפיירפוקס ובספארי כרגע.

מה עוד נוכל לעשות?

רק מתעסק כאן, אבל אנחנו יכולים להפוך במהירות את השעון שלנו לגלריית תמונות עגולה על ידי החלפת ה- <time> תגים עם <img> ואז מעדכן את הרוחב (--_w) ורדיוס (--_r) ערכים:

בוא ננסה עוד אחד. הזכרתי קודם איך השעון נראה כמו ניסוי באמנות מודרנית. אנחנו יכולים להישען על זה וליצור מחדש דפוס שראיתי על פוסטר (שלצערי לא קניתי) בגלריה לאמנות שלשום. כזכור, הוא נקרא "ירח" והורכב מחבורה של נקודות היוצרות מעגל.

עיגול גדול נוצר מתוך חבורה של עיגולים מלאים קטנים יותר בצבעי אדמה שונים.

הפעם נשתמש ברשימה לא מסודרת מכיוון שהמעגלים אינם פועלים לפי סדר מסוים. אנחנו אפילו לא הולכים לשים את כל פריטי הרשימה בסימון. במקום זאת, בואו נזריק להם JavaScript ונוסיף כמה פקדים שבהם נוכל להשתמש כדי לתפעל את התוצאה הסופית.

הפקדים הם כניסות טווח (<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 מודרניות המספקות פתרונות חדשים לפתרונות ישנים. אני בטוח שנראה מקרי שימוש מעניינים, מורכבים ויצירתיים הרבה יותר, במיוחד כשתמיכה בדפדפן מגיעה לכרום ול-Edge.

בול זמן:

עוד מ טריקים של CSS