Đã đăng vào thg 10 21, 2019 2:31 SA 3 phút đọc 3 phút đọc
Giới thiệu
Gần đây, chúng tôi đã làm việc trong một dự án liên quan đến hình tròn, hình thu nhỏ tròn, nút tròn, container tròn,... Trong bài viết hôm nay mình sẽ chia sẻ cho các bạn các cách tạo hình tròn bằng CSS. Nếu các bạn đang gặp phải vấn đề về tạo hình tròn trong CSS thì đây sẽ là bài viết hữu ích dành cho bạn.
Có một số kỹ thuật để xác định hình dạng tròn động trong HTML và CSS, mỗi cái có ưu và nhược điểm riêng. Dưới đây là một số cách tôi đã thử nghiệm nhiều nhất, từ phổ biến nhất đến ít dùng nhất.
Border radius
Kỹ thuật phổ biến nhất là làm tròn tất cả các góc bằng cách set
6, có thể được style tương tự như bất kỳ cách nào khác. Chúng được hỗ trợ rất tốt và thực hiện để animate, nhưng chúng đòi hỏi nhiều markup hơn các kỹ thuật khác. Để ngăn việc cắt hình ảnh trực quan, hãy đảm bảo bán kính hình tròn (cộng với một nửa chiều rộng của nó, nếu có) nhỏ hơn một chút so với
Đường dẫn clip là một kỹ thuật mới hơn. Hỗ trợ là tốt nhưng ít nhất quán. Clip Path không ảnh hưởng đến bố cục yếu tố, có nghĩa là chúng sẽ không ảnh hưởng đến
1 để lấp đầy trực quan một phần tử bằng một vòng tròn. Bất kỳ nội dung nào cũng sẽ nằm trên cùng của hình dạng đó, nhưng bố cục của nó sẽ không bị ảnh hưởng. Đây là kỹ thuật yêu thích ít nhất của tôi vì các cạnh của hình tròn có thể xuất hiện lởm chởm hoặc mờ tùy theo trình duyệt, nhưng nó có thể phù hợp với các điểm nhấn nền tinh tế.
Qua bài viết này mình đã giúp các bạn tìm hiểu các cách tạo hình tròn bằng CSS. Mình hy vọng nó sẽ có ích cho bạn.
Bài viết tham khảo: CSS Circles
All rights reserved
.
Ở bài này, mình sẽ giới thiệu cơ bản về SVG, cách vẽ SVG đơn giản, và cuối cùng là giới thiệu tool render SVG cho nhanh =))
Giới thiệu SVG
SVG là viết tắt của Scalable Vector Graphics, đúng như tên gọi, nó cấu tạo là các vector.
Hiểu đơn giản, hình ảnh thông thường được cấu tạo từ các pixel là các ô vuông, khi bạn zoom lên thì các pixel hiển thị to ra, các ô vuông to lên và hình của bạn trông giống hình game 8 bit vậy. Còn hình ảnh vector nó là các "đường" có hướng, kiểu như nối đường nối giữa 2 điểm, nên dù phóng to cũng ko bị vỡ ra bit.
Với hình ảnh định dạng SVG, thì nó tốn ít "chỗ" hơn, sử dụng cho các icon trên web nhẹ hơn nhiều so với việc load ảnh bình thường (à trừ khi là ảnh SVG của bạn vô cùng phức tạp nhé, thì dùng 1 file png optimize và giảm chất lượng ảnh còn hơn), nhất là khi muốn co kéo mà không bị giảm chất lượng hình ảnh, giống như 180p và full HD vậy
Hình ảnh bit map và ảnh vector khi nhìn qua không khác nhau
Nhưng khi phóng to thì ảnh bitmap bị vỡ, còn ảnh vector thì không
Mọi người cũng có thể xem thêm bài giới thiệu này: https://viblo.asia/p/tim-hieu-ve-svg-gAm5yqd85db
Vẽ với SVG
Các thẻ tag
Trong các thẻ SVG, có thể có nhiều thẻ con, list các thẻ con khá dài, bạn có thể xem chi tiết tất cả tại https://developer.mozilla.org/en-US/docs/Web/SVG/Element (thực ra mình cũng chưa thể tìm hiểu hết đám này). Ở đây mình sẽ giới thiệu 1 số thẻ tạo hình dạng (shape) như sau:
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
0. Mọi người có thể search thêm về hình elip để tập vẽ nhé
<svg>
<circle cx="50" cy="50" r="50" stroke="red" fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
1
Thẻ vẽ đường thẳng. Và để vẽ đường thẳng thì cần biết vị trí điểm đầu và vị trí điểm cuối, nên là sẽ có 4 param ở đây:
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
2,
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
3 là tọa độ x, y của điểm bắt đầu, và
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
4,
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
5 là tọa độ của điểm kết thúc.
<svg>
<circle cx="50" cy="50" r="50" stroke="red" fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
6
Thẻ vẽ hình đa giác. Với thẻ này, bạn sẽ định nghĩa các điểm là các đỉnh của đa giác, và sẽ nối các điểm theo thứ tự bạn viết và sau đó sẽ tự động nối điểm cuối cùng về điểm đầu để tạo 1 hình khép kín.
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
7 chính là danh sách các cặp tọa độ của mỗi đỉnh đa giác.
<svg>
<circle cx="50" cy="50" r="50" stroke="red" fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
8
Thẻ vẽ đường thẳng gãy khúc. Thẻ này sẽ định nghĩa các cặp tọa độ của các điểm, rồi nối các điểm với nhau bằng đường thẳng theo thứ tự. Nó không khác polygon là mấy, trừ việc nó không nối điểm cuối với điểm đầu .
<svg>
<circle cx="50" cy="50" r="50" stroke="red" fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
9
Vẽ hình chữ nhật. Với thẻ này, ngoài việc vẽ hình chữ nhật 4 góc nhọn thông thường, thì còn có thể bo góc cho hình nữa:
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
0 là chiều cao của đường bo tròn. Mọi người tham khảo hình minh họa phía dưới để hình dung rõ hơn nhé:
Thẻ vẽ đường. Đây là thẻ linh hoạt nhất, có thể vẽ mọi thứ bằng thẻ này, giống như dùng tay vẽ vậy. Và tất nhiên, nếu biết cách sử dụng thì hoàn toàn có thể dùng thẻ này để vẽ các hình trên, nhưng mà sẽ ko đơn giản như dùng trực tiếp thẻ như vậy . Chính vì sự linh động này, đây là thẻ phức tạp nhất để tìm hiểu. Mình đã nhiều lần từ bỏ trong lúc tìm hiểu vì quá đau đầu, mà các tài liệu tìm đọc thì đọc 1 hồi rối hết lên nên drop mấy lần rồi . Giờ mới quyết tâm quay lại và tìm được vài tài liệu dễ hiểu hơn.
. Chính vì sự linh động này, đây là thẻ phức tạp nhất để tìm hiểu. Mình đã nhiều lần từ bỏ trong lúc tìm hiểu vì quá đau đầu, mà các tài liệu tìm đọc thì đọc 1 hồi rối hết lên nên drop mấy lần rồi
. Giờ mới quyết tâm quay lại và tìm được vài tài liệu dễ hiểu hơn.
<svg><circlecx="50"cy="50"r="50"stroke="red"fill="none"/> //stroke để tô màu cho đường, không có nó lại 'invisible' mọi người bảo mình hướng dẫn linh tinh :D
</svg>
5 này có các phần tử con chính như sau (lưu ý là đây vẫn là 1 đường liền, tức là điểm trước nối điểm sau, vẽ không nhấc bút cho tới điểm cuối cùng nhé: end point thằng trước là start point vẽ thằng sau):
M - move to: Đây là điểm bắt đầu đặt bút vẽ, đi kèm theo sau là cặp tọa độ của điểm đặt bút này.
3. Sử dụng để xác định cung tròn có 2 điểm bắt đầu và kết thúc là vị trí nào trên hình elip, cũng có thể hiểu là xoay hình elip các kiểu, và nó cắt trục Ox tại 2 điểm start point và end point khi quay được bao nhiêu độ. (Tất nhiên đơn vị là đơn vị đo góc: độ).
Cặp tham số tiếp theo: Quyết định vẽ cung tròn to hay cung tròn nhỏ của đường elip, vẽ cung lồi hay cung lõm. Mỗi tham số sẽ nhận 2 giá trị: 0 hoặc 1. Tham số thứ 1: 'Large arc sweep flag'. Có nghĩa là chọn vẽ cung lớn hay cung nhỏ: 0 là chọn lấy cung nhỏ, 1 là chọn lấy cung lớn. Tham số thứ 2: 'Sweep flag'. Tham số này để chọn cung sẽ 'lồi' hay 'lõm' - hay có thể hình dung là phần nhiều diện tích hình elip sẽ ở trên hay ở dưới: 0 là elip có phần lớn 'chìm', còn 1 là elip với phần lớn hơn 'nổi lên'.
Cặp tham số cuối: xác định điểm cuối của elip. Điểm đầu của elip được xác định bằng điểm kết thúc của hình vẽ trước đó, nên điểm cuối elip này cũng sẽ là điểm bắt đầu vẽ của hình tiếp theo.
Q: Vẽ đường cong bậc 2 - Quadratic Bezier Curves. Đường này dùng để nối 2 điểm 1 cách "smooth" khi có 1 tiêu điểm. Với Q, bạn sẽ xác định 2 param: cặp tham số đầu tiên là tọa độ tiêu điểm, cặp tham số thứ 2 là tọa độ end point của hình vẽ. Với tiêu điểm được xác định và 2 điểm start point, end point, ta sẽ vẽ được 2 đường thẳng cắt nhau tại tiêu điểm. Để giải thích bằng lời thì khá dài dòng, mọi người hãy đọc thêm bài http://www.svgbasics.com/curves.html để hiểu về đường Quadratic Bezier Curves này nhé. Ngoài ra thì có thể đọc thêm bài này và thực hành luôn (rất có ích cho việc tìm hiểu phần tử C tiếp theo đây): http://apex.infogridpacific.com/SVG/svg-tutorial-lesson18-path-quadratics.html
Khi 2 control point nằm trên 1 đường thẳng, thì đường C tạo thành cũng là 1 đường thẳng.
Đường C có 3 cặp tham số: Cặp đầu tiên là tọa độ Control point của start point, cặp tiếp theo là tọa độ control point của end point, cuối cùng là tọa độ end point
Để sử dụng đường C khá là phức tạp, cần phải xác định các điểm gần chính xác, nên nếu bạn nào có khả năng sử dụng pen tool vẽ hình trong đồ họa thì có thể tự vẽ được, còn nếu không thì ... mò vậy
Dưới đây là hình mình vẽ sử dụng pen tool của Adobe Illustrator vẽ theo hướng dẫn tạo control point như hình con sóc kia, nhân tiện kẻ lưới để dễ xác định point vẽ lại bằng svg (1 ô nhỏ = 5px, 1 ô lớn = 70px)
Và đây là thành quả sau khi phân tích tọa độ các điểm: https://codepen.io/bunnypi04/pen/jObqxRX
(Mình đã vẽ thêm grid bằng JS cho mọi người dễ hình dung và xác định tọa độ)
5 - data là có thể vẽ mọi hình rồi nên mình sẽ chỉ giới thiệu các thẻ tới đây thôi. (Theo kinh nghiệm vẽ rất nhiều hình bằng Adobe Illustrator của mình thì mình nói thế ))
Tổng hợp các Path Command
Dưới đây là danh sách các command để vẽ dành cho path data. Mỗi command được ký hiệu bởi 1 chữ cái, và theo sau là các bộ tham số. Các chữ cái viết hoa sẽ diễn giải tọa độ theo hệ tọa độ xOy thông thường (tức là tính từ góc trên cùng bên trái của đối tượng SVG bao nó là gốc tọa độ - Vị trí tuyệt đối), còn chữ cái viết thường sẽ có chức năng command tương tự nhưng với diễn giải tọa độ với gốc tọa độ là điểm endPoint ngay trước đó (vị trí tương đối). Giả sử so với gốc tọa độ O của đối tượng SVG: điểm M có tọa độ 5, 5; điểm N có tọa độ 15,15; thì vị trí tuyệt đối của N là 15, 15 (vì so với gốc tọa độ); còn vị trí tương đối của N khi M là điểm start Point của nó là 10, 10.
Command
Params
Tên
Thông tin
M
x,y
move to
Di chuyển tới điểm x,y mà ko vẽ line
m
x,y
move to
Di chuyển tới điểm x,y mà ko vẽ line
m
x,y
move to
Di chuyển tới điểm x,y mà ko vẽ line
m
x,y
move to
Di chuyển tới điểm x,y mà ko vẽ line
m
Cũng như trên nhưng x,y có gốc tọa độ điểm dừng bút trước đó
L
line to
Vẽ 1 đường thẳng tới điểm x,y
Cũng như trên nhưng x,y có gốc tọa độ điểm dừng bút trước đó
L
line to
Vẽ 1 đường thẳng tới điểm x,y
l (L nhỏ, không phải i in hoa nhé)
Cũng là vẽ 1 đường thẳng nhưng điểm x,y x,y có gốc tọa độ là điểm dừng bút trước đó
H
x
l (L nhỏ, không phải i in hoa nhé)
Cũng là vẽ 1 đường thẳng nhưng điểm x,y x,y có gốc tọa độ là điểm dừng bút trước đó
H
x
horizontal line to
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x
h
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x-params nhưng gốc tọa độ là điểm dừng bút trước đó
horizontal line to
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x
h
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x-params nhưng gốc tọa độ là điểm dừng bút trước đó
V
y
vertical line to
Vẽ 1 đường thẳng dọc từ điểm dừng bút trước đó (song song với Oy ấy) tới giao điểm với đường thẳng x = y-params
V
y
h
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x-params nhưng gốc tọa độ là điểm dừng bút trước đó
V
y
vertical line to
Vẽ 1 đường thẳng dọc từ điểm dừng bút trước đó (song song với Oy ấy) tới giao điểm với đường thẳng x = y-params
V
y
h
Vẽ 1 đường thẳng ngang từ điểm dừng bút trước đó (song song với Ox ấy) tới giao điểm với đường thẳng y = x-params nhưng gốc tọa độ là điểm dừng bút trước đó
x,y
move to
Di chuyển tới điểm x,y mà ko vẽ line
m
x,y
move to
h
A
rx,ry x-axis-rotation large-arc-flag, sweepflag x, y
elliptical arc
Vẽ đường cong elip với điểm kết thúc đường là (x, y), với rx, ry lần lượt là chiều dài và chiều rộng elip, x-axis-rotation là độ nghiêng so với hình gốc, large-arc-flag là chọn đường cong lớn/nhỏ, sweepflag để chọn mặt phẳng chứa đường cong
a
rx,ry x-axis-rotation large-arc-flag, sweepflag x, y
elliptical arc
Vẽ đường cong elip với điểm kết thúc đường là (x, y), với rx, ry lần lượt là chiều dài và chiều rộng elip, x-axis-rotation là độ nghiêng so với hình gốc, large-arc-flag là chọn đường cong lớn/nhỏ, sweepflag để chọn mặt phẳng chứa đường cong
a
Như trên nhưng gốc tọa độ là điểm dừng bút trước đó
Z
no param
closepath
Như trên nhưng gốc tọa độ là điểm dừng bút trước đó
Z
no param
closepath
đóng đường vẽ lại bằng cách nối thẳng về điểm đầu tiên của path, tạo 1 hình khép kín
z
Cũng thế chả khác gì cả
Thử thực hành
Mình có tìm được 1 link code pen khá hữu ích cho việc hiểu hơn về các thành phần L, C, Q, A ở trên, mọi người vào đây thử nhé: https://codepen.io/anthonydugois/pen/mewdyZ
1 số thuộc tính thường dùng của SVG
Toàn bộ các thuộc tính của SVG thì dài lắm, mọi người có thể xem bản đầy đủ tại đây. Dưới đây mình sẽ giới thiệu 1 số thuộc tính thường dùng
Stroke
Stroke là thuộc tính về đườg vẽ line của bạn. Có các thuộc tính stroke như sau:
2: Hình dạng góc gấp khúc. VD: https://jsfiddle.net/api/mdn/
<svg>
<rect x="120" y="60" width="200" height="100" rx="15" />
</svg>
3: Nét đứt. Tạo nét đứt với các param lần lượt là độ dài nét, tiếp theo là độ dài khoảng trắng tiếp, cứ lặp lại như vậy. VD: https://www.w3schools.com/graphics/tryit.asp?filename=trysvg_stroke3
7, SVG sẽ quy định giới hạn cho bạn nhìn thấy cái gì trên ảnh SVG này. VD bạn có 1 ảnh SVG mẫu, nó khá nhiều chi tiết nhưng bạn chỉ muốn dùng 1 chi tiết nhỏ trên đó, mà lại ngại ngồi phân tích điểm để xóa các chi tiết thừa (hoặc là ảnh SVG phức tạp thì mò bục mặt), vậy thì bạn chỉ cần tìm vị trí điểm đó so với ảnh SVG gốc, giới hạn khung chữ nhật đó hiện ra thôi, "ẩn" hết các thứ ngoài box đó. Ứng dụng phổ biến nhất chính là SVG Sprites: 1 bộ icon vẽ bằng SVG trên 1 tấm SVG, rồi các icon sẽ là view box chỉ hiện 1 icon tương ứng, các cái còn lại ẩn hết. Nhờ vậy mà web chỉ cần load 1 tấm ảnh SVG và sử dụng cho tất cả các icon thay vì mỗi icon load 1 tấm ảnh..
Sau khi tìm hiểu kha khá về SVG (tất nhiên là chưa đủ hết được ), thì chỉ với nhiêu đó thì có thể quay trở lại mục đích ban đầu, đấy là hiệu ứng vẽ chữ, và tất nhiên hiệu ứng không dùng JS .
8 trên kia mình vẽ dùng toàn nét cơ bản, sử dụng line, đường cung nửa hình tròn, hình tròn. Kết quả có hình SVG như sau:. Do mình muốn hiệu ứng cho mỗi chữ cái, nên tất các các thẻ đường vẽ con đều chung css hiệu ứng vẽ luôn:
02 để tạo ra nét chữ và "nét trong suốt". Như vậy, hiệu ứng vẽ kia thực ra là các dash chạy qua chữ thôi.
. Ngoài ra thì vì vector bảo toàn độ nét, mà lại nhẹ hơn ảnh thường nên SVG cũng được dùng thay thế các hình ảnh đơn giản để giảm tải cho trang web (trừ trường hợp ảnh phức tạp như mình bảo ngay đầu bài nhé). 1 số người như mình thì thích tối thiểu js, mà thích mấy thứ hay ho như vẽ chữ kia thì cũng dùng cái này làm cho trang web trông ngầu hơn, mà lại không tải nặng chi chít js hay video hình ảnh.
Có 1 vài công cụ render SVG mình search được tại đây. Mặc dù không perfect, nhưng mà có thể dùng làm công cụ để thuần thục vẽ SVG này. Ngoài ra bạn cũng có thể export các hình ảnh thường ra SVG bằng các Graphic tool nữa đấy, tuy nhiên là khi đó vector sẽ không bảo toàn nét tuyệt đối như khi vẽ tay được . 1 cách để lấy code SVG từ 1 ảnh SVG bất kỳ đấy là mở file SVG ảnh bằng trình soạn thảo code, bạn sẽ nhậ được đoạn code của file SVG đó, hình ảnh vốn mang tính vector thì sẽ cho ra file SVG chính xác nhất.
. 1 cách để lấy code SVG từ 1
ảnh SVG bất kỳ đấy là mở file SVG ảnh bằng trình soạn thảo code, bạn sẽ nhậ được đoạn code của file SVG đó, hình ảnh vốn mang tính vector thì sẽ cho ra file SVG chính xác nhất.
Hy vọng bài viết đạt được mục đích "hiểu svg dễ dàng hơn" cho nhiều bạn mới tìm hiểu SVG