یک ساعت آنالوگ با استفاده از اجزای مستقل RxJS و Angular ایجاد کنید

معرفی
این روز 2 چالش جاوا اسکریپت 30 وس باس است که در آن یک ساعت آنالوگ ایجاد می کنم که زمان فعلی روز را نشان می دهد. در آموزش، من کامپوننت ها را با استفاده از RxJS، عملگرهای سفارشی، اجزای مستقل Angular ایجاد کردم و NgModules را حذف کردم.
در این پست وبلاگ، نحوه ایجاد یک قابل مشاهده را توضیح می دهم که عقربه های ساعت، دقیقه و ثانیه یک ساعت آنالوگ را ترسیم می کند. جزء ساعت یک تایمر ایجاد می کند که در هر ثانیه برای بدست آوردن زمان فعلی، زاویه چرخش عقربه ها را محاسبه می کند و سبک های CSS را برای انجام چرخش خط تنظیم می کند.
یک پروژه Angular جدید ایجاد کنید
ng generate application day2-ng-and-css-clock
کامپوننت برنامه بوت استرپ
اول تبدیل می کنم AppComponent
به کامپوننت مستقلی که بتوانم بوت استرپ کنم AppComponent
و ارائه دهندگان را در main.ts تزریق کنید.
// app.component.ts
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ClockComponent } from './clock';
@Component({
selector: 'app-root',
standalone: true,
imports: [
ClockComponent
],
template: '<app-clock></app-clock>',
styles: [`
:host {
display: block;
}
`],
})
export class AppComponent {
constructor(titleService: Title) {
titleService.setTitle('Day 2 NG and CSS Clock');
}
}
در Component decorator قرار دادم standalone: true
برای تبدیل AppComponent
به یک جزء مستقل
به جای واردات ClockComponent
در AppModule، من وارد می کنم ClockComponent
(این نیز یک جزء مستقل است) در آرایه واردات زیرا الگوی درون خطی به آن ارجاع می دهد.
// main.ts
import { enableProdMode } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
bootstrapApplication(AppComponent).catch(err => console.error(err));
دوم، من AppModule را حذف می کنم زیرا دیگر استفاده نمی شود.
جزء ساعت را اعلام کنید
من جزء مستقل را اعلام می کنم، ClockComponent
، برای ایجاد یک ساعت آنالوگ. برای تأیید اینکه مؤلفه مستقل است، standalone: true
در Decorator Component مشخص شده است.
src/app
├── app.component.ts
└── clock
├── clock.component.ts
├── clock.interface.ts
├── custom-operators
│ └── clock.operator.ts
└── index.ts
clock-operators.ts
دو عملگر سفارشی RxJS را در بر می گیرد که به رسم عقربه های ساعت ساعت آنالوگ کمک می کند. currentTime
اپراتور ثانیه ها، دقیقه ها و ساعت های زمان فعلی را برمی گرداند. rotateClockHands
نتایج currentTime را دریافت می کند و زاویه چرخش عقربه ها را محاسبه می کند.
// clock.component.ts
import { AsyncPipe, NgIf } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { timer } from 'rxjs';
import { currentTime, rotateClockHands } from './custom-operators/clock.operator';
@Component({
selector: 'app-clock',
standalone: true,
imports: [
AsyncPipe,
NgIf,
],
template: `
<div class="clock" *ngIf="clockHandsTransform$ | async as clockHandsTransform">
<div class="clock-face">
<div class="hand hour-hand" [style.transform]="clockHandsTransform.hourHandTransform"></div>
<div class="hand min-hand" [style.transform]="clockHandsTransform.minuteHandTransform"></div>
<div class="hand second-hand" [style.transform]="clockHandsTransform.secondHandTransform"></div>
</div>
</div>
`,
styles: [...omitted due to brevity...],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ClockComponent {
readonly oneSecond = 1000;
clockHandsTransform$ = timer(0, this.oneSecond)
.pipe(
currentTime(),
rotateClockHands(),
);
}
ClockComponent
واردات NgIf
و AsyncPipe
زیرا اجزاء استفاده می کند ngIf
و async
کلمات کلیدی برای حل clockHandsTransform$
قابل مشاهده clockHandsTransform$
یک قابل مشاهده است که از سبک های CSS برای رسم عقربه های ساعت، دقیقه و ثانیه تشکیل شده است. قابل مشاهده موجز است زیرا currentTime
و rotateClockHands
عملگرهای سفارشی منطق را کپسوله می کنند.
اپراتورهای سفارشی RxJS را ایجاد کنید
این یک موضوع سلیقه ای است، اما من ترجیح می دهم عملگرهای RxJS را به عملگرهای سفارشی تبدیل کنم، زمانی که مشاهدات دارای خطوط کد زیادی هستند. برای clockHandsTransform$
، من نقشه را در عملگرهای سفارشی تغییر می دهم و از آنها مجدداً در آن استفاده می کنم ClockComponent
.
// clock.operator.ts
export function currentTime() {
return map(() => {
const time = new Date();
return {
seconds: time.getSeconds(),
minutes: time.getMinutes(),
hours: time.getHours()
}
});
}
currentTime
اپراتور زمان جاری را دریافت می کند و متدهای شی Date را برای برگرداندن ثانیه، دقیقه و ساعت فعلی فراخوانی می کند.
// clock.operator.ts
function rotateAngle (seconds: number, minutes: number, hours: number): HandTransformations {
const secondsDegrees = ((seconds / 60) * 360) + 90;
const minsDegrees = ((minutes / 60) * 360) + ((seconds / 60) * 6) + 90;
const hourDegrees = ((hours / 12) * 360) + ((minutes / 60) * 30) + 90;
return {
secondHandTransform: `rotate(${secondsDegrees}deg)`,
minuteHandTransform: `rotate(${minsDegrees}deg)`,
hourHandTransform: `rotate(${hourDegrees}deg)`,
}
}
export function rotateClockHands() {
return function (source: Observable<{ seconds: number, minutes: number, hours: number }>) {
return source.pipe(map(({ seconds, minutes, hours }) => rotateAngle(seconds, minutes, hours)));
}
}
currentTime
نتایج را منتشر می کند rotateClockHands
و rotateClockHands
اپراتور یک تابع کمکی را فراخوانی می کند، rotateAngle
، برای استخراج سبک های CSS دست ها.
در نهایت، من از هر دو عملگر برای نوشتن clockHandsTransform$ observable استفاده می کنم.
از RxJS و Angular برای پیاده سازی قابل مشاهده در جزء ساعت استفاده کنید
// clock.component.ts
clockHandsTransform$ = timer(0, this.oneSecond)
.pipe(
currentTime(),
rotateClockHands(),
);
- تایمر (0، this.oneSecond) – هر ثانیه یک عدد صحیح منتشر می کند
- CurrentTime() – ثانیه، دقیقه و ساعت فعلی را برمی گرداند
- rotateClockHands() – زاویه چرخش عقربه های ثانیه، دقیقه و ساعت را محاسبه کنید
این همان است، ما یک ساعت آنالوگ کاربردی ایجاد کرده ایم که زمان فعلی را نمایش می دهد.
افکار نهایی
در این پست، نحوه استفاده از اجزای مستقل RxJS و Angular برای ایجاد ساعت آنالوگ را نشان میدهم. این برنامه پس از استفاده از ویژگی های جدید Angular 15 دارای ویژگی های زیر است:
- برنامه NgModules و کدهای سازنده دیگ بخار ندارد.
- در ClockComponent، من NgIf و AsyncPipe را به جای CommonModule وارد میکنم، فقط حداقل قطعاتی را که کامپوننت نیاز دارد.
این پایان پست وبلاگ است و امیدوارم از مطالب خوشتان بیاید و تجربه یادگیری من در Angular و سایر فناوری ها را دنبال کنید.
منابع: