בניית רכיב הזזה של תמונות באמצעות זוויתי

1. מבוא

מאת האורח/ת אייוש ארורה

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

בשיעור Lab הזה תלמדו איך ליצור רכיב זוויתי הזזה משלכם כדי לעזור לכם להפוך אותו לרכיב זוויתי כך שיוכל לעבוד מחוץ למסגרת הזוויתית.

מה תפתחו

במעבדה זו תוכלו לבנות רכיב של פס הזזה עם זווית. הרכיב שלך wi:

  • פועלים כמו רכיב HTML בדפדפן
  • יכולים להתחבר לכל מסגרת שמדברת עם ה-DOM.

מה תלמדו

  • איך יוצרים רכיב מותאם אישית של פס ההזזה של התמונה
  • איך משנים את רכיב ההתאמה האישית של פס ההזזה לרכיב מותאם אישית
  • איך לארוז את הרכיב כך שהוא יפעל בתוך הדפדפן

מה צריך?

שיעור Lab זה מתמקד ברכיבים זוויתיים. קונספטים ובלוקים של קוד שאינם רלוונטיים יותר מובלטים, והם ניתנים כדי פשוט להעתיק ולהדביק אותם.

2. תהליך ההגדרה

להורדת הקוד

כדי להוריד את כל הקוד של Lablab זה, צריך ללחוץ על הקישור הבא:

פותחים את הקובץ הדחוס. הפעולה הזו תשחרר תיקיית שורש (angular-element-codelab-master), שכוללת

שתי תיקיות (image-slider) ו-(image-slider-finished). אנחנו נעשה את כל עבודת הקידוד שלנו בספרייה שנקראת 'פס הזזה של תמונות'.

הפעלת הפרויקט

כדי להריץ את הפרויקט, עליך להריץ את הפקודה ( ng-ng- ) מספריית הבסיס ( image-slider ).

אחרי שהאפליקציה תופעל ללא התקנה, תהיה לך אפשרות לראות את הפרטים הבאים:

19ffd082e2f024a5.png

3. יוצרים רכיב מותאם אישית של פס ההזזה של התמונה?

איך יוצרים מחוון תמונות?

עבור מחוון תמונה זה, איגוד לחצנים באמצעות קישור קליקים זוויתי. אנחנו ניצור מערך של אובייקטים שמכילים תמונות, תגי Alt, קישורים וכו'. מציבים את התמונות האלה אחת אחרי השנייה במכל ומתרגמים את המאגר בזמן הקליק.

אנחנו ניצור רכיב של פס הזזה של תמונות ואז נהפוך אותו לאלמנט זוויתי.

  • מאגר לתמונות ולכותרות.
  • מערך המכיל את הנתונים
  • תבנית שמחייבת את הנתונים

4. הטמעה של רכיב פס ההזזה של התמונה

יש דרכים רבות להתחיל לעבוד על כל פרויקט, במקרה הזה, כדי שהפרויקט שלנו יהיה פשוט ככל האפשר ולהתמקד ברכיבים זוויתיים, סיפקנו לך קוד בסיסי יחד עם שירות ה-CSS.

יצירת מערך ושירות נתונים

חשוב לזכור, ה-מחווןArray יכיל:

  • מפתח img לכתובת ה-URL של התמונה בפס ההזזה
  • תג חלופי שיספק Alt לתמונה
  • טקסט שיספק תיאור של התמונה

הקובץ data.json שכבר נמצא בספרייה שלך ב-src/assets אמור להיראות בערך כך.

sliderArray = [
 {img: 'http://bloquo.cc/img/works/1.jpg', alt: '', text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/2.jpg', alt: '',  text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/3.jpg', alt: '', text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/4.jpg', alt: '',  text: '365 Days Of weddings a year'},
 {img: 'http://bloquo.cc/img/works/5.jpg', alt: '', text: '365 Days Of weddings a year'}
];

עלינו לאחזר את הנתונים האלה ברכיב שלנו באמצעות שירות. בקובץ data.service.ts אנחנו נכתוב שיטה של getData() באמצעות המודול httpClient מהאתר @angular/common/http, שיאחזר את הנתונים מהמערך שיצרנו למעלה.

 
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'

const URL = '../assets/data.json';

@Injectable({
 providedIn: 'root'
})
export class DataService {

 constructor(private http: HttpClient) {}

 getData() {
   return this.http.get(URL)
 }
}

אחזור הנתונים משירות הנתונים

אנחנו צריכים לייבא את השירות שלנו מהרכיב ולאחר מכן להירשם כמנוי לשירות כדי לקבל את האובייקט מ-data.json

לשם כך עלינו לבצע שלושה שלבים:

  • אתחול של מערך רכיבים
  • הרשמה לפונקציה 'גלוי' שהוחזרה על ידי 'getData()'
  • יצירת ממשק לבדיקה כדי לבדוק את הנתונים אחרי שנרשמים לאירוע.
  • הקצאה של הנתונים למערך הרכיבים.

אתחול רכיב רכיב

נכריז ונפעיל את מערך הרכיבים שבתוך slider.component.ts שהוא מערך אובייקטים:

כדי להצהיר:

sliderArray: object[];

כדי לאתחל:

constructor(private data: DataService) {
 this.sliderArray = [];
}

בשלב הבא עלינו לייבא ולהפעיל את השירות שלנו בתוך ה-constructor

constructor(private data: DataService) {}

עכשיו אנחנו מוכנים להשתמש בשירות שלנו ולהתקשר לשיטות השירות שלנו.

קבלת נתונים משירות נתונים

כדי להפיק את הנתונים מהשירות, נתקשר למספר getData() ונרשום אותו כפי שהוא ידווח. בנוסף, ניצור ממשק Result, כדי שנוכל לוודא שאנחנו מקבלים את הנתונים הנכונים.

לשם כך נעשה שימוש בשיטה ngOnInit:

this.data.getData().subscribe((result: Result)=>{
})

הקצאת נתונים למערך רכיבים

בסופו נקצה את הנתונים למערך הרכיבים:

this.data.getData().subscribe((result: Result)=>{  
  this.sliderArray = result.sliderArray;
})

לאחר שאנחנו מקבלים את הנתונים בתוך מערך הרכיבים שלנו, אנחנו יכולים לחייב את התבנית שלנו לנתונים אלה.

בslider.component.html, יש לנו כבר תבנית HTML. השלב הבא הוא לחייב את התבנית הזו לבצע את sliderArray.

5. קישור הנתונים לתבנית

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

יש שלושה שלבים:

  • הכפפה sliderArray לתבנית
  • מתבצעת הוספה של איגוד אירועים ללחצנים של פס ההזזה
  • הוספת טרנספורמציות של CSS באמצעות ngStyle ו-ngClass

איגוד SlidesArray לרכיב

יש לנו מאגר תגים img-container, a text-container ו-a slider.

אנחנו מחייבים את הנתונים בכל שלושת מאגרי התגים באמצעות ההוראה *ngFor

<div class="container">
 <div class="img-container" *ngFor="let i of sliderArray; let select = index;">
   <img src="{{i.img}}" alt="{{i.alt}}" >
 </div>

 <div>
   <div class="text-container">
     <div class="page-text" *ngFor="let i of sliderArray;let select = index;">
       <h3>{{i.text}}</h3>
     </div>
   </div>
 </div>

</div>

<div class="slider">
 <div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index">
    <div class="select-box">
     <div class="slide-button">
     </div>
    </div>
 </div>
</div>

קישור אירוע אל SlidesArray

לאחר שהנתונים יכובדו, נחייב את אירוע הקליק לכל לחצן שקף באמצעות click binding הזוויתי. אנחנו יוצרים פונקציה בשם selected(x)כאשר X הוא האינדקס של המערך.

selected(x) {
 this.downSelected(x);
 this.selectedIndex = x;
}

downSelected(i) {
  this.transform =  100 - (i) * 50;
  this.selectedIndex = this.selectedIndex + 1;
  if(this.selectedIndex > 4) {
    this.selectedIndex = 0;
  }
}

נקודות שכדאי לזכור:

  • הפונקציה שנבחרה נמוכה יותר מקטינה את ערך הטרנספורמציה של המאה ה-50 באינדקס של הקליק על הפונקציה selected.
  • הלוגיקה הזו מתרגמת את מאגר הטקסט ל-100%, 50%, -50%, -100% וכתוצאה מכך ארבעה מצבים שונים.

הוספת טרנספורמציות של CSS באמצעות ngstyle & ngClass

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

<div class="img-container"  *ngFor="let i of sliderArray; let select = index;"
      [ngClass]="{'selected': select == selectedIndex}">
</div>

לאחר מכן, נתרגם את מאגר התגים בהתאם לערך transform שמחושב באמצעות הפונקציה select().

<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>

לאחר שתבצעו את כל השלבים האלה, תוכלו למצוא את הקוד הסופי כפי שמפורט בהמשך:

<div class="container">
 <div class="img-container"  *ngFor="let i of sliderArray; let select = index;"
      [ngClass]="{'selected': select == selectedIndex}">
   <img src="{{i.img}}" alt="{{i.alt}}" >
 </div>

 <!--</div>-->
 <div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
   <div class="text-container">
     <div class="page-text" *ngFor="let i of sliderArray;let select = index;" [ngClass]="{'selected': select == selectedIndex}">
       <h3>{{i.text}}</h3>
     </div>
   </div>
 </div>

</div>

<div class="slider">
 <div class="slide-button-parent-container"  *ngFor="let i of sliderArray; let x =index" (click)="selected(x)" >
    <div class="select-box">
     <div   class="slide-button" [ngClass]="{'slide-button-select': x == selectedIndex}" >
     </div>
    </div>
 </div>
</div>

6. הפיכת הרכיב לאלמנט הזוויתי

תהליך זה כולל חמישה שלבים:

  • שימוש ב-Shadow DOM לרכיב זוויתי
  • שימוש ב-entryComponents
  • מתבצע ייבוא של מודול CreateCustomElement מ-@angular/elements ושימוש בו
  • הגדרת custom-element
  • מתבצעת הפעלה של שיטת ngDoBootstrap

שימוש ב-DOM Shadow לרכיב זוויתי

עכשיו צריך להפעיל את פס ההזזה של התמונות. עכשיו צריך פשוט להגדיר אותו Angular Element.

החלק המלהיב הוא שיש רק שינוי קטן ביצירת ה-DOM, הרכיב DOM.

עלינו לייבא את המודול ViewEncapsulation ולהשתמש בו בשיטה ShadowDom.

@Component({
 selector: 'app-slider',
 templateUrl: './slider.component.html',
 styleUrls: ['./slider.component.css'],
 encapsulation: ViewEncapsulation.ShadowDom
})

שימוש ברכיבי כניסה

רכיב הרשומה הוא רכיב שנטען בצורה זוויתית באופן רציף. אפשר לציין רכיב כניסה על ידי הפעלת אתחול ב-Ngmodule.

כאן נציין את SliderComponent במערך entryComponents בתוך @NgModule

@NgModule({
 declarations: [
   SliderComponent
 ],
 imports: [
   BrowserModule,
   HttpClientModule
 ],
 entryComponents: [SliderComponent],
})

ייבוא מודול 'createCustomElement' ושימוש בו

כאן, אנחנו צריכים להשתמש במודול createCustomElement של @angular/elements.. עליך להשתמש ב-SliderComponent, כפרמטר לפונקציה createCustomElement. לאחר מכן עלינו לרשום את ה-slider ב-DOM.

import { createCustomElement } from '@angular/elements';

export class AppModule {
 constructor(private injector: Injector) {
   const slider = createCustomElement(SliderComponent, { injector });
    }
}

כדי לרשום את פס ההזזה כרכיב DOM, אנחנו נגדיר אותו באמצעות השיטה customElements.define.

customElements.define('motley-slider', slider);

לבסוף, אנחנו צריכים להעלות את הרכיב המותאם אישית הזה באמצעות השיטה ngDoBootstrap(). הקוד המלא ייראה כך:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SliderComponent } from './slider/slider.component';
import { HttpClientModule} from "@angular/common/http";

@NgModule({
 declarations: [
   SliderComponent
 ],
 imports: [
   BrowserModule,
   HttpClientModule
 ],
 entryComponents: [SliderComponent],
})
export class AppModule {
 constructor(private injector: Injector) {
   const slider = createCustomElement(SliderComponent, { injector });
   customElements.define('motley-slider', slider);
 }

 ngDoBootstrap() {}

}

אריזת הרכיב הזוויתי

עלינו לשנות את package.json בפקודות החדשות שלנו, אנחנו נשנה את האובייקט של הסקריפט בקובץ package.json.

בואו ונבדוק את אובייקט הסקריפט המעודכן:

"scripts": {
 "ng": "ng",
 "start": "ng serve",
 "build": "ng build --prod --output-hashing=none",
 "package": "cat dist/my-app/{runtime,polyfills,scripts,main}.js | gzip > elements.js.gz",
 "serve": "http-server",
 "test": "ng test",
 "lint": "ng lint",
 "e2e": "ng e2e"
}

עכשיו נוכל להריץ את הפקודה ng build & ng package ולבסוף נפעיל ng כדי להציג את התפוצה/התיקייה שנוצרה באמצעות פקודת build. בנוסף, אנחנו יכולים להשתמש ב-gzip שמתקבל מהפקודה ng package, לחלץ אותו ולפרסם אותו כnpm module.