Xin chào các bạn,

Trong bài này mình sẽ hướng dẫn các bạn cách ghép hình bằng Canvas trong HTML5, cụ thể ở đây mình ghép khung vào hình mà mình chọn từ máy lên. Các bạn có thể xem demo ở đây.

Ý tưởng ghép khung vào hình

Ý tưởng cơ bản là mình vẽ lần lượt hai hình lên canvas, sau đó di chuyển, phóng to thu nhỏ hay xoay hình rồi cho tải về là xong. Rất đơn giản phải không?

Vẽ khung hình

Trong file html, các bạn thêm các thẻ <canvas>, <input><img> như sau:

Trong đó,

  • Thẻ canvas để mình sử dụng vẽ hình.
  • Thẻ img dùng để chứa hình mà mình tải lên.

Tiếp theo, các bạn tạo file js để code một số xử lý hình ảnh.

Mình lấy các đối tượng trong HTML như image, canvascontext và tạo các biến cơ bản. Sau đó tạo đối tượng frame là khung hình muốn ghép.

Ở hàm onload của frame, mình vẽ khung hình lên context.

Ban đầu đơn giản chỉ xóa canvas rồi vẽ frame hình lên trước, các bạn có thể xem thêm hàm drawImage(), clearRect()

Load hình

Tiếp theo mình sẽ load hình lên.

Trong file HTML các bạn thêm thẻ input để up hình.

Viết sự kiện change cho input.

Khi hình được load lên, mình sử dụng FileReader để đọc dữ liệu từ input và cập nhật lại source hình từ dữ liệu đó cho đối tượng userImage.

Ở hàm onload của userImage, mình sẽ tìm cạnh nhỏ nhất để scale hình cho vừa với khung. Và lưu giá trị vào minScale để giới hạn giá trị scale. (mình thích không cho người ta scale nhỏ hơn canvas thôi).

Giờ mình có hình rồi nên ta cập nhật thêm cho hàm drawCurrentImage()

Các bạn save() context hiện tại trước khi thay đổi để vẽ userImage, rồi nhớ restore() để trả về mặc định cho context trước khi vẽ cái khác.

Để vẽ theo tâm của hình (origin là tâm của hình), mình dùng cách translate() chuyển hình đến tọa độ mong muốn. Sau đó khi vẽ bằng drawImage(), ta vẽ lùi về một nữa kích thước ngang, dọc của hình.

Và mình dùng rotate(), scale() để gán các giá trị tương ứng cho context.

Di chuyển

Ý tưởng: mỗi khi chuột di chuyển mình sẽ tính toán độ thay đổi của chuột so với lần trước rồi cập nhật lại vị trí của hình.

Các bạn thêm các biến như bên dưới và các sự kiện mousedown, mousemove, mouseup, mouseout cho canvas.

Ở sự kiện cho mousemove, ta cập nhật vị trí hiện tại của hình với độ thay đổi của chuột. Các sự kiện mouseup, mousedownmouseout để xác định trạng thái kéo thả hình.

Mình thêm giới hạn cho tọa đổ để không kéo hình lệch xa quá, chỉ cho nó vừa khung và di chuyển hết hình thôi.

Các bạn thêm vào hàm drawCurrentImage(), mình tính phần dư của hình so với canvas, phần này sẽ là giới hạn di chuyển của tọa độ. Nếu tọa độ thấp hơn hoặc lớn hơn thì mình không cho phép vượt qua.

Thay đổi giá trị scale

Với giá trị scale, ta thêm thanh input range để kéo thay đổi giá trị vào HTML như sau

Mỗi lần thay đổi giá trị, mình cập nhật lại imageScale với giá trị của scaleBar.

Thay đổi góc xoay

Để thay đổi góc xoay, các bạn thêm vào file HTML hai nút xoay trái/phải.

Mỗi lần bấm nút xoay hình, mình cộng / trừ góc xoay cho 90 độ, và đổi width, height của hình cho nhau. Sau đó là vẽ lại hình.

Tải hình

Để tải hình, mình gán sự kiện click cho nút download, dùng hàm toDataURL() để lấy dữ liệu của canvas và tải xuống.

Tổng kết

Vậy là xong các chức năng cơ bản của việc ghép khung vào hình, các bạn có thể phát triển thêm như là xoay hình, phóng to thu nhỏ, chọn frame… Còn lại là các thứ như là css lại giao diện theo ý các bạn thôi.

Full Source code của project.

Bài viết này mình cũng đang tìm hiểu về Javascript, nên nếu có gì sai sót các bạn có thể góp ý thêm nha. Bạn nào có sử dụng lại nhớ báo mình cho mình biết nhé.

Hẹn gặp lại các bạn.

Cập nhật

  • 3/10/2016: cập nhật scale hình ảnh
  • 11/2/2017: cập nhật xoay hình ảnh