일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 |
- 그럼에도불구하고
- coding
- react
- frontend
- node.js
- media query
- cleancode
- HTML
- CSS
- max-width
- java
- TypeScript
- react-router-dom
- 그럼에도 불구하고
- 코딩테스트
- github
- JS
- 자바문제풀이
- Servlet
- node
- redux
- 프론트엔드
- git
- 자바
- 변수
- @media
- 반응형 페이지
- webpack
- 코드업
- JavaScript
- Today
- Total
그럼에도 불구하고
Drag & Drop 이용하여 이미지 올리기 본문
Drag & Drop 이용하여 이미지를 올려보자
HTML
<!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>Document</title>
<link rel="stylesheet" href="./style.css">
<script src="main2.js" defer></script>
</head>
<body>
<div class="file-zone">
이미지를 올려주세요
</div>
<div class="file-preview-area">
<h1>업로드한 이미지</h1>
<div class="image-list">
</div>
</div>
</body>
</html>
CSS
body {
display: block;
overflow: scroll;
width: 100%;
height: 100vh;
}
.file-zone {
background-color: rgba(0, 0, 0, 0.1);
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: calc(100% - 400px);
transition: 0.1s all ease-out;
}
.file-zone.on {
background-color: rgba(97, 131, 209, 0.9);
}
.file-preview-area {
width: 100%;
min-height: 400px;
background-color: rgba(0, 0, 0, 0.58);
overflow: hidden;
}
.file-preview-area .image-list {
display: grid;
overflow: scroll;
gap: 10px;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 400px;
}
.file-preview-area .image-list>img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
JavaScript
const fileZone = document.querySelector('.file-zone');
const className = 'on';
fileZone.addEventListener('dragover', (event) => {
event.preventDefault();
fileZone.classList.add(className);
})
fileZone.addEventListener('dragleave', (event) => {
event.preventDefault();
fileZone.classList.remove(className);
})
fileZone.addEventListener('drop', (event) => {
event.preventDefault();
fileZone.classList.remove(className);
const transferdFiles = event.dataTransfer.files;
displayImages(transferdFiles);
})
function displayImages(transferdFiles) {
const imageFileList = [];
const fileNum = transferdFiles.length;
for (let i = 0; i < fileNum; i++) {
if (transferdFiles[i].type.match('image.*') === false) {
return;
}
imageFileList.push(transferdFiles[i]);
}
const imagePreviewArea = document.querySelector('.image-list');
for (let imageFile of imageFileList) {
const fileReader = new FileReader();
fileReader.readAsDataURL(imageFile);
fileReader.addEventListener('load', (event) => {
const image = new Image();
image.src = event.target.result;
imagePreviewArea.insertBefore(image, imagePreviewArea.firstChild);
});
}
}
const fileZone = document.querySelector('.file-zone');
const className = 'on';
fileZone.addEventListener('dragover', (event) => {
event.preventDefault();
fileZone.classList.add(className);
})
fileZone.addEventListener('dragleave', (event) => {
event.preventDefault();
fileZone.classList.remove(className);
})
on 이라는 클래스를 이용하여 이미지가 dragover과 dragleave 됐을 때의 시각적인 효과를 부여한다.
※ dragover
※ dragleave
# event.preventDefault()
event.preventDefault()를 사용하여 해당 이벤트의 기본동작을 실행하지 않게 만든다.
event.preventDefault()를 사용하지 않는 경우
이미지를 dragover, dragleave, drop 하게 되면
자동적으로 내가 올린 이미지를 새로운 창으로 띄우게 된다. 이것을 preventDefault 메서드를 통해 막는 것이다.
fileZone.addEventListener('drop', (event) => {
event.preventDefault();
fileZone.classList.remove(className);
const transferdFiles = event.dataTransfer.files;
displayImages(transferdFiles);
})
transferdFileds 라는 변수는 drop 된 image 파일의 정보를 가져오기 위해 dataTransfer.files를 사용한다.
# event.dataTransfer.files
dataTransfer.files는 drag 작업을 할 때 사용한다. dataTransfer 객체의 파일 속성은 drag 해 온 작업의 파일 목록을 말하며, drag에 파일이 포함되어 있지 않으면 목록이 비어있게 된다.
이 기능은 사용자의 데스크톱에서 브라우저로 파일을 드래그할 때 사용할 수 있다.
REF: https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/files
drag & drop 기능을 사용할 경우 유용하게 사용할 수 있으니 꼭 알아두자 :)
그후에 displayImages()라는 함수에 transferdFiles를 인자로 넘기게 된다.
function displayImages(transferdFiles) {
const imageFileList = [];
const fileNum = transferdFiles.length;
for (let i = 0; i < fileNum; i++) {
if (transferdFiles[i].type.match('image.*') === false) {
return;
}
imageFileList.push(transferdFiles[i]);
}
const imagePreviewArea = document.querySelector('.image-list');
for (let imageFile of imageFileList) {
const fileReader = new FileReader();
fileReader.readAsDataURL(imageFile);
fileReader.addEventListener('load', (event) => {
const image = new Image();
image.src = event.target.result;
imagePreviewArea.insertBefore(image, imagePreviewArea.firstChild);
});
}
}
내가 drop 한 image를 받기 위하여 imageFileList라는 변수를 배열로 선언한다.
const fileNum = transferdFiles.length;
for (let i = 0; i < fileNum; i++) {
if (transferdFiles[i].type.match('image.*') === false) {
return;
}
imageFileList.push(transferdFiles[i]);
}
받아온 file의 개수만큼 for문을 돌리고, 받아온 파일의 파일 양식이 image 파일일 때만 imageFileList에 저장한다.
const imagePreviewArea = document.querySelector('.image-list');
for (let imageFile of imageFileList) {
const fileReader = new FileReader();
fileReader.readAsDataURL(imageFile);
fileReader.addEventListener('load', (event) => {
const image = new Image();
image.src = event.target.result;
imagePreviewArea.insertBefore(image, imagePreviewArea.firstChild);
});
}
}
저장된 file 수만큼 다시 for문으로 반복하여 imageFile의 URL값으로 image의 경로를 생성해 준다.
https://despiteallthat.tistory.com/92
.image-list 클래스를 가진 div 태그에 (imagePreviewArea) image를 넣은 순서대로 삽입해 준다.
여기서 .insertBefore()메서드를 이용하면 참조된 노드 앞에 특정 부모 노드의 자식 노드를 삽입할 수 있다.
즉 image 태그 ( 자식 노드 )를 imagePreviewArea ( 부모 노드 )에 삽입하는 것이다.
REF: https://developer.mozilla.org/ko/docs/Web/API/Node/insertBefore
'JavaScript > Function implementation' 카테고리의 다른 글
배경색 무작위 조작하기 (0) | 2023.02.02 |
---|---|
숫자 뽑기 게임 (0) | 2023.01.31 |
"selectstart" 글자 돋보기 만들기 (0) | 2023.01.10 |
아날로그 시계 만들기 (0) | 2023.01.07 |
mousemove 이벤트로 색 변환하기 (0) | 2023.01.06 |