Gatsby gần đây đã công bố ra mắt Functions, mở ra một chiều hướng khả thi mới — và tôi thì không thể phấn khích hơn! Với Gatsby hiện cung cấp Serverless Functions trên Gatsby Cloud (và Netlify cũng cung cấp hỗ trợ thông qua @netlify/plugin-gatsby), khuôn khổ từng bị hiểu lầm là "chỉ dành cho blog" giờ đây (theo tôi) trở thành nhà cung cấp công nghệ thú vị nhất trong không gian Jamstack hơn bao giờ hết.
Bản demo trong bài viết này là kết quả của một dự án gần đây mà tôi đã làm, trong đó tôi cần vẽ các vị trí địa lý xung quanh một quả cầu 3D và tôi nghĩ rằng sẽ rất thú vị nếu xem liệu có thể sử dụng cùng một kỹ thuật bằng cách sử dụng các vị trí ngoài hành tinh hay không. Cảnh báo tiết lộ: Hoàn toàn có thể! Nếu bạn muốn nhảy về phía trước, bạn có thể tìm thấy mã hoàn chỉnh tại đây.
Nếu bạn đã thiết lập dự án Gatsby, thật tuyệt! nhưng hãy đảm bảo rằng bạn đã nâng cấp Gatsby lên ít nhất phiên bản
Nếu chưa, hãy thoải mái sao chép kho lưu trữ khởi động Gatsby hoàn toàn cơ bản của tôi: mr-minimum.
Trước khi có thể bắt đầu sử dụng Hàm Gatsby để theo dõi Trạm vũ trụ quốc tế, trước tiên tôi cần tạo một quả địa cầu để nó quay quanh quỹ đạo.

Phần trên thiết lập một phần tử
Các phần tử được trả về dưới dạng phần tử con của thành phần canvas sẽ được hiển thị như một phần của cảnh 3D. Bạn sẽ thấy ở trên rằng tôi đã bao gồm
Đảm bảo
Điều này sẽ không có tác dụng nhiều vào lúc này vì không có gì để hiển thị trong cảnh. Hãy sửa lỗi đó!
Nếu cú pháp ở trên trông hơi khác so với cú pháp của tài liệu Three.js thì đó là do React Three Fibre sử dụng phương pháp khai báo để sử dụng Three.js trong React.
Bạn có thể xem giải thích hay về cách hoạt động của đối số hàm tạo trong React Three Fibre trong tài liệu tại đây: Đối số hàm tạo
Bây giờ hãy thêm
Bây giờ bạn sẽ thấy một cái gì đó tương tự như hình ảnh bên dưới.

Không thú vị lắm phải không? Hãy làm gì đó về điều đó!
Tôi sẽ sử dụng admin 0 quốc gia. Tôi chọn tùy chọn này vì nó cung cấp đủ chi tiết hình học để xem từng quốc gia, nhưng không quá nhiều đến mức gây thêm gánh nặng không cần thiết cho GPU của máy tính.
Bây giờ, hãy tạo một tệp trong
Có khá nhiều thứ đang diễn ra trong tệp này nên tôi sẽ hướng dẫn bạn.
Nếu bạn muốn biết thêm về cách thức hoạt động của GeoJsonGeometry, đây là kho lưu trữ mã nguồn mở để tham khảo: https://github.com/vasturiano/three-geojson-geometry. Kho lưu trữ có một thư mục example tuy nhiên, cú pháp hơi khác so với những gì bạn thấy ở đây vì các ví dụ được viết bằng JavaScript thuần túy chứ không phải React.
Bây giờ bạn sẽ thấy một thứ tương tự như hình ảnh bên dưới.

Giờ thì thú vị hơn một chút rồi!
Tạo một tệp trong
Hàm này chịu trách nhiệm lấy dữ liệu từ
Các kỹ sư của Gatsby đã thực hiện một công việc tuyệt vời trong việc đơn giản hóa các hàm không có máy chủ mà những điều trên là tất cả những gì bạn thực sự cần để bắt đầu, nhưng sau đây là một số thông tin chi tiết hơn về những gì đang diễn ra.
Tạo một tệp trong
Có khá nhiều thứ diễn ra trong tệp này nên tôi sẽ hướng dẫn bạn.
Một điều cần phải tìm hiểu một chút, ít nhất là đối với tôi, là cách sử dụng tọa độ hai chiều hình cầu (vĩ độ và kinh độ) trong ba chiều, ví dụ x, y, z. Khái niệm này đã được giải thích khá rõ trong bài đăng này của Mike Bostock.
Chìa khóa để vẽ vĩ độ / kinh độ trong không gian 3D nằm trong công thức này… mà tôi hoàn toàn không hiểu!
May mắn thay, Three.js có một bộ MathUtils mà tôi đã sử dụng như sau:
Bây giờ hãy thêm
Et voilà! Bây giờ bạn sẽ thấy một hình ảnh tương tự như hình ảnh bên dưới.

Hàm
ISS đang di chuyển với tốc độ khoảng 28.000 km/h và việc thăm dò Hàm Gatsby ít thường xuyên hơn sẽ tiết lộ những bước nhảy lớn hơn về vị trí. Tôi đã sử dụng 5 giây ở đây vì đó là thời gian yêu cầu thường xuyên nhất được cho phép bởi API Where is ISS at
Bạn cũng có thể nhận thấy rằng không cần xác thực để yêu cầu dữ liệu từ API Where is ISS at. Nghĩa là về mặt kỹ thuật, tôi có thể gọi API trực tiếp từ trình duyệt, tuy nhiên, tôi đã quyết định thực hiện cuộc gọi API này ở phía máy chủ bằng cách sử dụng Hàm Gatsby vì hai lý do:
Trong trang web này, tôi đã trực quan hóa độ trễ thời gian từ hàm


Bạn có thể đọc tất cả về cách tạo trang web này trên blog Gatsby: Cách chúng tôi thực hiện chương trình tặng thưởng 500 chai Gatsby
Trong trang 500 Bottles, tôi vẽ vị trí địa lý của từng người chiến thắng trong cuộc thi bằng phương pháp tương tự như được mô tả trong

Tôi có một số ý tưởng muốn khám phá bằng cách sử dụng V4 Space X API, vì vậy hãy theo dõi tôi nếu bạn thích: @PaulieScanlon
!
Bản demo trong bài viết này là kết quả của một dự án gần đây mà tôi đã làm, trong đó tôi cần vẽ các vị trí địa lý xung quanh một quả cầu 3D và tôi nghĩ rằng sẽ rất thú vị nếu xem liệu có thể sử dụng cùng một kỹ thuật bằng cách sử dụng các vị trí ngoài hành tinh hay không. Cảnh báo tiết lộ: Hoàn toàn có thể! Nếu bạn muốn nhảy về phía trước, bạn có thể tìm thấy mã hoàn chỉnh tại đây.
Bắt đầu
Với Gatsby Functions, bạn có thể tạo các ứng dụng động hơn bằng các kỹ thuật thường liên quan đến các ứng dụng phía máy khách bằng cách thêm thư mụcapi
vào dự án của mình và xuất một hàm, ví dụ:
Mã:
|-- src |-- api -- some-function.js |-- pages
Mã:
// src/api/some-function.jsexport default function handler(req, res) { res.status(200).json({ hello: `world` })}
v3.7
Mã:
npm install gatsby@latest --save
Trước khi có thể bắt đầu sử dụng Hàm Gatsby để theo dõi Trạm vũ trụ quốc tế, trước tiên tôi cần tạo một quả địa cầu để nó quay quanh quỹ đạo.

Bước 1: Xây dựng Quả cầu tương tác 3D
Tôi bắt đầu bằng cách thiết lập một quả cầu tương tác 3D có thể được sử dụng sau này để vẽ vị trí ISS hiện tại.Cài đặt các phụ thuộc
Mã:
npm install @react-three/fiber @react-three/drei three three-geojson-geometry axios --save
Tạo cảnh
Tạo tệp mới trong src/components
có tên là three-scene.js
Mã:
// src/components/three-scene.jsimport React from 'react';import { Canvas } from '@react-three/fiber';import { OrbitControls } from '@react-three/drei';const ThreeScene = () => { return ( { gl.setClearColor('#ffffff'); }} style={{ width: '100vw', height: '100vh', cursor: 'move' }} > );};export default ThreeScene;
mới và có thể được cấu hình bằng các props được React Three Fibre cung cấp.Các phần tử được trả về dưới dạng phần tử con của thành phần canvas sẽ được hiển thị như một phần của cảnh 3D. Bạn sẽ thấy ở trên rằng tôi đã bao gồm
để thêm tương tác chạm/chuột cho phép người dùng xoay cảnh trong không gian 3DĐảm bảo
ThreeScene
được nhập và hiển thị trên một trang nào đó trong trang web của bạn. Trong kho lưu trữ ví dụ của tôi, tôi đã thêm ThreeScene
vào index.js:
Mã:
// src/pages/index.jsimport React from 'react';import ThreeScene from '../components/three-scene';const IndexPage = () => { return ( );};export default IndexPage;
Tạo hình cầu
Tạo một tệp trong src/components
có tên là three-sphere.js:
Mã:
// src/components/three-sphere.jsimport React from 'react';const ThreeSphere = () => { return ( );};export default ThreeSphere;
Bạn có thể xem giải thích hay về cách hoạt động của đối số hàm tạo trong React Three Fibre trong tài liệu tại đây: Đối số hàm tạo
Bây giờ hãy thêm
ThreeSphere
vào ThreeScene
:
Mã:
// src/components/three-scene.jsimport React from 'react';nhập { Canvas } từ '@react-three/fiber';nhập { OrbitControls } từ '@react-three/drei';+ nhập ThreeSphere từ './three-sphere';const ThreeScene = () => { return ( { gl.setClearColor('#ffffff'); }} style={{ width: '100vw', height: '100vh', cursor: 'move' }} > + );};xuất mặc định ThreeScene;

Không thú vị lắm phải không? Hãy làm gì đó về điều đó!
Tạo hình học (để trực quan hóa các quốc gia trên hành tinh Trái đất)
Bước tiếp theo này yêu cầu sử dụng three-geojson-geometry và một tài nguyên CDN có chứa Dữ liệu Trái đất tự nhiên. Bạn có thể chọn từ danh sách đầy đủ các hình học phù hợp tại đây.Tôi sẽ sử dụng admin 0 quốc gia. Tôi chọn tùy chọn này vì nó cung cấp đủ chi tiết hình học để xem từng quốc gia, nhưng không quá nhiều đến mức gây thêm gánh nặng không cần thiết cho GPU của máy tính.
Bây giờ, hãy tạo một tệp trong
src/components
có tên là three-geo.js:
Mã:
// src/components/three-geo.jsimport React, { Fragment, useState, useEffect } from 'react';import { GeoJsonGeometry } from 'three-geojson-geometry';import axios from 'axios';const ThreeGeo = () => {const [isLoading, setIsLoading] = useState(true); const [geoJson, setGeoJson] = useState(null); useEffect(() => { axios .get( 'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_110m_admin_0_countries.geojson' ) .then((phản hồi) => { setIsLoading(false); setGeoJson(phản hồi.data); }) .catch((lỗi) => { console.log(lỗi); ném Lỗi mới(); }); }, []); return ( {!isLoading ? ( {geoJson.features.map(({ geometry }, index) => { return (
[*] ); })} ) : null} );};export default ThreeGeo;
- Tạo một thể hiện trạng thái
isLoading
bằng cách sử dụng React hooks và đặt nó thànhtrue
. Điều này ngăn React cố gắng trả về dữ liệu mà tôi chưa có. - Sử dụng
useEffect
, tôi yêu cầu geojson từ CloudFront CDN. - Sau khi truy xuất thành công, tôi đặt phản hồi ở trạng thái React bằng cách sử dụng
setGeoJson(...)
và đặtisLoading
thànhfalse
- Sử dụng Array.prototype.map, tôi lặp lại các "tính năng" có trong phản hồi geojson và trả về
lineSegments
vớilineBasicMaterial
cho mỗihình học
- Tôi đặt
lineSegments
hình học
thành giá trị trả về được cung cấp bởiGeoJsonGeomtry
được truyền qua các "tính năng"hình học
cùng với bán kính100
.
100
ở đây như tôi đã sử dụng trong sphereGeometry
args
trong three-sphere.js. Bạn không cần phải đặt bán kính thành cùng một giá trị nhưng việc sử dụng cùng một bán kính cho ThreeSphere
và ThreeGeo
là hợp lý.Nếu bạn muốn biết thêm về cách thức hoạt động của GeoJsonGeometry, đây là kho lưu trữ mã nguồn mở để tham khảo: https://github.com/vasturiano/three-geojson-geometry. Kho lưu trữ có một thư mục example tuy nhiên, cú pháp hơi khác so với những gì bạn thấy ở đây vì các ví dụ được viết bằng JavaScript thuần túy chứ không phải React.
Kết hợp hình cầu và hình học
Bây giờ là lúc phủ hình học lên trên hình cầu trống: Thêm ThreeGeo
vào ThreeScene
Mã:
// src/components/three-scene.jsimport React from 'react';import { Canvas } from '@react-three/fiber';import { OrbitControls } from '@react-three/drei';import ThreeSphere from './three-sphere';+ import ThreeGeo từ './three-geo';const ThreeScene = () => { return ( { gl.setClearColor('#ffffff'); }} style={{ width: '100vw', height: '100vh', cursor: 'move' }} > + );};

Giờ thì thú vị hơn một chút rồi!
Bước 2: Xây dựng hàm không máy chủ
Tạo hàm
Bước tiếp theo là nơi tôi sử dụng hàm Gatsby để yêu cầu dữ liệu từ ISS ở đâu, hàm này trả về vị trí hiện tại của Trạm vũ trụ quốc tế Trạm.Tạo một tệp trong
src/api
có tên là get-iss-location.js:
Mã:
// src/api/get-iss-location.jsconst axios = require('axios');export default async function handler(req, res) { try { const { data } = await axios.get( 'https://api.wheretheiss.at/v1/satellites/25544' ); res.status(200).json({ iss_now: data }); } catch (error) { res.status(500).json({ error }); }}
api.whereistheiss.at
và khi thành công sẽ trả về data
và mã trạng thái 200
cho trình duyệt.Các kỹ sư của Gatsby đã thực hiện một công việc tuyệt vời trong việc đơn giản hóa các hàm không có máy chủ mà những điều trên là tất cả những gì bạn thực sự cần để bắt đầu, nhưng sau đây là một số thông tin chi tiết hơn về những gì đang diễn ra.
- Hàm này là mặc định xuất từ tệp có tên
get-iss-location.js
; - Với Hàm Gatsby, tên tệp sẽ trở thành đường dẫn tệp được sử dụng trong yêu cầu
get
phía máy khách có tiền tố api, ví dụ:/api/get-iss-location
; - Nếu yêu cầu "ISS ở đâu" thành công, tôi sẽ trả về đối tượng
iss_now
chứadữ liệu
từ API ISS ở đâu và mã trạng thái200
trở lại máy khách; - Nếu yêu cầu có lỗi, tôi sẽ gửi
lỗi
trở lại máy khách.
Bước 3: Xây dựng Trạm vũ trụ quốc tế
Tạo hình cầu ISS
Trong bước tiếp theo này, tôi sử dụng Hàm Gatsby để định vị một hình cầu biểu diễn Trạm vũ trụ quốc tế khi nó quay quanh quả địa cầu. Tôi thực hiện điều này bằng cách gọi liên tục một yêu cầu axios.get
từ một hàm poll
và thiết lập phản hồi ở trạng thái React.Tạo một tệp trong
src/components
có tên là three-iss.js
Mã:
// src/components/three-iss.jsimport React, { Fragment, useEffect, useState } from 'react';import * as THREE from 'three';import axios from 'axios';export const getVertex = (latitude, longitude, radius) => { const vector = new THREE.Vector3().setFromSpherical( new THREE.Spherical( radius, THREE.MathUtils.degToRad(90 - vĩ độ), THREE.MathUtils.degToRad(kinh độ) ) ); return vector;};const ThreeIss = () => { const [issNow, setIssNow] = useState(null); const poll = () => { axios .get('/api/get-iss-location') .then((response) => { setIssNow(response.data.iss_now); }) .catch((error) => { console.log(error); throw new Error(); }); }; useEffect(() => { const pollInterval = setInterval(() => { poll(); }, 5000); poll(); return () => clearInterval(pollInterval); }, []); return ( {issNow ? ( ) : null} );};export default ThreeIss;
- Tạo một thể hiện trạng thái
issNow
bằng cách sử dụng các hook React và đặt nó thành null. Điều này ngăn React cố gắng trả về dữ liệu mà tôi chưa có; - Sử dụng
useEffect
, tôi tạo một khoảng thời gian JavaScript gọi hàmpoll
sau mỗi 5 giây; - Hàm
poll
là nơi tôi yêu cầu vị trí ISS từ điểm cuối Hàm Gatsby (/api/get-iss-location
); - Sau khi truy xuất thành công, tôi đặt phản hồi ở trạng thái React bằng cách sử dụng
setIssNow(...)
; - Tôi truyền
vĩ độ
vàkinh độ
vào một hàm tùy chỉnh có tên làgetVertex
, cùng vớibán kính
.
120
. Điều này khác với giá trị bán kính 100
được sử dụng trong ThreeSphere
và ThreeGeo
. Hiệu ứng của bán kính lớn hơn là định vị ISS cao hơn trong bối cảnh 3D, thay vì ở mặt đất — vì về mặt logic, đó là nơi ISS sẽ ở, đúng không?100
có hiệu ứng hình cầu và hình học chồng lên nhau để biểu diễn Trái đất, và 120
đối với ISS có hiệu ứng trạm vũ trụ "quay quanh" quả cầu mà tôi đã tạo ra.Một điều cần phải tìm hiểu một chút, ít nhất là đối với tôi, là cách sử dụng tọa độ hai chiều hình cầu (vĩ độ và kinh độ) trong ba chiều, ví dụ x, y, z. Khái niệm này đã được giải thích khá rõ trong bài đăng này của Mike Bostock.
Chìa khóa để vẽ vĩ độ / kinh độ trong không gian 3D nằm trong công thức này… mà tôi hoàn toàn không hiểu!
Mã:
x=rcos(ϕ)cos(λ)y=rsin(ϕ)z=−rcos(ϕ)sin(λ)
- Truyền
vĩ độ
,kinh độ
vàradius
vào hàmgetVertex(...)
- Tạo đối tượng
THREE.Spherical
mới từ các tham số được đặt tên ở trên - Đặt đối tượng
THREE.Vector3
bằng cách sử dụng các giá trị Spherical được trả về bởi hàm trợ giúpsetFromSpherical
.
Bây giờ hãy thêm
ThreeIss
vào ThreeScene
:
Mã:
import React từ 'react';import { Canvas } từ '@react-three/fiber';import { OrbitControls } từ '@react-three/drei';import ThreeSphere từ './three-sphere';import ThreeGeo từ './three-geo';+ import ThreeIss từ './three-iss';const ThreeScene = () => { return ( { gl.setClearColor('#ffffff'); }} style={{ width: '100vw', height: '100vh', cursor: 'move' }} > + );};xuất mặc định ThreeScene;

Hàm
poll
sẽ liên tục gọi Hàm Gatsby, hàm này sẽ yêu cầu vị trí hiện tại của ISS và kết xuất lại thành phần React mỗi khi phản hồi thành công. Bạn sẽ phải quan sát cẩn thận nhưng ISS sẽ thay đổi vị trí rất nhỏ sau mỗi 5 giây.ISS đang di chuyển với tốc độ khoảng 28.000 km/h và việc thăm dò Hàm Gatsby ít thường xuyên hơn sẽ tiết lộ những bước nhảy lớn hơn về vị trí. Tôi đã sử dụng 5 giây ở đây vì đó là thời gian yêu cầu thường xuyên nhất được cho phép bởi API Where is ISS at
Bạn cũng có thể nhận thấy rằng không cần xác thực để yêu cầu dữ liệu từ API Where is ISS at. Nghĩa là về mặt kỹ thuật, tôi có thể gọi API trực tiếp từ trình duyệt, tuy nhiên, tôi đã quyết định thực hiện cuộc gọi API này ở phía máy chủ bằng cách sử dụng Hàm Gatsby vì hai lý do:
- Sẽ không có bài đăng trên blog hay nào về Hàm Gatsby nếu tôi không sử dụng chúng.
- Ai biết được tương lai của Where is ISS at sẽ ra sao, tại một thời điểm nào đó, nó có thể yêu cầu xác thực và việc thêm khóa API vào các yêu cầu API phía máy chủ khá đơn giản, hơn nữa, thay đổi này sẽ không yêu cầu bất kỳ bản cập nhật nào cho mã phía máy khách.
Bước 4: Làm cho nó trở nên thú vị hơn! (Tùy chọn)
Tôi đã sử dụng cách tiếp cận trên để tạo ra triển khai hấp dẫn hơn một chút này: https://whereisiss.gatsbyjs.io,Trong trang web này, tôi đã trực quan hóa độ trễ thời gian từ hàm
poll
bằng cách triển khai hoạt ảnh đếm ngược Svg
và thêm
bổ sung với stroke-dashoffset
để tạo các đường đứt nét bao quanh nó.
Bước 5: Áp dụng các kỹ năng kết xuất địa lý mới của bạn theo những cách thú vị khác!
Gần đây tôi đã sử dụng phương pháp này để vẽ vị trí địa lý cho những người chiến thắng trong cuộc thi 500 Bottles: https://500bottles.gatsbyjs.io. Quà tặng MIỄN PHÍ phiên bản giới hạn mà tôi đã làm việc cùng nhóm tiếp thị của Gatsby.
Bạn có thể đọc tất cả về cách tạo trang web này trên blog Gatsby: Cách chúng tôi thực hiện chương trình tặng thưởng 500 chai Gatsby
Trong trang 500 Bottles, tôi vẽ vị trí địa lý của từng người chiến thắng trong cuộc thi bằng phương pháp tương tự như được mô tả trong
ThreeIss,
cho phép bất kỳ ai truy cập trang web đều có thể xem những người chiến thắng ở đâu trên thế giới.
Suy nghĩ kết thúc
Gatsby Functions thực sự mở ra rất nhiều khả năng cho các nhà phát triển Jamstack và không bao giờ phải lo lắng về việc khởi động hoặc mở rộng quy mô máy chủ, giúp loại bỏ rất nhiều vấn đề, giúp chúng ta rảnh tay suy nghĩ về những cách mới để sử dụng chúng.Tôi có một số ý tưởng muốn khám phá bằng cách sử dụng V4 Space X API, vì vậy hãy theo dõi tôi nếu bạn thích: @PaulieScanlon
Các nguồn tài nguyên khác
- Nếu bạn muốn tìm hiểu thêm về Gatsby Functions, tôi thực sự khuyên bạn nên tham gia Summer Functions, một khóa học kéo dài năm tuần do người bạn tốt của tôi Benedicte Raae.
- Trong hội thảo trực tuyến MIỄN PHÍ vào tối thứ sáu gần đây của Summer Functions, chúng tôi đã tạo ra một máy đánh bạc biểu tượng cảm xúc cực kỳ thú vị:
- Xây dựng máy đánh bạc biểu tượng cảm xúc bằng Hàm không máy chủ #GatsbyJS · #GatsbySummerFunctions
- Bạn cũng có thể quan tâm đến tập sau từ chương trình internet khó nhằn của chúng tôi Gatsby Deep Dives, trong đó Kyle Mathews (người sáng tạo ra Gatsby) sẽ hướng dẫn chúng ta cách thức hoạt động của Hàm Gatsby:
- Các hàm không có máy chủ của Gatsby
— Chúng ta đang trực tuyến phải không? với Kyle Mathews
- Nếu bạn muốn tìm hiểu thêm về Gatsby, tôi có một số bài viết và hướng dẫn trên blog của mình: https://paulie.dev và vui lòng tìm tôi trên Twitter nếu bạn muốn trò chuyện: @PaulieScanlon

Đọc thêm
- Giới thiệu về khả năng soạn thảo toàn bộ ngăn xếp
- Cài đặt blog solo miễn phí tối ưu với Ghost và Gatsby
- Lý do nên dùng Prisma trong Jamstack
- Regexes Got Good: Lịch sử và tương lai của biểu thức chính quy trong JavaScript