sách gpt4 ăn đã đi

Tái cấu trúc: Hoạt ảnh tổng hợp và phân tán logo trong biểu ngữ

In lại Tác giả: Tôi là chú chim nhỏ Thời gian cập nhật: 2023-03-16 14:31:40 35 4
mua khóa gpt4 giày nike

1. Hiển thị hiệu ứng


hình ảnh

Xem trực tuyến.

2. Hướng dẫn trước khi bắt đầu

Mã nguồn tham khảo thực hiện hiệu ứng: Thu thập và lan tỏa logo.

Mã hiệu ứng ban đầu được triển khai dựa trên các thành phần lớp phản ứng jsx. Phụ thuộc cũ, mã dư thừa.

Tôi sẽ tái cấu trúc dựa trên điều này, mục tiêu tái cấu trúc:

  • Dựa trên các gói phụ thuộc mới nhất, sử dụng ts + hook để đạt được hiệu quả
  • Đơn giản hóa cấu trúc và kiểu dáng DOM
  • Hỗ trợ đáp ứng

Việc tái cấu trúc nên dựa trên việc khôi phục và sử dụng cách tốt hơn để đạt được hiệu quả tương tự. Sẽ tốt hơn nếu các chức năng có thể được hoàn thiện hơn.

Trong quá trình tái thiết, hãy chú ý tìm hiểu:

  • chế độ nghiêm ngặt
  • Không thể lấy dữ liệu mới nhất, setState cập nhật không đồng bộ, useRef đồng bộ hóa dữ liệu mới nhất
  • Vòng đời thành phần lớp, cách chuyển đổi nó thành hook
  • Vẽ trên canvas để lấy dữ liệu hình ảnh và xử lý dữ liệu

3. Tái cấu trúc

Lưu ý: Sau đây là toàn bộ mã. Nếu bạn quan tâm đến mã, bạn có thể so sánh nó với mã nguồn; nếu bạn quan tâm đến hiệu ứng, tôi hy vọng nó sẽ hữu ích cho bạn! .

Giàn giáo: vite-react+ts.

3.1 Xóa các file và code thừa, chỉ để lại cấu trúc đơn giản nhất

  • Sửa đổi tập tin nhập chính.tsx vì:
                        
                          nhập ReactDOM từ "react-dom/client"; nhập App từ "./App"; ReactDOM.createRoot(document.getElementById("root") dưới dạng HTMLElement).render(  );

                        
                      

Lưu ý: Chế độ nghiêm ngặt đã bị xóa ở đây.

  • Xóa chỉ mục.css.

  • Sửa đổi App.tsx thành:

                        
                          nhập "./App.css"; hàm App() { trả về ( 
); } xuất mặc định App;
  • Ôn lại Ứng dụng.css vì:
                        
                          * { lề: 0; đệm: 0; kích thước hộp: hộp viền; }

                        
                      

3.3 Cài đặt phụ thuộc

                        
                          sợi thêm rc-tween-one lodash-es -S sợi thêm @types/lodash-es -D

                        
                      

RC-tween-one: Thành phần hoạt hình của Ant Motion.

3.4 Cấu trúc lại mã

ỨNG DỤNG.tsx 。

                        
                          import TweenOne từ "rc-tween-one"; import LogoAnimate từ "./logoAnimate"; import "./App.css"; function App() { return ( 
logo 聚合分散
); } export default App;

Ứng dụng.css 。

                        
                          * { lề: 0; đệm: 0; kích thước hộp: hộp viền; } .banner { chiều rộng: 100%; chiều cao: 100vh; tràn: ẩn; nền: gradient tuyến tính (135 độ, #35aef8 0%, #7681ff 76%, #7681ff 76%); vị trí: tương đối; hiển thị: flex; căn chỉnh các mục: giữa; căn chỉnh nội dung: khoảng cách đều nhau; } .banner .content { chiều cao: 35%; màu sắc: #fff; } .banner .content .title { kích thước phông chữ: 40px; nền: gradient tuyến tính (màu vàng, trắng); -webkit-background-clip: văn bản; màu sắc: trong suốt; } .banner .logo-box { chiều rộng: 300px; chiều cao: 330px; } .banner .logo-box * { sự kiện con trỏ: không có; } .banner .logo-box img { lề trái: 70px; biến đổi: tỷ lệ (1,5); lề trên: 60px; độ mờ đục: 0,4; } .banner .logo-box .point-wrap { vị trí: tuyệt đối; } .banner .logo-box .point-wrap .point { bán kính đường viền: 100%; } @media screen and (max-width: 767px) { .banner { hướng uốn cong: cột; } .banner .content { thứ tự: 1; } } * { lề: 0; đệm: 0; kích thước hộp: hộp viền; } .banner { chiều rộng: 100%; chiều cao: 100vh; tràn: ẩn; nền: gradient tuyến tính (135 độ, #35aef8 0%, #7681ff 76%, #7681ff 76%); vị trí: tương đối; hiển thị: flex; căn chỉnh các mục: giữa; căn chỉnh nội dung: khoảng cách đều nhau; } .banner .content { chiều cao: 35%; màu sắc: #fff; } .banner .content .title { kích thước phông chữ: 30px; } .banner .logo-box { chiều rộng: 300px; chiều cao: 330px; } .banner .logo-box * { sự kiện con trỏ: không có; } .banner .logo-box img { lề trái: 70px; biến đổi: tỷ lệ (1,5); lề trên cùng: 60px; độ mờ đục: 0,4; } .banner .logo-box .point-wrap { vị trí: tuyệt đối; } .banner .logo-box .point-wrap .point { bán kính đường viền: 100%; } @media màn hình và (chiều rộng tối đa: 767px) { .banner { hướng flex: cột; } .banner .content { thứ tự: 1; } }

                        
                      

Tập trung vào việc xây dựng lại tệp logoAnimate.tsx.

                        
                          nhập React, { useRef, useState, useEffect } từ "react"; nhập TweenOne, { Ticker } từ "rc-tween-one"; loại nhập { IAnimObject } từ "rc-tween-one" nhập { cloneDeep, delay } từ "lodash-es"; gõ Point = { WrapStyle: { left: number; top: number }; style: { width: number; số; màu nền: chuỗi; }; hoạt ảnh: IAnimObject }; const logoAnimate = () => { const data = { image: "../../../storages/f390-audiofreehighqps/4C/D1/GKwRIDoHwne3AABEqQH4FjLV. png", w: 200, // Chiều rộng thực tế của ảnh h: 200, // Chiều cao thực tế của tỷ lệ hình ảnh: 1,5, // Tỷ lệ chia tỷ lệ cần thiết cho điểm hiển thịSizeMin: 10, // Kích thước tối thiểu của dấu chấm để hiển thị}; const intervalRef = useRef(null); 5000; const initAnimateTime = 800; const logoBoxRef = useRef(null); Tập hợp: true, đảm bảo rằng bạn sẽ luôn nhận được dữ liệu mới nhất useState không đồng bộ và không thể lấy được trong khoảng thời gian const GatherRef = useRef(true); // Dữ liệu thay đổi sẽ nhắc dom thay đổi const [points, setPoints] = useState< Point[ ]>([]); // Đồng bộ hóa dữ liệu điểm để đảm bảo rằng bạn luôn nhận được dữ liệu mới nhất useState không đồng bộ và không thể lấy được trong khoảng thời gian const pointRef = useRef(points); useEffect(() => { pointRef.current = point; }, [points]); const setDataToDom = (imgData: Uint8ClampedArray, w: number, h: number) => { const pointArr: { x: number; ;r: số [] = []; const num = Math.round(w / 10); for (let i = 0; i < w; i += num) { for (let j = 0; j < h; j += num) { const chỉ mục = (i + j * w) * 4 + 3; if (imgData[index] > 150) { pointArr.push({ x: i, y: j, r: Math.random() * data.pointSizeMin + 12 }); } } } const newPoints = pointArr.map((item, i) => { const opacity = Math.random() * 0,4 + 0,1; điểm const: Point = { quấnStyle: { left: item.x * data.scale, top: item.y * data.scale }, style: { chiều rộng: item.r * data.scale, chiều cao: item.r * data.scale, độ mờ: độ mờ, nềnColor: `rgb(${Math.round(Math.random() * 95 + 160)}, 255, 255)`, }, hoạt hình: { y: (Math.random() * 2 - 1) * 10 || 5 || 2.5, độ trễ: Math.random() * 1000, lặp lại: -1, thời lượng: 3000, dễ dàng: "easeInOutQuad", }, }; điểm trả về; }); delay(() => { setPoints(newPoints); }, initAnimateTime + 150); intervalRef.current = Ticker.interval(updateTweenData, intervalTime }; = () => { const { w, h } = dữ liệu const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); if (!ctx) trả về; ctx.clearRect(0, 0, w, h); ); img.crossOrigin = "ẩn danh"; img.src = data.image; img.onload = () => { ctx.drawImage(img, 0, 0); dữ liệu const = ctx.getImageData(0, 0, w, h).data; setDataToDom(data, w, h }); useEffect(() => { createPointData(); return () => { RemoveInterval(); }; }, []); // dữ liệu phân tán const phân tánData = () => { if (!logoBoxRef.current || !logoBoxRef.current.parentElement) trả về; const reg = logoBoxRef.current.parentElement.getBoundingClientRect(); const boxRect = logoBoxRef.current.getBoundingClientRect(); const boxTop = boxRect.top - rect.top; const boxLeft = boxRect.left - rect.left; const newPoints = cloneDeep(pointsRef.current).map((item) => ({ ...item, hoạt ảnh: { x: Math.random() * rect.width - boxLeft - item.wrapStyle.left, y: Math.random() * rect.height - boxTop - item.wrapStyle.top, độ mờ: Math.random() * 0,2 + 0,1, tỷ lệ: Math.random() * 2,4 + 0,1, thời lượng: Math.random() * 500 + 500, ease: "easeInOutQuint", }, })); setPoints(newPoints); }; // Mô tả dữ liệu const gatherData = () => { const newPoints = cloneDeep(pointsRef.current).map((item) => ({ ...item, animation: { x: 0, y: 0, opacity: Math.random() * 0.2 + 0.1, scale: 1, delay: Math.random() * 500, duration: 800, ease: "easeInOutQuint", }, })); setPoints(newPoints); }; const updateTweenData = () => { gatherRef.current ? disperseData() : gatherData(); gatherRef.current = !gatherRef.current; }; const removeInterval = () => { if (intervalRef.current) { Ticker.clear(intervalRef.current); intervalRef.current = null; } }; const onMouseEnter = () => { if (!gatherRef.current) { updateTweenData(); } removeInterval(); }; const onMouseLeave = () => { if (gatherRef.current) { updateTweenData(); } intervalRef.current = Ticker.interval(updateTweenData, intervalTime); }; trả về ( <> {points.length === 0 ? (    ) : (  {points.map((item, i) => (    ))}  )}  ); }; xuất khẩu mặc định logoAnimate;hiện tại; }; const removeInterval = () => { nếu (intervalRef.current) { Ticker.clear(intervalRef.current); intervalRef.current = null; } }; const onMouseEnter = () => { nếu (!gatherRef.current) { updateTweenData(); } removeInterval(); }; const onMouseLeave = () => { nếu (gatherRef.current) { updateTweenData(); } intervalRef.current = Ticker.interval(updateTweenData, intervalTime); }; trả về ( <> {points.length === 0 ? (    ) : (  {points.map((item, i) => (    ))}  )}  ); }; xuất khẩu mặc định logoAnimate;hiện tại; }; const removeInterval = () => { nếu (intervalRef.current) { Ticker.clear(intervalRef.current); intervalRef.current = null; } }; const onMouseEnter = () => { nếu (!gatherRef.current) { updateTweenData(); } removeInterval(); }; const onMouseLeave = () => { nếu (gatherRef.current) { updateTweenData(); } intervalRef.current = Ticker.interval(updateTweenData, intervalTime); }; trả về ( <> {points.length === 0 ? (    ) : (  {points.map((item, i) => (    ))}  )}  ); }; xuất khẩu mặc định logoAnimate;

                        
                      

Cuối cùng, bài viết về tái cấu trúc: tổng hợp logo và hoạt ảnh phân tán trong biểu ngữ kết thúc ở đây. Nếu bạn muốn biết thêm về tái cấu trúc: tổng hợp logo và hoạt ảnh phân tán trong biểu ngữ, vui lòng tìm kiếm bài viết CFSDN hoặc tiếp tục duyệt qua các bài viết liên quan. sẽ ủng hộ blog của tôi trong tương lai! .

35 4 0
tôi là một con chim nhỏ
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress