Kết hợp Web và Ứng dụng gốc với 4 API JavaScript chưa biết

theanh

Administrator
Nhân viên
Vài năm trước, bốn API JavaScript đã nằm ở cuối danh sách nhận thức trong cuộc khảo sát State of JavaScript. Tôi quan tâm đến các API đó vì chúng có rất nhiều tiềm năng hữu ích nhưng không được ghi nhận xứng đáng. Ngay cả sau khi tìm kiếm nhanh, tôi vẫn ngạc nhiên về số lượng API web mới được thêm vào thông số kỹ thuật ECMAScript không nhận được sự công nhận xứng đáng và thiếu sự nhận thức cũng như hỗ trợ trình duyệt trong các trình duyệt.

Tình huống đó có thể là "catch-22":
Hầu hết các API này được thiết kế để hỗ trợ các ứng dụng web tiến bộ (PWA) và thu hẹp khoảng cách giữa ứng dụng web và ứng dụng gốc. Hãy nhớ rằng việc tạo PWA không chỉ đơn thuần là thêm tệp kê khai. Chắc chắn, theo định nghĩa, đây là PWA, nhưng trên thực tế, nó hoạt động giống như một dấu trang trên màn hình chính của bạn. Trên thực tế, chúng ta cần một số API để đạt được trải nghiệm ứng dụng hoàn toàn gốc trên web. Và bốn API mà tôi muốn làm sáng tỏ là một phần của câu đố PWA mang đến cho web những gì chúng ta từng nghĩ chỉ có thể có trong các ứng dụng gốc.

Bạn có thể xem tất cả các API này đang hoạt động trong bản demo này khi chúng ta thực hiện.

1. API định hướng màn hình​

Có thể sử dụng API định hướng màn hình để phát hiện hướng hiện tại của thiết bị. Khi biết được người dùng đang duyệt theo hướng dọc hay ngang, chúng ta có thể sử dụng nó để nâng cao UX cho thiết bị di động bằng cách thay đổi UI cho phù hợp. Chúng ta cũng có thể sử dụng nó để khóa màn hình ở một vị trí nhất định, điều này hữu ích khi hiển thị video và các thành phần toàn màn hình khác được hưởng lợi từ chế độ xem rộng hơn.

Sử dụng đối tượng toàn cục screen, bạn có thể truy cập nhiều thuộc tính khác nhau mà màn hình sử dụng để hiển thị trang, bao gồm đối tượng screen.orientation. Đối tượng này có hai thuộc tính:
  • type: Hướng màn hình hiện tại. Có thể là: "portrait-primary", "portrait-secondary", "landscape-primary" hoặc "landscape-secondary".
  • angle: Góc hướng màn hình hiện tại. Có thể là bất kỳ số nào từ 0 đến 360 độ, nhưng thông thường được đặt theo bội số của 90 độ (ví dụ: 0, 90, 180 hoặc 270).
Trên thiết bị di động, nếu góc0 độ, thì kiểu thường sẽ được đánh giá là "portrait" (dọc), nhưng trên thiết bị máy tính để bàn, thông thường là "landscape" (ngang). Điều này làm cho thuộc tính type chính xác để biết vị trí thực của thiết bị.

Đối tượng screen.orientation cũng có hai phương thức:
  • .lock(): Đây là phương thức bất đồng bộ lấy giá trị type làm đối số để khóa màn hình.
  • .unlock(): Phương thức này mở khóa màn hình về hướng mặc định của nó.
Và cuối cùng, screen.orientation đếm với sự kiện "orientationchange" để biết khi nào hướng đã thay đổi.

Hỗ trợ trình duyệt​



Tìm và khóa hướng màn hình​

Chúng ta hãy viết một bản demo ngắn bằng cách sử dụng API hướng màn hình để biết hướng của thiết bị và khóa thiết bị ở vị trí hiện tại.

Đây có thể là mẫu HTML của chúng ta:
Mã:
 Kiểu định hướng:  
 Góc định hướng:  
 Màn hình khóa Mở khóa màn hình Chuyển sang chế độ toàn màn hình
Về phía JavaScript, chúng tôi đưa các thuộc tính typeangle hướng màn hình vào HTML của chúng tôi.
Mã:
let currentOrientationType = document.querySelector(".orientation-type");let currentOrientationAngle = document.querySelector(".orientation-angle");currentOrientationType.textContent = screen.orientation.type;currentOrientationAngle.textContent = screen.orientation.angle;
Bây giờ, chúng ta có thể thấy các thuộc tính hướng và góc của thiết bị. Trên máy tính xách tay của tôi, chúng là "landscape-primary".



Nếu chúng ta lắng nghe sự kiện orientationchange của cửa sổ, chúng ta có thể thấy các giá trị được cập nhật như thế nào mỗi khi màn hình xoay.
Mã:
window.addEventListener("orientationchange", () => { currentOrientationType.textContent = screen.orientation.type; currentOrientationAngle.textContent = screen.orientation.angle;});



Để khóa màn hình, trước tiên chúng ta cần ở chế độ toàn màn hình, vì vậy chúng ta sẽ sử dụng một tính năng cực kỳ hữu ích khác: API toàn màn hình. Không ai muốn một trang web chuyển sang chế độ toàn màn hình mà không có sự đồng ý của họ, vì vậy chúng ta cần kích hoạt tạm thời (tức là người dùng nhấp chuột) từ một phần tử DOM để hoạt động.

API toàn màn hình có hai phương thức:
  1. Document.exitFullscreen() được sử dụng từ đối tượng tài liệu toàn cục,
  2. Element.requestFullscreen() làm cho phần tử được chỉ định và các phần tử con của nó chuyển sang chế độ toàn màn hình.
Chúng ta muốn toàn bộ trang ở chế độ toàn màn hình để có thể gọi phương thức từ phần tử gốc tại đối tượng document.documentElement:
Mã:
const fullscreenButton = document.querySelector(".fullscreen-button");fullscreenButton.addEventListener("click", async () => { // Nếu đã ở chế độ toàn màn hình, thoát về chế độ xem bình thường if (document.fullscreenElement) { await document.exitFullscreen(); } else { await document.documentElement.requestFullscreen(); }});
Tiếp theo, chúng ta có thể khóa màn hình theo hướng hiện tại:
Mã:
const lockButton = document.querySelector(".lock-button");lockButton.addEventListener("click", async () => { try { await screen.orientation.lock(screen.orientation.type); } catch (error) { console.error(error); }});
Và làm ngược lại với nút mở khóa:
Mã:
const unlockButton = document.querySelector(".unlock-button");unlockButton.addEventListener("click", () => { screen.orientation.unlock();});

Chúng ta không thể kiểm tra hướng bằng Media Query sao?​

Có! Chúng ta thực sự có thể kiểm tra hướng trang thông qua tính năng orientation media trong một truy vấn phương tiện CSS. Tuy nhiên, các truy vấn phương tiện tính toán hướng hiện tại bằng cách kiểm tra xem chiều rộng có "lớn hơn chiều cao" đối với chế độ ngang hay "nhỏ hơn" đối với chế độ dọc không. Ngược lại,
Bạn có thể đã nhận thấy cách các PWA như Instagram và X buộc màn hình ở chế độ dọc ngay cả khi hướng hệ thống gốc được mở khóa. Điều quan trọng cần lưu ý là hành vi này không đạt được thông qua Screen Orientation API, mà bằng cách đặt thuộc tính orientation trên tệp manifest.json thành loại hướng mong muốn.

2. Device Orientation API​

Một API khác mà tôi muốn đề cập đến là Device Orientation API. API này cung cấp quyền truy cập vào cảm biến con quay hồi chuyển của thiết bị để đọc hướng của thiết bị trong không gian; một tính năng luôn được sử dụng trong các ứng dụng di động, chủ yếu là trò chơi. API thực hiện điều này bằng sự kiện deviceorientation kích hoạt mỗi khi thiết bị di chuyển. Sự kiện này có các thuộc tính sau:
  • event.alpha: Định hướng theo trục Z, từ 0 đến 360 độ.
  • event.beta: Định hướng theo trục X, từ -180 đến 180 độ.
  • event.gamma: Định hướng theo trục Y, từ -90 đến 90 độ.

Hỗ trợ trình duyệt​



Di chuyển các thành phần bằng thiết bị của bạn​

Trong trường hợp này, chúng ta sẽ tạo một khối lập phương 3D bằng CSS có thể xoay bằng thiết bị của bạn! Hướng dẫn đầy đủ mà tôi sử dụng để tạo khối CSS ban đầu được ghi nhận là của David DeSandro và có thể được tìm thấy trong phần giới thiệu về phép biến đổi 3D của ông ấy.

Xem Bút [Xoay khối [phân nhánh]](https://codepen.io/smashingmag/pen/vYwdMNJ) của Dave DeSandro.
Xem Bút Xoay khối [forked] của Dave DeSandro.
Bạn có thể thấy HTML thô đầy đủ trong bản demo, nhưng chúng ta hãy in nó ở đây để lưu giữ:
Mã:
   1 2 3 4 5 6   [HEADING=1]API định hướng thiết bị[/HEADING] 
 Alpha:  
 Beta:  
 Gamma:
Để tóm tắt, tôi sẽ không giải thích mã CSS ở đây. Chỉ cần nhớ rằng mã này cung cấp các kiểu cần thiết cho khối lập phương 3D và có thể xoay qua tất cả các trục bằng hàm CSS rotate().

Bây giờ, với JavaScript, chúng ta lắng nghe sự kiện deviceorientation của cửa sổ và truy cập dữ liệu hướng sự kiện:
Mã:
const currentAlpha = document.querySelector(".currentAlpha");const currentBeta = document.querySelector(".currentBeta");const currentGamma = document.querySelector(".currentGamma");window.addEventListener("deviceorientation", (sự kiện) => { currentAlpha.textContent = event.alpha; currentBeta.textContent = event.beta; currentGamma.textContent = event.gamma;});
Để xem dữ liệu thay đổi như thế nào trên thiết bị máy tính để bàn, chúng ta có thể mở DevTools của Chrome và truy cập Bảng điều khiển cảm biến để mô phỏng thiết bị xoay.



Để xoay khối lập phương, chúng ta thay đổi thuộc tính transform CSS của khối theo dữ liệu hướng thiết bị:
Mã:
const currentAlpha = document.querySelector(".currentAlpha");const currentBeta = document.querySelector(".currentBeta");const currentGamma = document.querySelector(".currentGamma");const cube = document.querySelector(".cube");window.addEventListener("deviceorientation", (event) => { currentAlpha.textContent = event.alpha; currentBeta.textContent = event.beta; currentGamma.textContent = event.gamma; cube.style.transform = `rotateX(${event.beta}deg) rotateY(${event.gamma}deg) rotateZ(${event.alpha}deg)`;});
Đây là kết quả:


3. Vibration API​

Chúng ta hãy chuyển sự chú ý của mình sang Vibration API, không có gì ngạc nhiên khi nó cho phép truy cập vào cơ chế rung của thiết bị. Điều này rất hữu ích khi chúng ta cần cảnh báo người dùng bằng thông báo trong ứng dụng, chẳng hạn như khi một quy trình hoàn tất hoặc khi nhận được tin nhắn. Tuy nhiên, chúng ta phải sử dụng nó một cách tiết kiệm; không ai muốn điện thoại của họ nổ tung vì thông báo.

Chỉ có một phương thức mà Vibration API cung cấp cho chúng ta và đó là tất cả những gì chúng ta cần: navigator.vibrate().

vibrate() có sẵn trên toàn cầu từ đối tượng navigator và sử dụng đối số về thời gian rung kéo dài tính bằng mili giây. Đối số này có thể là một số hoặc một mảng các số biểu thị cho người bảo trợ của các lần rung và tạm dừng.
Mã:
navigator.vibrate(200); // rung 200msnavigator.vibrate([200, 100, 200]); // rung 200ms, đợi 100 và rung 200ms.

Hỗ trợ trình duyệt​



Bản demo API rung​

Chúng ta hãy tạo một bản demo nhanh trong đó người dùng nhập số mili giây họ muốn thiết bị rung và các nút để bắt đầu và dừng rung, bắt đầu bằng mã đánh dấu:
Mã:
  Mili giây:   Rung Dừng
Chúng ta sẽ thêm một trình lắng nghe sự kiện cho một cú nhấp và gọi phương thức vibrate():
Mã:
const vibrateButton = document.querySelector(".vibrate-button");const millisecondsInput = document.querySelector("#milliseconds-input");vibrateButton.addEventListener("click", () => { navigator.vibrate(millisecondsInput.value);});
Để dừng rung, chúng tôi ghi đè rung hiện tại bằng rung không mili giây.
Mã:
const stopVibrateButton = document.querySelector(".stop-vibrate-button");stopVibrateButton.addEventListener("click", () => { navigator.vibrate(0);});

4. API Contact Picker​

Trước đây, chỉ có các ứng dụng gốc mới có thể kết nối với "danh bạ" của thiết bị. Nhưng bây giờ chúng ta có API thứ tư và cuối cùng mà tôi muốn xem xét: API Contact Picker.

API này cấp cho các ứng dụng web quyền truy cập vào danh sách liên lạc của thiết bị. Cụ thể, chúng ta có phương thức async contacts.select() có sẵn thông qua đối tượng navigator, phương thức này có hai đối số sau:
  • properties: Đây là một mảng chứa thông tin mà chúng ta muốn lấy từ một thẻ liên hệ, ví dụ: "name", "address", "email", "tel""icon".
  • options: Đây là một đối tượng chỉ có thể chứa thuộc tính boolean multiple để xác định người dùng có thể chọn một hoặc nhiều liên hệ cùng một lúc hay không.

Hỗ trợ trình duyệt​

Tôi e rằng trình duyệt này gần như không hỗ trợ gì, chỉ giới hạn ở Chrome Android, Samsung Internet và trình duyệt web gốc của Android tại thời điểm tôi viết bài này.


Chọn danh bạ của người dùng​

Chúng tôi sẽ tạo một bản demo khác để chọn và hiển thị danh bạ của người dùng trên trang. Một lần nữa, bắt đầu với HTML:
Mã:
 Get Contacts 
Contacts:
 [LIST]  [/LIST]
Sau đó, trong JavaScript, trước tiên chúng ta xây dựng các phần tử của mình từ DOM và chọn các thuộc tính mà chúng ta muốn chọn từ các liên hệ.
Mã:
const getContactsButton = document.querySelector(".get-contacts");const contactList = document.querySelector(".contact-list");const props = ["name", "tel", "icon"];const options = {multiple: true};
Bây giờ, chúng ta chọn các liên hệ một cách không đồng bộ khi người dùng nhấp vào getContactsButton.
Mã:
const getContacts = async () => { try { const contacts = await navigator.contacts.select(props, options); } catch (error) { console.error(error); }};getContactsButton.addEventListener("click", getContacts);
Bằng cách sử dụng thao tác DOM, sau đó chúng ta có thể thêm một mục danh sách vào mỗi liên hệ và một biểu tượng vào phần tử contactList.
Mã:
const appendContacts = (contacts) => { contacts.forEach(({name, tel, icon}) => { const contactElement = document.createElement("li"); contactElement.innerText = `${name}: ${tel}`; contactList.appendChild(contactElement); });};const getContacts = async () => { try { const contacts = await navigator.contacts.select(props, options); appendContacts(contacts); } catch (error) { console.error(error); }};getContactsButton.addEventListener("click", getContacts);
Việc thêm một hình ảnh hơi khó vì chúng ta sẽ cần chuyển đổi nó thành một URL và thêm nó cho từng mục trong danh sách.
Mã:
const getIcon = (icon) => { if (icon.length = 0) { const imageUrl = URL.createObjectURL(icon[0]); const imageElement = document.createElement("img"); imageElement.src = imageUrl; return imageElement; }};const appendContacts = (contacts) => { contacts.forEach(({name, tel, icon}) => { const contactElement = document.createElement("li"); contactElement.innerText = `${name}: ${tel}`; contactList.appendChild(contactElement); const imageElement = getIcon(icon); contactElement.appendChild(imageElement); });};const getContacts = async () => { try { const contacts = await navigator.contacts.select(props, options); appendContacts(contacts); } catch (lỗi) { console.error(lỗi); }};getContactsButton.addEventListener("click", getContacts);
Và đây là kết quả:



Lưu ý: API Contact Picker sẽ chỉ hoạt động nếu ngữ cảnh an toàn, tức là trang được phục vụ qua https:// hoặc wss:// URL.

Kết luận​

Vậy là chúng ta có bốn API web mà tôi tin rằng sẽ giúp chúng ta xây dựng các PWA hữu ích và mạnh mẽ hơn nhưng nhiều người trong chúng ta đã bỏ qua. Tất nhiên, điều này là do trình duyệt không hỗ trợ nhất quán, vì vậy tôi hy vọng bài viết này có thể nâng cao nhận thức về các API mới để chúng ta có cơ hội tốt hơn để thấy chúng trong các bản cập nhật trình duyệt trong tương lai.

Chúng không thú vị sao? Chúng ta đã thấy mức độ kiểm soát của chúng ta đối với hướng của thiết bị và màn hình của thiết bị cũng như mức độ truy cập mà chúng ta có thể truy cập vào các tính năng phần cứng của thiết bị, tức là độ rung và thông tin từ các ứng dụng khác để sử dụng trong giao diện người dùng của riêng chúng ta.

Nhưng như tôi đã nói trước đó, có một loại vòng lặp vô hạn trong đó thiếu nhận thức dẫn đến thiếu hỗ trợ trình duyệt. Vì vậy, mặc dù bốn API mà chúng tôi đã đề cập rất thú vị, nhưng kết quả của bạn chắc chắn sẽ khác khi sử dụng chúng trong môi trường sản xuất. Vui lòng thận trọng và tham khảo Caniuse để biết thông tin hỗ trợ mới nhất hoặc kiểm tra thiết bị của riêng bạn bằng WebAPI Check.
 
Back
Bên trên