Hướng dẫn build template sang angular 8

Lần trước mình đã có một bài hướng dẫn các bạn biến một file pts thành 1 giao diện web, hôm nay chúng ta sẽ bắt tay vào làm một trang web dự báo thời tiết mà hoàn toàn có thể đem ra sử dụng thật luôn, từ các bước thiết kế cho đến lập trình sử dụng Adobe XD, Angular 7 và Firebase.

Bước 1: Thiết kế

Bạn có thể down bản thiết kế tại đây để xem các layer xếp chồng lên nhau thế nào để tạo ra được bản thiết kế cuối cùng.

A. Thương hiệu

Hướng dẫn build template sang angular 8

Thương hiệu sẽ thể hiện được giá trị cốt lõi của nó thông qua bản thiết kế, và ở đây thể hiện sự tối giản, gọn gàng và dễ sử dụng.

  • Màu sắc 2 màu sắc cơ bản đã bão hòa đem lại sự tươi mới cho giao diện
  • Kiểu chữ Chỉ sử dụng đúng font 'Sans Serif' nên chúng ta không phải tải bất cứ font nào khác, giúp tăng hiệu suất
  • Logo

Hướng dẫn build template sang angular 8

Việc thiết kế logo nói dễ không dễ, nói khó cũng không hẳn, căn bản là phải phù hợp với mục đích của thương hiệu. Như logo của Nike, chỉ là một dấu chữ check, mất có 35$, trông khi logo của pepsi, cũng chỉ là 3 màu cơ bản xoay qua lại một chút, tốn 1.000.000$

Hướng dẫn build template sang angular 8
Còn đây là logo chúng ta sẽ dùng, chỉ là một chữ M đơn giản, sử dụng 2 hình tam giác giao nhau, vs 2 màu là 2 màu cơ bản của trang web, hiệu quả và chỉ tốn có 0 đồng.

B. UI/UX

Ứng dụng chủ yếu sử dụng các thẻ có đổ bóng giống như những mảnh giấy trôi nổi. Chỉ những thông tin quan trọng mới được hiển thị ở phía trước để tránh khiến giao diện lộn xộn và sử dụng các hành ảnh động để tăng điểm UX.

  • Light mode (Mặc định)

Hướng dẫn build template sang angular 8

Dark mode

Hướng dẫn build template sang angular 8

  • Icon Người dùng sẽ phải được thông báo về tình hình thời tiết trong nháy mắt, vì thế nên chúng ta sẽ sử dụng bộ icon sau cho cả trang web

Hướng dẫn build template sang angular 8

  • Tranh minh họa

Có một cách để người dùng có thể dễ dàng đoán ra địa điểm mà lại lấp đầy khoảng trống một cách cực kì trực quan, đấy là thêm một bức tranh minh họa địa điểm, họ sẽ chẳng cần phải đọc chữ, mà hình ảnh thì lúc nào cũng để lại ấn tượng hơn. Cùng nghía qua 1 số hình minh họa nhé!

  1. Tunisia

Hướng dẫn build template sang angular 8
2. Qatar

Hướng dẫn build template sang angular 8
3. Nhật bản

Hướng dẫn build template sang angular 8
4. Pháp

Hướng dẫn build template sang angular 8

Bước 2: Lập trình

Đã gọi là từ A tới Z thì phải bắt đầu từ người chưa biết gì, nên chúng ta sẽ bắt đầu từ việc install nodejs và angular CLI nhé. Ai biết rồi thì có thể bỏ qua đoạn này.

Install nodejs từ đây, sau đó mở console, install Angular CLI và typescript bằng câu lệnh sau

npm i -g typescript 
npm i -g @angular/cli

Sau đấy chạy dòng lệnh sau để generate app sử dụng Angular CLI và đừng quên thêm

ng new Minimus --routing

7 để về sau phân trang và thêm các đường dẫn.

ng new Minimus --routing

Sau khi đã generate và install xong các thứ cần thiết, chúng ta sẽ khởi động server bằng câu lệnh (thêm

ng new Minimus --routing

8 để tự động mở ứng dụng trên tab mới)

ng serve -o 

A. Template và style

Trước khi đọc tiếp, hãy đảm bảo bạn sẽ tận dụng tối đa bài hướng dẫn này, bằng cách ngưng việc copy + paste, hãy đọc code, mở phần mềm code và trình duyệt cạnh nhau, gõ lại theo cách của bạn, đó là cách duy nhất để bạn có thể hiểu từ đầu đến cuối.

Rồi, giờ thì quay trở lại project, nơi chúng ta đã hoàn thành các bước setup cơ bản, tiếp theo sẽ là viết HTML và CSS. Hãy mở phần mềm code yêu thích của bạn và bắt đầu nào!

  • App Component

Chúng ta sẽ sử dụng root component

ng new Minimus --routing

9 cho phần navbar component, sẽ làm cho nó ẩn hiện tùy vào việc người dùng có login hay không (sẽ nói đến trong part 2). Có một số thư viện Angular có thể hỗ trợ, nhưng để đảm bảo nó nhẹ nhất có thể, trong bài viết này sẽ không sử dụng đến.

Đầu tiên mở file

ng serve -o 

0, xóa toàn bộ đoạn HTML mặc định đi, và thêm đoạn HTML này vào:



Today

Light Dark
Copyright © 2018 Minimus

Thêm hàm này vào file

ng serve -o 

1 để đóng mở sidenav

toggleMenu() {
    this.showMenu = !this.showMenu;
 }

SVG icon

SVG icon và logo bạn có thể lấy ở đây (copy + paste)

  • hamburger icon
  • logo
  • icon thời tiết

Thêm style cho root component

Giờ là thời gian dành cho css, hãy xem nhanh đoạn css bên dưới và xem kết quả đạt được, sau đó tự viết css của bạn, vì mỗi người 1 quan niệm về cái đẹp =))

.root__container {
  width: 100vw;
  height: 100vh;
  display: grid;
  grid-template-columns: auto;
  grid-template-rows: 0.5fr auto;
  position: relative;
}
/*

Header
*/ /* Slide Menu
*/ .side-menu__container { position: fixed; left: 0; top: 0; width: 100%; height: 100%; overflow: hidden; pointer-events: none; z-index: 25; } .side-menu__container-active { pointer-events: auto; } .side-menu__container::before { content: ''; cursor: pointer; position: absolute; display: block; top: 0; left: 0; height: 100%; width: 100%; background-color: # 0c1066; opacity: 0; transition: opacity 300ms linear; will-change: opacity; } .side-menu__container-active::before { opacity: 0.3; } .slide-menu { box-sizing: border-box; transform: translateX(-103%); position: relative; top: 0; left: 0; z-index: 10; height: 100%; width: 90%; max-width: 26rem; background-color: white; box-shadow: 0 0 2rem rgba(0, 0, 255, 0.1); display: grid; grid-template-columns: 1fr; grid-template-rows: 2fr 4fr 1fr; grid-gap: 1rem; transition: transform 300ms linear; will-change: transform; } .slide-menu-active { transform: none; } .menu-header { background: linear-gradient(to right, # 00FF9B, # 5f84fb); display: grid; grid-template-rows: 1fr 4fr; grid-template-columns: 1fr 4fr; grid-template-areas: "greeting greeting" "image details"; box-sizing: border-box; width: 100%; align-content: center; color: white; box-shadow: 0 0.5rem 2rem rgba(0, 0, 255, 0.2); } .greeting__text { grid-area: greeting; font-size: 1.25rem; letter-spacing: 0.15rem; text-transform: uppercase; margin-top: 1rem; justify-self: center; align-self: center; } .account-details { grid-area: details; display: flex; flex-flow: column; margin-left: 1rem; align-self: center; } .name__text { font-size: 1.15rem; margin-bottom: 0.5rem; } .email__text { font-size: 0.9rem; letter-spacing: 0.1rem; } .menu-body { display: grid; width: 100%; } .profile-image__container { grid-area: image; margin-right: 0.5rem; border-radius: 50%; height: 4rem; width: 4rem; overflow: hidden; display: flex; justify-content: center; align-items: center; background-color: white; align-self: center; margin-left: 2rem; } .profile__image { max-width: 4rem; } /*Header*/ .main__header { width: 100%; display: grid; grid-template-columns: 1fr 1fr 0.25fr; grid-template-rows: 1fr; box-shadow: 0 0 2rem rgba(0, 0, 255, 0.1); height: 4rem; margin: 0; align-items: center; transition: background-color 500ms linear; animation: 1s ease-in-out 0ms 1 fadein; } .main__header-dark { background-color: # 2B244D; color: white; } .toggle-button__container { cursor: pointer; position: relative; margin: 0 0.5rem; } .mode-toggle__input { -webkit-appearance: none; -moz-appearance: none; } .mode-toggle__bg { height: 1rem; width: 2rem; border-radius: 0.5rem; background-color: rgba(0, 0, 0, 0.5); display: inline-block; transition: background-color 300ms linear; } .mode-toggle__circle { height: 1.30rem; width: 1.30rem; background-color: # 2B244D; position: absolute; top: -0.2rem; border-radius: 50%; box-shadow: 0 0 0 rgba(0, 0, 255, 0.5); transition: left 300ms linear; left: 0.1rem; } .mode-toggle__circle-checked { background-color: white; left: 1.75rem; } .mode-toggle__bg-checked { background-color: # FF0070; } .mode-toggle__text { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1rem; } /*Content*/ .left__section { display: grid; grid-template-rows: 1fr; grid-template-columns: 1fr 1fr; max-width: 5rem; } .date__text { text-transform: uppercase; letter-spacing: 0.1rem; display: inline; margin: 0.5rem 0; } /*SVGs*/ .hamburger__icon { position: relative; z-index: 35; height: 1rem; padding: 0.5rem 1.5rem; margin-right: 1rem; cursor: pointer; } .logo__icon { height: 2rem; margin-left: 1rem; } .logo__text { fill: # 2B244D; } .logo__text-dark { fill: # ffff; } .hamburger__icon__fill { fill: # 2B244D; } .hamburger__icon__fill-dark { fill: # ffff; } /*
Body
*/ .main-container__bg { height: 100%; width: 100%; position: absolute; top: 0; left: 0; z-index: -2; opacity: 0; background: white; transition: opacity 300ms linear; } .main-container__bg-dark { opacity: 1; background: linear-gradient(to bottom, # B290FF, # 2E1D65); transition: opacity 300ms linear; } /*
Footer
*/ .main__footer { background: transparent; position: absolute; bottom: 1rem; left: 1.5rem; z-index: 100; } .copyright__text { letter-spacing: 0.1rem; color: white; } @media only screen and (max-width: 300px) { .slide-menu { width: 100%; } }

Hoa mắt nhỉ, giờ giải thích cụ thể hơn đoạn CSS trên nhé

  • Bố cục

display: grid;  
grid-template-columns: auto;
grid-template-rows: 0.5fr auto;

Ở đây ta dùng CSS grid để chia bố cục, 1 phần nhỏ phía trên cho navbar, phần to phía dưới cho router outlet, cũng chính là nội dung của trang, giống như thế này:

Hướng dẫn build template sang angular 8

  • sidenav

.side-menu__conatiner {
    position: fixed; 
    left: 0;
    top: 0 
}

fix cứng vị trí của sidenav là trên cùng bên tay trái

.slide-menu { transform: translateX(-103%); }

translateX ở đây sẽ dịch chuyển

ng serve -o 

2 theo trục X 1 đoạn -103%, tức là giấu nó vào bên trái ý, sau đó ta thêm vào class

ng serve -o 

3

.slide-menu-active {  transform: none; }

để reset lại,

ng serve -o 

2 sẽ hiện thị ra luôn, ko bị giấu đi nữa.

Bố cục của chúng ta như thế này

Hướng dẫn build template sang angular 8

Demo

  • Nút chuyển đổi

Một mẹo nhỏ về UI là cách hiển thị nút chuyển đổi giữa 2 kiểu giao diện. Đầu tiên ta set

ng serve -o 

5 cho thuộc tính

ng serve -o 

6 để bỏ đi các css mặc định, sau đó sử dụng 2 class cho nền nút chuyển đổi và màu sắc, vị trí của hình tròn, ta dùng 1 biến boolean để lưu trữ kiểu giao diện hiện tại, chuyển đổi giữa 2 class bằng

ng serve -o 

7 đã được tích hợp sẵn trong Angular.

  • Home component Đây là component Home dùng để hiển thị các thẻ thời tiết của thành phố yêu thích của người dùng, từ đây anh ta cũng có thể nhấp vào thêm thành phố để thêm vào trang chủ của mình.

Đầu tiên chúng ta tạo component bằng lệnh sau:

ng new Minimus --routing

0

Trong component này chúng ta sẽ gọi đến và hiển thị 2 component là

ng serve -o 

8 và

ng serve -o 

9

ng new Minimus --routing

1

  • Weather card component

Ở đây ta dùng



Today

Light Dark
Copyright © 2018 Minimus

0 để chuyển giữa các kiểu thời tiết

ng new Minimus --routing

2

Thêm CSS

ng new Minimus --routing

3

Ta sẽ được demo thế này

Hướng dẫn build template sang angular 8

Chế độ ban đêm

Bạn có thể thấy có 1 số css thêm hậu tố



Today

Light Dark
Copyright © 2018 Minimus

1 là để dùng cho chế độ ban đêm, vẫn dùng

ng serve -o 

7 để chuyển đổi class. Ví dụ trong trường hợp này, khi chuyển sang chế độ ban đêm

Hướng dẫn build template sang angular 8

  • Add card component

Ở component add card thì ta cũng thêm

ng serve -o 

7 cho chế độ ban đêm, và thêm



Today

Light Dark
Copyright © 2018 Minimus

4 để điều hướng người dùng đến trang thêm thành phố khi click vào card đó

ng new Minimus --routing

4

Css về cơ bản cũng không khác quá nhiều, vì nó cần đồng bộ vs các card khác, vẫn sử dụng grid layout

ng new Minimus --routing

5

Kết quả

Hướng dẫn build template sang angular 8

  • Detail component

Đây là component để hiển thị chi tiết thời tiết 1 thành phố. Ta sử dụng



Today

Light Dark
Copyright © 2018 Minimus

5 để lấy dữ liệu thời tiết trong ngày hôm nay và 5 ngày tới, lưu vào các biến riêng để hiển thị ngoài màn hình

ng new Minimus --routing

6

Phần HTML của trang này có rất nhiều svgs nên rất là dài, vì thế sẽ không đề cập đến trong bài này, bạn có thể vào đây để xem full code nhé.

Bài dài quá rồi nên lần sau mình sẽ nói tiếp phần service và router nhé. :3

Nguồn: https://medium.com/@hamedbaatour/build-a-real-world-beautiful-web-app-with-angular-6-a-to-z-ultimate-guide-2018-part-i-e121dd1d55e