Giới thiệu
Trong bài viết này, chúng ta sẽ tìm hiểu cách biến một hình ảnh SVG tĩnh thành một nền phản ứng thú vị với sự di chuyển của chuột! Đây là một bổ sung tuyệt vời cho các trang web hồ sơ, trang web tương tác hoặc thậm chí trong các bối cảnh chuyên nghiệp nếu bạn muốn tạo ra điều gì đó thú vị. Cụ thể, bài viết này sẽ hướng dẫn cách thao tác với nền hình đa giác được tạo ra từ Haikei, một nguồn tài nguyên SVG miễn phí để tạo mẫu và hiệu ứng.
Ý tưởng
Mục tiêu là tạo ra một nền hình đa giác Haikei thay đổi màu sắc khi chuột di chuyển qua. Khi người dùng di chuyển chuột qua hình ảnh SVG, các hình tam giác bên dưới sẽ thay đổi màu sắc một cách tinh tế, với hiệu ứng nhẹ hơn trên các hình tam giác xung quanh. Chúng ta có thể áp dụng một vài hiệu ứng thú vị, chẳng hạn như làm tối các hình tam giác xung quanh, làm sáng chúng hoặc thêm hiệu ứng phát sáng. Nếu bạn chỉ muốn xem kết quả, có một CodePen ở cuối bài viết này! Hoặc bạn chỉ muốn xem mã mà tôi đã bỏ qua ở đây.
Chuẩn bị nền
Để theo dõi hướng dẫn này, bạn có thể truy cập tài nguyên sau: Haikei. Dưới đây là hình ảnh mà tôi sẽ sử dụng.
Đầu tiên, chúng ta cần nhập hình ảnh vào Figma. Vì các tệp xuất từ Haikei thường nhỏ hơn kích thước mà chúng ta muốn cho màn hình PC (1920x1080), chúng ta có thể dễ dàng điều chỉnh kích thước tại đây. Nếu bạn muốn tính tương thích tối đa, bạn cũng có thể tạo một hình ảnh nhỏ hơn cho điện thoại.
Bây giờ đến phần khó khăn. Bạn có biết có bao nhiêu hình đa giác trong hình ảnh đó không? 108... Chúng ta cần các ID duy nhất cho mỗi hình đa giác, vì vậy bạn có thể chỉnh sửa SVG trong Figma và đặt tên cho mỗi path/vector rồi nhấp vào Xuất dưới dạng ID, hoặc bạn có thể chỉnh sửa mã SVG thủ công trong dự án của bạn. Để linh hoạt, hãy đặt tên cho chúng theo cách có thể lặp lại như Vector1, Vector2, v.v. Hãy vui vẻ! Bạn có thể viết một script cho điều này nhưng vì đây chỉ là một lần duy nhất nên tại sao không chịu khó một chút?
Cuối cùng, trong thiết lập cơ bản, chúng ta nên cung cấp cho thẻ SVG nhiều tùy chọn kích thước linh hoạt hơn, như sau:
html
<svg
width="100%"
height="100%"
viewBox="0 0 1980 1080"
fill="none"
preserveAspectRatio="none"
xmlns="http://www.w3.org/2000/svg"
>
Chúng ta cũng nên đặt nó bên trong một div như sau:
css
.poly-container {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
overflow: hidden;
}
Vậy là xong, đó là tất cả thiết lập. Bây giờ là phần phức tạp hơn.
Thao tác với các hình đa giác
Có nhiều cách khác nhau để thực hiện điều này. Để thay đổi một hình đa giác duy nhất, chúng ta chỉ cần thêm hiệu ứng :hover vào CSS cho các path SVG với một transition. Nhưng đó không phải là mục tiêu; chúng ta muốn ảnh hưởng đến nhiều hình. Tôi đã có một vài ý tưởng, đầu tiên là tạo một lưới các điểm xung quanh chuột theo hình tròn và thay đổi màu sắc dựa trên khoảng cách. Nhưng điều đó gặp phải một số vấn đề đầu tiên, nó quá phức tạp, và chúng ta sẽ cần phải kiểm tra liên tục các phần tử bên dưới một điểm với elementFromPoint. Điều đó khá nặng nề vì chúng ta muốn một nền nhẹ. Nhưng tin tốt là tôi đã tìm ra một giải pháp khác như dưới đây.
Khởi tạo dữ liệu hình đa giác
Ý tưởng của tôi là lặp qua các thành phần SVG một lần ở đầu và thu thập 4 giá trị. Đầu tiên là khoảng cách, sau đó là màu sắc, tên ID, và cuối cùng là tâm của hình đa giác. Sau đó, chúng ta có thể lưu trữ tất cả 108 phần tử trong một mảng. Cấu trúc kiểu/đối tượng như sau:
typescript
type IdValue = {
id: string;
distanceToMouse: number;
color: number[];
elCenter: DOMRect;
};
Tại sao chúng ta cần lưu trữ những thứ này? Đầu tiên, chúng ta cần ID để tham chiếu và vị trí, khoảng cách như một placeholder, và màu sắc như giá trị ban đầu. Đối với màu sắc, chúng ta dĩ nhiên cần thay đổi nó, và nếu muốn quay lại ban đầu, chúng ta cần nó trong bộ nhớ. Về elCenter, chúng ta chỉ muốn lưu trữ điểm tâm của mỗi hình đa giác một lần khi khởi tạo hoặc khi thay đổi kích thước. Nếu không, nếu không lưu trữ, chúng ta sẽ chạy getBoundingClientRect(); mỗi frame, điều này nặng nề và không cần thiết.
Vòng lặp chuột
Bây giờ chúng ta đã khởi tạo các giá trị, chúng ta có thể xem xét vòng lặp chính. Tôi đã đưa các hàm của mình vào một trình lắng nghe sự kiện mousemove. Chúng ta chỉ cần xem xét các thay đổi khi bộ điều khiển, tức là chuột di chuyển. Đây là cách nó trông như thế nào:
typescript
function mouseMove(e: MouseEvent) {
mouseRef.current.x = e.clientX;
mouseRef.current.y = e.clientY;
for (const i of otherPolyRef.current) {
updateDistances(i);
darkenDistance(i);
}
}
Bây giờ chúng ta lưu trữ vị trí chuột để sử dụng trong updateDistances, phần quan trọng của toàn bộ hiệu ứng. Bây giờ updateDistances như nó nghe; chúng ta truyền mỗi IdValue, nó tính toán khoảng cách Euclidean từ tâm của hình đa giác đến chuột, và lưu trữ giá trị mới trong IdValue.
Áp dụng màu sắc dựa trên khoảng cách
Từ điểm này, mỗi IdValue đã có giá trị khoảng cách được cập nhật. Bây giờ chúng ta có thể xem xét điều gì tạo ra hiệu ứng của chúng ta darkenDistance, mà để đơn giản hóa hiện tại chỉ là một thay đổi màu đen và trắng. Các phần tử gần chuột sẽ tối hơn, các phần tử xa hơn sẽ chỉ là trắng. Mã và những gì chúng ta mở rộng cho phiên bản màu sắc như sau:
typescript
export function darkenDistance(
i: IdValue,
distanceMax = 1000,
intensity = [0.01, 0.99]
) {
const el = document.getElementById(i.id);
if (!el) return;
const distance = Math.min(i.distanceToMouse, distanceMax);
const originalLightness = 100;
const norm = intensity[0] + intensity[1] * (distance / distanceMax);
const lightness = Math.round(originalLightness * norm);
el.style.fill = `hsl(0, 0%, ${lightness}%)`;
el.style.stroke = `hsl(0, 0%, ${lightness}%)`;
el.style.transition = "fill 0.3s linear, stroke 0.3s linear";
}
Hãy cùng đi qua điều này. Đầu tiên, chúng ta thu thập các giá trị quan trọng từ IdValue: ref, màu sắc, và 'originalLightness'. Giá trị này được đặt là 100, và hue và saturation được đặt là 0; điều này tạo ra một phiên bản chuyên nghiệp hơn của hiệu ứng.
Bây giờ, điều quan trọng nhất là toán học. Ở đây, nó rất đơn giản và tuyến tính, nhưng về cơ bản, giả sử chúng ta ở xa chuột nhưng vẫn trong phạm vi. Khoảng cách chuẩn hóa của chúng ta sẽ đạt 0.99, chúng ta nhân nó với độ sáng, nó giảm nhẹ, nhưng nếu chúng ta gần hoặc gần nhất, độ sáng ban đầu của chúng ta sẽ bị nhân với 0.01, giảm mạnh. Cường độ của chúng ta hoạt động như một khoảng nếu chúng ta không muốn làm tối quá mức, chúng ta có thể tăng 0.01 lên thành 0.1 hoặc hơn. Như vậy, khi di chuyển chuột, chúng ta sẽ có hiệu ứng như sau.
Đối với màu sắc, chúng ta chỉ cần trích xuất và lưu trữ giá trị gốc trong i.color thay vì chỉ sử dụng các giá trị đã tạo sẵn. Và khi đưa vào độ sáng mới, chúng ta thêm hue và saturation gốc.
typescript
el.style.fill = `hsl(${i.color[0]}, ${i.color[1]}%, ${lightness}%)`;
el.style.stroke = `hsl(${i.color[0]}, ${i.color[1]}%, ${lightness}%)`;
Bây giờ là lúc thú vị; bạn có thể thêm hiệu ứng phát sáng vào nó. Đảo ngược hiệu ứng, làm cho nó sáng hơn khi gần chuột. Hoặc chỉ giảm hiệu ứng nói chung, làm cho nó ít đáng chú ý hơn để phù hợp với một thiết kế thích hợp thay vì một hoạt hình thú vị.
Các biến thể
Tại đây, tôi sẽ giới thiệu một số hình ảnh của một vài biến thể mà tôi đã thực hiện trước khi liên kết đến một CodePen của hiệu ứng yêu thích của tôi. Tất cả những điều này có thể được thực hiện bằng cách thay đổi hàm darkenDistance hoặc thay đổi màu sắc SVG khi khởi tạo. Một lưu ý bên lề nếu bạn không muốn tạo lại một SVG mới từ Haikei để thay đổi màu sắc thành một cái gì đó mới, bạn chỉ cần thêm một thứ vào giai đoạn khởi tạo để thay đổi màu sắc thành một dải mà bạn mong muốn! Và đây là hiệu ứng yêu thích của tôi, phiên bản đen trắng đơn giản với đường viền đen đặc. Vẫn sử dụng SVG đa giác tím.
Đây là ý tưởng ban đầu. Một chút thất vọng, thành thật mà nói, nhưng tôi khá chắc chắn rằng điều đó là do màu sắc ở đây.
Đây là một hiệu ứng thú vị. Tôi đã thêm một hiệu ứng phát sáng cùng với việc làm tối màu. Hơn nữa, ở khoảng cách, tôi cũng đã thêm một hiệu ứng làm sáng.
Và cuối cùng, đây là một CodePen để bạn có thể thử nghiệm với nó.
Kết Luận
Hy vọng bạn thích bài viết này hoặc thấy nó thú vị! Tôi rất thích làm những điều như thế này, nó rất linh hoạt, thú vị, và tôi thực sự thấy nó có thể tạo ra những nền thú vị cho các trang web. Tôi hy vọng bạn đã học được điều gì đó từ bài viết này. Và nếu bạn muốn tìm hiểu thêm về những thứ khác của tôi, bạn có thể truy cập trang web của tôi tại đây hoặc chờ đợi bài viết tiếp theo của tôi, chắc chắn sẽ rất thú vị!