Thứ Ba, 5 tháng 1, 2016

Cơ Bản Vẽ Trên Canvas 2D Với HTML5

Cơ Bản Vẽ Trên Canvas 2D Với HTML5 :: Bài viết :: STDIO

Giới thiệu

Vào năm 2012, W3C giới thiệu HTML5, trước đó chúng ta sử dụng phiên bản HTML4. HTML5 ra đời thêm nhiều tính năng giúp tiện dụng hơn trong việc tạo ra các văn bản web sinh động và có nhiều lựa chọn hơn. Có nhiều tag hay tính năng mới ra đời như <article> nhằm "nói" với trình duyệt rằng đây là khối chứa nội dung bài viết, hoặc <audio> hỗ trợ chơi một số file nhạc (tức là trình duyệt web cần phải cài thêm các plug-in rời để chơi các file âm thanh nữa. Các bạn có thể tham khảo thêm trên trang chủ W3C.

Về đồ họa, tuyệt vời nhất đối với tôi có thể kể đến tag <canvas>, với tag Canvas hỗ trợ 2 loại vẽ bao gồm 2D getContext("2d") và 3D getContext("experimental-webGL"). Trong bài viết này tôi sẽ giới thiệu cơ bản về vẽ 2D với Canvas.

Bài viết này sẽ bao gồm sơ lược việc tạo đối tượng vẽ và vẽ các đường nét, hình chữ nhật, đường tròn và vẽ một ảnh có sẵn lên Canvas.

Tiền đề bài viết

Việc tìm hiểu về HTML5 của tôi đã diễn ra cách đây 2 năm, lúc mà HTML5 vừa mới được giới thiệu. Sau một thời gian dài, tôi tìm kiếm các tài liệu giảng dạy cũ và tìm ra được các bài thuyết trình mà tôi đã vô tình bỏ quên trong một thư mục trong ổ cứng mình.

Đối tượng hướng đến

Trước khi HTML5 và Canvas ra đời, thông thường các lập trình viên muốn tạo ra các hiệu ứng đẹp trên trình duyệt, ta có thể nghĩ đến Flash (ActionScript), Silverlight, Java Applet (Java) và dĩ nhiên phải cài đặt thêm các plug-in cần thiết cho trình duyệt web để trình duyệt có thể vận hành các tài liệu này.

Với tiêu chuẩn mới của HTML5 và Canvas, bạn có thể sử dụng thuần JavaScript để vẽ và tạo hiệu ứng cho website của mình mà không cần phải dùng thêm các plug-in khác.

Môi trường thử nghiệm

Tất cả các trình duyệt web mới nhất tại thời điểm hiện tại đã hỗ trợ tốt cho Canvas và HTML5. Tuy nhiên, nếu cần thiết bạn có thể tham khảo thêm ở W3C để biết đặt tính riêng của từng trình duyệt.

Demo

DOWNLOAD STDIO_PROJECT_1.ZIP

Bạn có thể xem trực tiếp demo bên dưới nhưng bạn nên download mã nguồn về để tiện xem phần phân tích code bên dưới

Phân tích và giải thích codes

Toàn bộ mã nguồn đều nằm trong file index.htm, javascript cũng được in-line trong tài liệu này.

Để có thể bắt đầu vẽ ta cần tạo 1 thẻ Canvas trong tài liệu html. Ta có đoạn sau

<canvas id="STDIO_canvas_49" width=600 height=450 >
	YOUR BROWSER DOES NOT SUPPORT HTML5 CANVAS
</canvas>

Các phép vẽ sẽ được vẽ trong thẻ canvas này và ta đặt 1 id là STDIO_canvas_49, id này dùng cho javascript để lấy được canvas thông qua hàm getElementById của javascript.

Xem xét hàm vẽ STDIO_DrawCanvas(_id)

Xem xét hàm vẽ STDIO_DrawCanvas(_id)

Trong hàm này có 2 phần chính, phần thứ nhất là lấy đối tượng vẽ "context" của canvas, phần thứ 2 là vẽ các hình đơn giản để bạn có thể tham khảo các hàm vẽ cơ bản.

Tạo "context"

Trong đoạn này tôi getContext("2d") vì chỉ muốn thao tác vẽ 2d, sau bước này ta có đối tượng để vẽ là STDIO_context

var STDIO_canvas = document.getElementById(_id);
var STDIO_context = STDIO_canvas.getContext("2d");

document.getElementById mà trong trường hợp này _id chính là STDIO_canvas_49 mà tôi đã gọi và truyền vào hàm vẽ lúc nhấn vào button DRAW (xem đoạn gọi hàm vẽ tại
<button onclick="javascript:STDIO_DrawCanvas('STDIO_canvas_49')">DRAW</button>

Các phương thức vẽ cơ bản

// FILL RECTANGLE
STDIO_context.fillStyle = "#ff8800";
STDIO_context.fillRect(0 + wonder1, 0 + wonder4, 150, 75);

// DRAW RECTANGLE
STDIO_context.strokeStyle = "#000000";
STDIO_context.strokeRect(50 + wonder2, 50 + wonder3, 120, 75);

// DRAW A LINE
STDIO_context.strokeStyle = "#00aadd";
STDIO_context.moveTo(100 + wonder3, 200 + wonder2);
STDIO_context.lineTo(250 + wonder3, 250 + wonder2);
STDIO_context.stroke();

// DRAW CIRCLE
STDIO_context.beginPath();
STDIO_context.arc(250 + wonder4, 50, 40, 0, 2*Math.PI);
STDIO_context.stroke();

// FILL CIRCLE
STDIO_context.fillStyle = "#ffbb33";
STDIO_context.beginPath();
STDIO_context.arc(300 + wonder1, 300 + wonder4, 30, 0, 2*Math.PI);
STDIO_context.fill();

// DRAW TEXT
STDIO_context.strokeStyle = "#ffbb33";
STDIO_context.font = "30px Arial";
STDIO_context.strokeText("www.stdio.vn", 10 + wonder2, 300 + wonder3);

// FILL TEXT
STDIO_context.fillStyle = "#aa0000";
STDIO_context.font = "25px Arial";
STDIO_context.fillText("Kevin La", 300 + wonder3, 250 + wonder2);

// DRAW IMAGE
var STDIO_image = new Image();
STDIO_image.src = "img_sins_heart.png";
STDIO_image.onload = function()
{
	STDIO_context.drawImage(STDIO_image, 200 + wonder2, 100 + wonder3);
}

Các phương thức vẽ có trong demo

Các phương thức vẽ cơ bản có khá nhiều, bạn có thể tham khảo thêm trên W3C, ở đây tôi giới thiệu việc vẽ

  • Vẽ hình chữ nhật // FILL RECTANGLE
  • Đường viền xung quanh hình chữ nhật // DRAW RECTANGLE
  • Vẽ một đoạn thẳng // DRAW A LINE
  • Vẽ một đường tròn // DRAW CIRCLE
  • Vẽ một hình tròn // FILL CIRCLE
  • Vẽ đường viền cũng quanh chữ // DRAW TEXT
  • Vẽ chữ // FILL TEXT
  • Vẽ một hình có sẵn // DRAW IMAGE

Khái niệm stroke và fill

Vẽ các hình này ta cần phân biệt 2 khái niệm cơ bản:

  • stroke - vẽ đường viền xung quanh hình học đó
  • fill - vẽ và tô phần "ruột" của hình học đó

Như đã đề cập ở bước trước STDIO_context nắm toàn bộ thuộc tính và phương thức vẽ trên Canvas 2D nên ta sẽ dùng đối tượng này để tinh chỉnh thuộc tính và tiến hành vẽ.

STDIO_context.fillStyle là chỉ định màu muốn dành cho việc fill.
STDIO_context.strokeStyle là chỉ định màu muốn dành cho việc stroke.

Khảo sát đoạn // DRAW CIRCLE các bạn thấy tôi "stroke" 1 đường tròn nhưng không thực hiện bước này STDIO_context.strokeStyle như các việc "stroke" LINE trước đó vậy màu của việc stroke circle sẽ là màu gì? Ta thấy rằng trước khi vẽ đường tròn thì ở bước gần nhất là vẽ đường thẳng ta đã chỉ định STDIO_context.strokeStyle = "#00aadd" cho việc vẽ LINE mà thuộc tính này chưa được thay đổi, nên hiện tại nó vẫn dùng màu này (màu xanh dương cho việc vẽ đường tròn - và vẽ line trước đó).

Vẽ một hình đã có sẵn - Image

Ta lưu ý, để vẽ một hình ảnh thì đầu tiên ta phải nạp Image (hình) đó, lúc này Image đang ở nơi lưu trữ (hosting) và ta cần download về và nạp vào bộ nhớ.

var STDIO_image = new Image();
STDIO_image.src = "img_sins_heart.png";

Tạo 1 đối tượng Image, sau đó chỉ định đường dẫn tới ảnh mà ta cần download và nạp. Sau bước này, ta có thể gọi hàm vẽ ngay

STDIO_context.drawImage(STDIO_image, 200 + wonder2, 100 + wonder3);

Như vậy ta sẽ có được 3 dòng code sau để nạp và vẽ ảnh

var STDIO_image = new Image();
STDIO_image.src = "img_sins_heart.png";
STDIO_context.drawImage(STDIO_image, 200 + wonder2, 100 + wonder3);

Tuy nhiên, không như ta mong đợi, ta phải biết rằng, khi tiến hành gán STDIO_image.src = "img_sins_heart.png"; thì lúc này trình duyệt mới tiến hành download và nạp ảnh và chắc chắn rằng dường như không kịp hoàn tất để bước sau là bước STDIO_context.drawImage(STDIO_image, 200 + wonder2, 100 + wonder3); có dữ liệu để vẽ được, ta cần phải đợi cho đến khi ảnh đã nạp xong thì mới tiến hành vẽ. Do đó, tôi sẽ đưa hàm này vào hàm onload (hàm onload là hàm được gọi sau khi ảnh đã load xong).

// DRAW IMAGE
var STDIO_image = new Image();
STDIO_image.src = "img_sins_heart.png";
STDIO_image.onload = function()
{
	STDIO_context.drawImage(STDIO_image, 200 + wonder2, 100 + wonder3);
}

Lời kết

Đối với các bạn chưa thao tác với javascript nhiều có thể sẽ lạ với đoạn STDIO_image.onload = function(){} các bạn có thể xem nó như bạn đang truyền một địa chỉ hàm vào "con trỏ hàm" onload, và đây cũng là sự kết hợp với Anonymous Function đoạn function() { // BLOCK STATEMENT }

Do tôi không chuyên về web development, nên nếu có sơ sót, vui lòng gửi feedback, tôi sẽ sớm cập nhật nhằm cung cấp bài viết chất lượng cao hơn.

THẢO LUẬN
Đăng nhập để cùng nhau thảo luận. Đăng ký ngay nếu bạn chưa có tài khoản.
GỬI
ĐĂNG NHẬP
*Sử dụng BUGS để chia sẻ mã nguồn trong bình luận
NỘI DUNG BÀI VIẾT

0 nhận xét: