Skip to main content

Framer Motion: Làm thế nào để vẽ một SVG?

00:08:20:70

Phần 1: Tổng quan về SVG

Trong hệ thống những thứ được sử dụng cho việc tạo animation không thể thiếu được bóng dáng của những thẻ svg.

SVG có thể thực hiện hiển thị hình ảnh với độ phân giải màn hình khác nhau, bên cạnh đó nó có thể sẽ được những hình, đường rất khó vẽ đối với việc sử dụng html, css thuần. Trong bài viết này tôi sẽ trình bày cơ bản các phần của một SVG và cách vẽ cơ bản của SVG.

SVG là gì?

SVG là tên viết tắt của cụm từ Scalable Vector Graphics. Nó là một dạng ngôn ngữ XML được sử dụng với mục đích miêu tả các hình ảnh đồ họa vector 2 chiều, hoạt hình và tĩnh. Bình thường chúng ta có thể hiểu svg là một loại dạng hình ảnh. Chúng khác những dạng hình ảnh khác là sử dụng định dạng XML để hiển thị hình ảnh dưới dạng vector, dùng những điểm được định nghĩa để vẽ hình ảnh mà chúng ta nhìn thấy.

Ưu điểm của SVG

Sở hữu kích thước nhỏ: hình ảnh dạnh vector, bitmap nên chúng ta có thể hiển thị, co dãn ảnh thoải mái mà không bị vỡ

Hỗ trợ đầy đủ ở tất cả các trình duyệt phổ biến

Animation: Tất cả các thuộc tính của SVG đều có thể animate được. Chúng ta có thể sử dụng một SVG duy nhất kết hợp với css và javascript để làm animation cho từng thành phần, nó làm giảm bớt dung lượng của web và làm cho web của chúng ta load cực kỳ nhanh.

Một ví dụ về svg

html
<svg width="200" height="200" viewBox="-100 -100 200 200">
    <g transform="translate(0 5)">
      <g>
        <polygon points="0,0 36,-50 0,-100" fill="#EDD8B7" />
        <polygon points="0,0 -36,-50 0,-100" fill="#E5C39C" />
      </g>
      <g transform="rotate(72)">
        <polygon points="0,0 36,-50 0,-100" fill="#EDD8B7" />
        <polygon points="0,0 -36,-50 0,-100" fill="#E5C39C" />
      </g>
      <g transform="rotate(-72)">
        <polygon points="0,0 36,-50 0,-100" fill="#EDD8B7" />
        <polygon points="0,0 -36,-50 0,-100" fill="#E5C39C" />
      </g>
      <g transform="rotate(144)">
        <polygon points="0,0 36,-50 0,-100" fill="#EDD8B7" />
        <polygon points="0,0 -36,-50 0,-100" fill="#E5C39C" />
      </g>
      <g transform="rotate(-144)">
        <polygon points="0,0 36,-50 0,-100" fill="#EDD8B7" />
        <polygon points="0,0 -36,-50 0,-100" fill="#E5C39C" />
      </g>
    </g>
  </svg>

Kết quả thực tế

Các thuộc tính của SVG

  • height: xác định chiều cao của svg trong hệ tọa độ người dùng. Tham khảo thêm tại link

  • width: xác định chiều rộng của svg trong hệ tọa độ ngưởi dùng. Tham khảo thêm tại link

  • preserveAspectRatio: cho biết cách một phần tử đã có viewBox cung cấp một tỉ lệ khung hình như thế nào so với tỉ lệ khung hình phần tử cha của nó.

    Syntax: preserveAspectRatio="align meetOrSlice" Alignment value(prop: align):

    • none: không bắt buộc tỉ lệ khung hình đồng nhất. meetOrSlice sẽ không có tác dụng.
    • xMinYMin: x nhỏ nhất và y nhỏ nhất viewPort
    • xMidYMin: trung điểm của viewPort trục x của phần tử trùng với trung điểm trục x của viewPort svg. vị trí y nhỏ nhất
    • xMaxYMin: giá trị vị trí x = min-x + width, y nhỏ nhất viewPort
    • xMinYMid: tương tự như những align trên, x nhỏ nhất, trung điểm của viewPort trục y của phần tử trùng với trung điểm trục y của viewPort svg.
    • xMidYMid
    • xMaxYMid
    • xMinYMax
    • xMidYMax
    • xMaxYMax
  • viewBox: xác định vị trí và kích thước trong không gian người dùng giá trị của viewBox gồm danh sách gồm 4 số: min-x, min-y, width, height. Các số được phân cách với nhau bởi dấu cách hoặc dấy phẩy. Ví dụ:

    html
    <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    </svg>
    
  • x: tọa độ x của svg trong vùng chứa của svg xác định bằng viewPort

  • y: tọa độ y của svg trong vùng chứa của svg xác định bằng viewPort

xMidYMid meetxMinYMid meetxMaxYMid meetxMidYMin slicexMidYMid slicexMidYMax slicexMidYMin meetxMidYMid meetxMidYMax meetxMinYMid slicexMidYMid slicexMaxYMid slicenone

Có một số thuộc tính không được khuyến nghị (not recommended) sẽ không được trình bày ở đây

Các thành phần của SVG

Ở đây tôi sẽ đi qua một số thành phần thông dụng nhất. Độc giả có thể tham khảo thêm tại link

  • <circle>: là một hình dạng cơ bản của svg, sử dụng để vẽ đường tròn dựa trên tâm và bán kinh:
html
  <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="50" />
  </svg>
  • <clipPath>: đường cắt hạn chế vùng có thể vẽ. Nó định nghĩa 1 đường trong svg và bên trong đường cắt đó sẽ được vẽ còn bên ngoài đường cắt thì không. Ví dụ:
html
<svg viewBox='0 0 100 100' height={100} width={100}>
        <clipPath id='myClip' className={styles.myClip}>
          <circle cx='40' cy='35' r='35' />
        </clipPath>

        <path
          id='heart'
          d='M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z' />

        <use clipPath='url(#myClip)' href='#heart' fill='red' />
      </svg>
css
@keyframes openYourHeart {
  from {
    r: 0;
  }
  to {
    r: 60px;
  }
}

.myClip circle {
  animation: openYourHeart 15s infinite;
}

.containerClipPath {
  padding: 10px;
  width: 100%;
  display: flex;
  justify-content: center;
}

Ở đây mọi người nhìn ví dụ rất dễ hiểu thôi, văn thì nó hơi dài dòng một chút.

  • <defs>: lưu trữ các đối tượng đồ họa được sử dụng sau này (khai báo trước). Các đối tượng được tạo bên trong <defs> không được hiển thị trực tiếp. Để hiển thị chúng, bạn phải tham chiếu đến chúng, thường tôi sử dụng <use>

    Ví dụ:

html
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg" height={100} width={100}>
    <defs>
      <circle id="myCircle" cx="0" cy="0" r="5"/>

      <linearGradient id="myGradient" gradientTransform="rotate(90)">
        <stop offset="20%" stop-color="gold" />
        <stop offset="90%" stop-color="red" />
      </linearGradient>
    </defs>

    <use x="5" y="5" href="#myCircle" fill="url('#myGradient')"/>
  </svg>
  • <g>: phần tử này dùng để nhóm các svg/ thành phần svg lại với nhau. Ví dụ:
html
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" height={100} width={100}>
    <g fill="white" stroke="yellow" stroke-width="5">
      <circle cx="40" cy="40" r="25" />
      <circle cx="60" cy="60" r="30" />
    </g>
</svg>
  • <image>: chắc hẳn mọi người nhìn đều hiểu tag này để làm gì rồi, nó dùng để hiện thị các hình ảnh raster image hoặc các tệp svg khác.

    Ví dụ:

html
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
  <image href="https://i.ibb.co/x3XQFn9/Webp-net-resizeimage.jpg" height="200" width="200" />
</svg>
  • <line>: tạo một đường thẳng nối 2 điểm.

Ví dụ:

html
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" height={100} width={100}>
  <line x1="0" y1="20" x2="100" y2="80" stroke="black" />
</svg>
  • <linearGradient>: phần tử cho phép có thể tạo ra 1 linear gradient dưới dạng svg

Ví dụ:

html
<svg
  viewBox="0 0 100 100"
  height={100} width={100}
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <linearGradient id="myGradient" gradientTransform="rotate(90)">
      <stop offset="5%" stop-color="gold" />
      <stop offset="95%" stop-color="red" />
    </linearGradient>
  </defs>

  <circle cx="5" cy="5" r="4" fill="url('#myGradient')" />
</svg>
  • <path>: là phần tử chung để xác định một hình dạng svg. Tất cả các hình dạng cơ bản của svg đề có thể được tạo ra từ path

    Sơ lược về thuộc tính của path:

    • d: xác định hình dạng của path. Tham khảo thêm tại link
    • pathLength: xác định chiều dài của path theo đơn vị người dùng (user unit)

    Ví dụ:

html
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path
    d="M 10,30
           A 20,20 0,0,1 50,30
           A 20,20 0,0,1 90,30
           Q 90,60 50,90
           Q 10,60 10,30 z" />
</svg>

Định nghĩa phần thuộc tính d trong path này cũng khá phức tạp, tôi xin phép không trình bày tại đây, mọi người có thể tham khảo thêm tại link

  • <rect>: thẻ này tương tự với <circle>, khác ở chỗ nó vẽ ra một hình chữ nhật.

    Ví dụ:

html
<svg viewBox="0 0 220 100" xmlns="http://www.w3.org/2000/svg" fill='blue' height='100' width='220'>
  <rect width="100" height="100" />
  <rect x="120" width="100" height="100" rx="15" />
</svg>

Ở đây tôi tổng hợp một số thẻ tôi hay dùng trong svg, mọi người có thể tham khảo thêm ở link

Vậy là chúng ta đã đi qua và hiểu thêm một chút về thành phần cũng như các cấu tạo của SVG. Ở bài viết tiếp theo, tôi sẽ đi vào các mà framer motion tạo ra một SVG, cũng như các sử dụng chúng để tạo một animation. Mời các bạn đón đọc.

Framer Motion: Làm thế nào để vẽ một SVG phần 2?
Upcoming
Bài viết này hướng dẫn các sử dụng các phần tử framer motion để tạo một animation với SVG
arrow-right