- vừa được xem lúc

Code Weekly Downloads Chart trên npmjs.com

0 0 48

Người đăng: Phan Quang Hiếu

Theo Viblo Asia

Mở đầu ?

Là một lập trình viên Web chắc hẳn ai cũng biết đến và từng truy cập website npmjs.com để khám phá, tìm hiểu (lấy link install ?) các thư viện Javascript. Và mỗi lần truy cập mình điều thấy khá thích thú với biểu đồ Weekly Downloads, vậy nên mình sẽ cùng với các bạn tìm hiểu cách tạo ra một component tương tự nhé ?

Công nghệ mình dùng cho project là ReactJS và SVG


Nội dung

Data

data = [ { downloads: 111154, label: '2020-07-12 to 2020-07-18', }, { downloads: 111834, label: '2020-07-19 to 2020-07-25', }, ...
]

Mình sử dụng định dạng data như trên, đấy cũng là dạng dữ liệu mà mà component của npmjs.com sử dụng (nhưng mình tìm toét cả mắt ở tag Network thì không thấy responce nào trả về như thế ? ai tìm được chỉ mình với nha)

Phần biểu đồ tim tím

const WIDTH = 500
const HEIGHT = 100
// ... <svg width={WIDTH} height={HEIGHT}> <path d={pathD1} fill='none'></path> <path d={pathD2} stroke='none'></path> <line x1={pointSelected.x} x2={pointSelected.x} y1={0} y2={HEIGHT}></line> <circle cx={pointSelected.x} cy={pointSelected.y}></circle> <rect width={WIDTH} height={HEIGHT} onMouseMove={handleMouseMove} onMouseOut={handleMouseOut} ></rect> </svg>
// ...

Bên trong thẻ svg mình dùng một số thẻ nữa với chức năng như sau

  • thẻ path đầu tiên để vẽ đường xanh tím này
  • thẻ path thứ high để vẽ hình tím tím này
  • thẻ linecircle để vẽ hình này khi ta hover trên biểu đồ
  • còn thẻ rect để ta bắt sự kiện onMouseMoveonMouseOut khi hover chuột để xem chi tiết lượt download của từng tuần

Path & Path

Phần quan trọng nhất là làm sao chúng ta có thể tính được pathD để vẽ được biểu đồ trên bằng dữ liệu bên trên. Mỗi tuần mình sẽ cho là 1 điểm có tọa độ x , y , số lượt downloads, và label là thời gian tuần đó {x, y, downloads, label} .Đầu tiên chúng ta sẽ tính toán tọa độ các điểm:

const WIDTH = 500
const HEIGHT = 100 const { min, max } = findMinMax(data) // tìm giá trị download min và max (findMinMax là mình tự viết) const deltaX = WIDTH / (data.length - 1) // tính khoảng cách theo trục X giữa 2 điểm  const deltaY = 60 / (max - min) // ở đây chiều cao chart của mình là 100px mình muốn tuần có 
//lượt download lớn nhất ở tọa độ Y 0 tuần có lượt download thấp nhất ở tọa độ Y 60 
//nên mình tính deltaY theo từng lượt download như trên //đây là phầm tính tọa độ các điểm
let points = []
for (const [index, value] of data.entries()) { points.push({ x: index * deltaX, y: (max - value.downloads) * deltaY + 8, // tất cả +8 để cho đẹp chút thôi downloads: value.downloads, label: value.label, })
}

Tiếp theo ta sẽ tính biến pathD. ở đây mình dùng attribute d của thẻ path, nó sẽ bao gồm một dãy các kí tự trong đó có một chữ cái đi kèm tọa độ x y. Ở đây mình dùng những kí tự đơn giản sau (khó mình không biết ?)

  • M 20 40 : luôn bắt đầu với M để di chuyển bút vẽ đến tọa {20,40}
  • L 40 60 : vẽ 1 đường thẳng từ điểm trước đó của bút đến tọa độ {40,60}
  • Z : đóng lại đường đã vẽ thành một hình (màu trong hình được định nghĩa bằng attribute fill)
let pathD = `M ${points[0].x} ${points[0].y} `
for (const point of points) { pathD += `L ${point.x} ${point.y} `
}
const pathD1 = pathD
const pathD2 = `${pathD} L ${WIDTH} ${HEIGHT} L 0 ${HEIGHT} Z`

Vậy là phần khó đã xong (style mình sẽ để riêng 1 file scss sau)

Bắt sự kiện Mouse và show thông tin chi tiết

//...
const defaultPoint = { // giá trị mặc định của điểm là không hiển thị trên svg x: -1000, y: -1000, downloads: data[data.length - 1].downloads, label: 'Weekly Downloads',
} function Chart() { const [pointSelected, setPointSelected] = useState(defaultPoint) const handleMouseMove = (e) => { let index = Math.round(e.nativeEvent.offsetX / deltaX) // xác định tọa độ theo trục X chuột đang di chuyển trên để tìm point setPointSelected(points[index]) } const handleMouseOut = (e) => { setPointSelected(defaultPoint) } return ( <div className='chart__container'> <h1>{pointSelected.label}</h1> <div className='content'> <div className='num'>{Intl.NumberFormat().format(pointSelected.downloads)}</div> // format lượt download dạng ###,###,### <div className='chart'> <svg width={WIDTH} height={HEIGHT}> <path d={pathD1} fill='none'></path> <path d={pathD2} stroke='none'></path> <line x1={pointSelected.x} x2={pointSelected.x} y1={0} y2={HEIGHT}></line> <circle cx={pointSelected.x} cy={pointSelected.y}></circle> // các thuộc tính x1,x2 của line, cx, cy, r của circle các bạn tự tìm hiểu thêm nha <rect width={WIDTH} height={HEIGHT} onMouseMove={handleMouseMove} onMouseOut={handleMouseOut} ></rect> </svg> </div> </div> </div> )
}

Vậy là được rồi đấy các bạn ?

Đây là phần demo


Kết luận

Đây là bài viểt debut của mình, có gì sai sót mong các bạn, các anh chị góp ý

Hi vọng với chút chia sẻ này sẽ giúp đỡ được mọi người, đặc biệt là các bạn mới để cộng đồng DEV Việt Nam ngày càng phát triển! ?

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 496

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 413

- vừa được xem lúc

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 134

- vừa được xem lúc

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 117

- vừa được xem lúc

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 93

- vừa được xem lúc

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 228