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

Vanilla JS: Preview image when drag and drop

0 0 103

Người đăng: kentrung

Theo Viblo Asia

1. Yêu cầu

Yêu cầu bài toán là khi người dùng kéo thả ảnh từ máy tính vào vùng chỉ định thì chúng ta sẽ hiển thị hình ảnh preview để xem trước mà không cần phải upload lên server. Đây là một trong những bài tập vanilla Javascript ở mức cơ bản giúp các bạn làm quen, chủ yếu giải thích về Javascript nên phần giao diện sẽ không phân tích nhiều. Hi vọng với bài tập này các bạn sẽ thấy thích thú khi học Javascript.

2. HTML - CSS

<!DOCTYPE html>
<html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vanilla JS: Preview image when drag and drop</title> <!-- bootstrap 4.5.0 --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" /> <style> #dnd {height: 100px;display: flex;align-items: center;justify-content: center;margin: 0 auto 2rem;border: 2px dashed #ccc;} .drag-over {border-color: red !important;color: red;} .preview-img {max-width: 150px;margin: 0 1em 1em 0;padding: 0.5em;border: 1px solid #ccc; border-radius: 3px;} </style>
</head>
<body> <div class="container"> <h2 class="my-5 text-center">Preview image when drag and drop</h2> <div id="dnd"> <span>Drag and drop file here to preview</span> </div> <div class="preview"></div> </div> <script> // code javascript </script>
</body>
</html>

3. Hướng giải quyết chính

  • Lắng nghe sự thay đổi (dragover hoặc dragleave) của div#dnd, ngăn chặn hành vi xử lý mặc định của trình duyệt
  • Lắng nghe sự thay đổi (drop file) của div#dnd, khi người dùng kéo file và thả vào đó, lấy ra thông tin các file thông qua DragEvent - dataTransfer
  • Kiểm tra đúng định dạng là ảnh
  • Sử dụng FileReader để đọc file
  • Hiển thị preview image

4. Javascript

Step 1: Lắng nghe sự thay đổi (dragover hoặc dragleave) của div#dnd, ngăn chặn hành vi xử lý mặc định của trình duyệt, khi drag trên vùng chọn thì thêm chút hiệu ứng như border và chữ thành màu đỏ.

const dndElement = document.querySelector('#dnd') dndElement.addEventListener('dragover', function(e) { e.preventDefault() this.classList.add('drag-over')
}) dndElement.addEventListener('dragleave', function(e) { e.preventDefault() this.classList.remove('drag-over')
})

Step 2: Lắng nghe sự thay đổi (drop file) của div#dnd, ngăn chặn hành vi xử lý mặc định của trình duyệt, lấy ra thông tin các file

dndElement.addEventListener('drop', function(e) { e.preventDefault() const files = e.dataTransfer.files; for (var i = 0; i < files.length; i++) { const file = files[i] console.log(111, file) }
})

Ta thu được kết quả log khi thả 2 file ảnh vào

Trong đối tượng File ta có thể lấy các thông tin cơ bản của file như:

  • name: tên file
  • size: kích thước file (có thể dùng để giới hạn kích thước).
  • type: định dạng file (có thể dùng để validate có đúng là ảnh hay không).

Step 3: Tương ứng mỗi file sẽ gọi hàm renderPreviewImage, trong hàm này kiểm tra phải là định dạng ảnh, nếu không đúng thì thông báo lỗi

const validImageTypes = ['image/gif', 'image/jpeg', 'image/png'] dndElement.addEventListener('drop', function(e) { e.preventDefault() const files = e.dataTransfer.files; for (var i = 0; i < files.length; i++) { const file = files[i] renderPreviewImage(file) }
}) function renderPreviewImage(file) { const fileType = file['type'] if (!validImageTypes.includes(fileType)) { resultElement.insertAdjacentHTML( 'beforeend', '<span class="preview-img">Chọn ảnh đi :3</span>' ) return }
}

Step 4: Nếu đúng định dạng là ảnh thì tiếp tục sử dụng FileReader để đọc file ảnh được chọn ở trên

function renderPreviewImage(file) { ... const fileReader = new FileReader() fileReader.readAsDataURL(file)
}

Step 5: Sử dụng FileReader onload để xử lý khi quá trình đọc file hoàn thành, chèn ảnh vào khu vực hiển thị

function renderPreviewImage(file) { ... const fileReader = new FileReader() fileReader.readAsDataURL(file) fileReader.onload = function() { const url = fileReader.result resultElement.insertAdjacentHTML( 'beforeend', `<img src="${url}" alt="${file.name}" class="preview-img" />` ) }
}

Dưới đây là toàn bộ code JS

const dndElement = document.querySelector('#dnd')
const resultElement = document.querySelector('.preview')
const validImageTypes = ['image/gif', 'image/jpeg', 'image/png'] dndElement.addEventListener('dragover', function(e) { e.preventDefault() this.classList.add('drag-over')
}) dndElement.addEventListener('dragleave', function(e) { e.preventDefault() this.classList.remove('drag-over')
}) dndElement.addEventListener('drop', function(e) { e.preventDefault() this.classList.remove('drag-over') const files = e.dataTransfer.files; for (var i = 0; i < files.length; i++) { const file = files[i] renderPreviewImage(file) }
}) function renderPreviewImage(file) { const fileType = file['type'] if (!validImageTypes.includes(fileType)) { resultElement.insertAdjacentHTML( 'beforeend', '<span class="preview-img">Chọn ảnh đi :3</span>' ) return } const fileReader = new FileReader() fileReader.readAsDataURL(file) fileReader.onload = function() { const url = fileReader.result resultElement.insertAdjacentHTML( 'beforeend', `<img src="${url}" alt="${file.name}" class="preview-img" />` ) }
}

5. Kết quả


Bài viết đến đây là hết, hi vọng với bài viết này các bạn đã thêm được nhiều kiến thức bổ ích. Hẹn gặp lại các bạn ở bài viết tiếp theo!

Bình luận

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

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

Một số quy tắc và name class phổ biến cho Front-end Dev

Trong CSS, các thủ tục setting đóng vai trò to lớn, nhưng bên cạnh đó, cách đặt tên theo các từ đơn sao cho phù hợp cũng quan trọng không kém . Đặt tên rất khó, nhưng cũng rất quan trọng .

0 0 93

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

2021, chúng ta cần tối ưu hóa việc tải hình ảnh trên web như nào?

Rất chào các bạn,. Như các bạn đã biết, trong kỉ nguyên công nghệ, song song với sự sinh ra dày đặc của các trang web mới cũng là sự biến mất của những trang web "lạc hậu" hay hoạt động kém hiệu quả.

0 0 57

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

Tài nguyên nghiên cứu sâu Html

1. Articles and standards. . HTML 5.

0 0 198

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

Tìm hiểu về Event.preventDefault(), Event.stopPropagation() và Event.stopImmediatePropagation()

Chúng ta thương thấy 3 method này và có thể dẫn dến bối rối và nhầm lẫn giữa chúng:. . Event.preventDefault().

0 0 52

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

Vanilla JS Project: Tính tuổi

1. Yêu cầu.

0 0 74

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

Thủ thuật nhỏ để căn chỉnh image với object-fit

Chào các bạn,. Có lẽ trong hành trình code của các bạn thì không ít lần gặp vấn đề méo ảnh do fix cứng cả width, height của ảnh nhỉ? Hoặc kể cả khi bạn set value cho 1 thuộc tính weigth hoặc height còn thuộc tính còn lại để auto thì nhiều lúc ảnh cũng không được hiển thị toàn vẹn cho lắm.

0 0 49