[드래그앤드롭]검색결과, 2건
블로그에서 드래그 앤 드롭을 다룬적이 있으며 다음의 글을 참고하자
=> [HTML5] 드래그 앤 드롭 (Drag & Drop)
이전 글에서 간단한 데모를 다뤘었는데, 동일한 페이지에 있는 select 박스간 항목의 이동이었다
이번에는 웹 페이지 외부에 있는 파일(이미지파일, 텍스트 파일)을 웹 페이지로 드래그 해서 놓는 실습을 해 보도록 하자
우선 먼저 참고할 사항은, 브라우저간 일관되지 않은 결과가 나타난다는 것이다
http://caniuse.com/ 사이트에 따르면 드래그 앤 드롭은 IE와 오페라를 제외한 크롬,사파리,파이어폭스에서 동작한다고 되어 있다. 그리고 이번 데모에서 사용할 HTML5 File API 역시 크롬,사파리,파이어폭스에서 동작한다고 되어 있다.
그러나 막상 테스트를 해 보면 조금씩 다른 결과를 보여주어 당혹스럽게 한다
HTML5 자체가 브라우저마다 조금씩 다르게 지원하거나 일부가 누락된 경우가 있다고는 하지만
드래그 앤 드롭에 있어서는 더욱 일관되지 못함을 볼 수 있다
어쨋던 이 글에서 만든 데모는 파이어폭스에서 정상 동작하며 크롬에서 동작시키기 위해서는 특정 API를 제거해야 한다. 데모를 보여준 후 추가로 언급하겠다
실습, 외부파일을 웹페이지로 끌어다 놓기
웹 페이지이 외부 즉 데스크탑에 있는 이미지 파일 혹은 텍스트 파일을 웹 페이지의 DIV 영역으로 끌어다 놓는 데모를 제작해 보자
드래그 앤 드롭에 대한 기술적 요소는 이전에 작성한 강좌를 참고하도록 하며,
추가로 사용된 HTML5 File API 는 데모를 통해 알아보도록 하자
데모를 간단히 설명하면 이미지를 드롭했을 때에는 페이지에 이미지가 표시되며 텍스트파일을 드롭했을 때에는 텍스트파일의 내용이 페이지에 표시되도록 한다
바로 전체 소스코드를 보도록 하자
<html>
<head>
<style>
#dropbox {
margin: auto;
width: 300px;
height: 300px;
border: 5px solid #3C2F2E;
-moz-border-radius: 15px;
margin-top: 30px;
}
</style>
</head>
<body>
<div id="dropbox" ondragenter="onDragEnter(event)" ondragover="onDragOver(event)"
ondrop="onDrop(event)">
</div>
</body>
</html>
<script type="text/javascript">
var dropBox = document.getElementById("dropbox");
var dropImage = document.createElement("img");
function onDragEnter(event){
if (event.dataTransfer.dropEffect == "move")
event.preventDefault();
}
function onDragOver(event){
if (event.dataTransfer.dropEffect == "move") {
event.preventDefault();
}
function onDrop(event){
var file = event.dataTransfer.files[0];
var imageType = /image.*/;
var textType = /text.*/;
var isImage;
if(file.type.match(imageType)){
isImage = true;
}
else if(file.type.match(textType)){
isImage = false;
}
var reader = new FileReader();
reader.onload = (function(aFile){return function(e) {
var result = e.target.result;
if(isImage){
dropImage.src = result;
dropBox.appendChild(dropImage)
}
else{
dropBox.innerHTML = result;
}
};
})(file);
if(isImage){ reader.readAsDataURL(file); }
else { reader.readAsText(file,"EUC-KR"); }
event.stopPropagation();
event.preventDefault();
}
dropImage.addEventListener("load", function(e) {
//이미지 로딩 시 추가 처리할 로직 기입(사이즈 조절 등)
}, true);
</script>
드롭 이벤트에서(onDrop)에서 외부 파일을 드롭했을 때 그 정보를 취득하기 위한
다음의 코드가 사용되며 event.dataTransfer.files[0],
이렇게 전달된 파일 데이터를 읽기 위해 FileReader(File API 중 파일을 읽기 위한 객체)를 사용했다
FileReader의 Load 이벤트에서 드롭으로 전달된 파일정보를 읽어 들여 이미지 혹은 텍스트를 DIV 에 출력하는 것이다
> 이미지 읽기: reader.readAsDataURL(file);
> 텍스트 읽기: reader.readAsText(file,"EUC-KR");
아래 그림은 데모를 실행한 결과모습인데, 텍스트 파일과 이미지 파일을 드롭한 후 또 다른 이미지 파일을 드롭하기 위해 웹페이지로 옮기는 모습니다. 전체 코드이기에 직접 실행해 보기 바란다.
소스나 기능이 최적화 되지는 않았지만 응용을 위한 기본자료로써는 충분할 것이다
우선 이 데모는 파이어폭스에서만 정상 동작한다
만일 크롬에서 동작시키려면 event.dataTransfer.dropEffect 속성을 사용해서는 안된다
아마도 크롬 브라우저는 dataTransfer 객체의 dropEffect 속성이 구현되지 않았나 보다
즉 onDragEnter 와 onDragOver 이벤트코드에서 if (event.dataTransfer.dropEffect == "move")
부분을 제거하거나 아래와 같이 두 이벤트를 무시하면 된다
ondragenter="return false;"
ondragover="return false;"
이로써 파이어폭스와 크롬에서 잘 동작하지만 사파리와 오페라는 여전히 동작하지 않는다
주제와 벗어나는 말이지만, HTML5의 드래그앤드롭과 File API 는 아직 실서비스에 적용하기에는 무리가 있지 않나 싶다
외부파일의 드래그 드롭은 아래 사이트를 참조하면 보다 유익한 정보를 얻을 수 있다
http://demos.hacks.mozilla.org/openweb/imageUploader/ (파이어폭스에서 실행해야 함)
http://hacks.mozilla.or.kr/2010/07/an-html5-offline-image-editor-and-uploader-application/
https://www.ibm.com/developerworks/mydeveloperworks/blogs/bobleah/entry/html5_code_example_of_file_api_drag_drop_hard_drive_files_to_a_webpage28?ca=dgr-jw22BobHTML5Tip1&lang=en
'모바일 > HTML5' 카테고리의 다른 글
Visual Studio 에서 HTML5 템플릿 만들기 (6) | 2010.09.28 |
---|---|
MS의 고뇌?, 실버라이트와 HTML5 (10) | 2010.09.16 |
[HTML5] LocalStorage 와 크로스브라우저 (10) | 2010.09.14 |
[CSS3] Animation (18) | 2010.09.13 |
[CSS3] Transform (10) | 2010.09.10 |
끌어다 놓기(드래그 앤 드롭, Drag & Drop)
끌어다 놓기는 사용자 편의성을 고려한 편리한 UI 기능이라 할 수 있는데,
아래 그림에서 보는 바와 같이 영역 A -> 영역 B로 특정 콘텐트를 마우스로 이동하는 것을 말한다
아래 그림은 구글 캘랜더에서 할일목록을 드래그 앤 드롭을 통해 다른 날짜로 이동하고 있는 모습이다
이러한 UI의 사용자 액션은 직관적이며 편리한 기능이다.
윈폼 닷넷과 같은 윈도우 응용프로그램에서는 드래그 앤 드롭과 관련된 API 가 이미 제공되고 있다
그러나 웹 환경에서는 지금까지 전용 API는 제공되지 않고 유사 구현을 위해 복잡한 자바스크립트
이벤트(mouse 관련 이벤트를 직접 구현함)를 다루어야 했다
HTML 5 의 Drag & Drop API
HTML 5 에는 드래그 앤 드롭을 위한 전용 API 가 제공된다
이 API는 기존 윈도우 응용프로그램의 드래그 앤 드롭 API와 개념적으로 상당히 유사하다
과거처럼 자바스크립트의 마우스 관련 이벤트와는 전혀 상관이 없으며
드래그 대상, 드롭 대상, 이동 콘텐트 등의 정보를 기반으로 동작한다
또한 웹 페이지 내 콘텐트의 이동 뿐만 아니라 웹 페이지 간, 웹 페이지와 다른 응용프로그램 간
드래그 앤 드롭이 가능하기 때문에 이전 웹 환경과는 완연히 구분되는 기능이라 할 수 있겠다
지원되는 브라우저 현황
아래 표는 http://caniuse.com/ 에서 제공하는 브라우저(버전)별 Drag & Drop 지원 표이다
(데스크탑 용 브라우저 기준이다)
위 표를 보면 파이어폭스, 사파리, 크롬은 지원한다고 나와 있는 반면,
막상 테스트를 해 보니 파이어폭스를 제외하고는 제대로 동작하지 않았다
(크롬, 사파리 최선 버전 브라우저에서 Drag & Drop 정상 동작 하지 않음)
(표에서는 지원된다고 나와 있으니 조금 더 확인이 필요 할 것 같다)
그리고 아이폰의 사파리도 지원하지 않는 것으로 보인다
아이폰 사파리 브라우저에서 테스트를 해 봤지만 전혀 동작하지 않았다
Drag & Drop API
대부분의 HTML 5 스크립트 API들은 고도로 추상화 되었기 때문에 매우 사용하기가 쉽다
드래그 앤 드롭 API 역시 이용하는 데 어려움이 없으며 기존 윈도우 응용프로그램의 API 개념과
상당부분 유사하다. 드래그 앤 드롭 API 이해를 위해서는 다음의 것들을 이해하면 된다
- 드래그 대상(Source)
드래그 대상은 말 그대로 끌어올 것에 해당한다.
HTML 요소에 draggable 속성 값을 true로 설정하면 드래그 대상이 될 수 있다
- 드롭 대상(Target)
드롭 대상은 말 그대로 끌어다 놓을 곳에 해당한다
HTML 요소들의 기본 값은 드롭을 받아 들이지 않게 되어 있다
따라서 드롭이 가능하도록 설정하려면 이벤트의 preventDefault() 함수로 기본 값을 취소해야 한다
- 드래그 데이터(Data)
드래그 데이터는 말 그대로 이동할 대상 콘텐트에 해당한다.
이동할 데이터는 DataTransfer 객체를 통해 이루어 지는데
드래그 대상에서 이 객체에 값을 저장하고 드롭 대상에서 이 객체의 값을 꺼내어 오는 방식이다
- 드롭 이벤트들
드래그 앤 드롭과 관련해 총 7가지 이벤트가 존재한다
이 이벤트들은 드래그 앤 드롭 과정에서 (거의) 순차적으로 발생하며 드래그,드롭 대상에서
자신에게 맞는 이벤트 처리를 해 주면 된다
: dragstart 이벤트
드래그 대상에서 정의해야 하는 이벤트 이다
드래그가 시작될 때 발생하며 드래그 대상에서는 이 이벤트를 수신하여 이동할 데이터를 DataTransfer 객체에 채우게 된다
: dragenter 이벤트
드롭 대상에서 정의해야 하는 이벤트이다
이동할 데이터를 마우스로 끌어서 드롭 대상에 들어 오는 순간 발생한다
: dragover 이벤트
드롭 대상에서 정의해야 하는 이벤트이다
이동할 데이터를 마우스로 끌어서 드롭 대상에 올려 놓는 동안 계속해서 발생하는 이벤트이다
: drop 이벤트
드롭 대상에서 정의해야 하는 이벤트이다
마우스로 끌어서 놓는 순간 발생한다. 드롭 대상에서는 이 이벤트르 수신하여
DataTransfer 객체로부터 데이터를 꺼내 오고 드롭 대상에 끼워 넣는 작업을 하게 된다
이외에도 drag 이벤트, dragleave 이벤트, dragend 이벤트 등이 추가로 존재하지만
위에 설명한 4가지 이벤트로 기본적인 드래그 & 드롭 구현이 가능하다
Drag & Drop 데모 만들어 보기
이제 간단한 드래그 앤 드롭 데모를 만들어 보자
문서 내에서 select 박스 간 데이터를 이동하는 예제이다
(아래 코드는 시라이시 슌페이의 HTML5 & API 입문 책의 소스코드를 기반으로 했음을 밝힌다)
<html>
<head>
<script type="text/javascript">
function onDragStart(event){
document.getElementById("msg").innerHTML += "onDragStart->";
//드래그 대상 요소가 option 일 경우에만 가능토록 함
if(event.target.tagName.toLowerCase() == "option"){
//dataTransfer 객체에 이동할 요소의 ID를 "selectOption"라는 이름으로 등록함
event.dataTransfer.setData("selectOption", event.target.id);
}
else{
//만일 드래그 대상 요소가 option이 아닐 경우 취소함
event.preventDefault();
}
}
function onDragEnter(event){
document.getElementById("msg").innerHTML += "onDragEnter->";
//드래그 대상이 selectOption 일 경우에만 드롭 가능토록 설정함
var types = event.dataTransfer.types;
for(var i = 0; i < types.length; i++){
if(types[i] == "selectOption"){
event.preventDefault();
return;
}
}
}
function onDragOver(event){
document.getElementById("msg").innerHTML += "onDragOver->";
//드롭이 가능하도록 기본 상태를 취소함
event.preventDefault();
}
function onDrop(event){
document.getElementById("msg").innerHTML += "onDrop";
//dataTransfer 객체로 부터 데이터를 꺼내옴
var id = event.dataTransfer.getData("selectOption");
//현재 문서객체에서 해당 요소를 가져옴
var optionElement = document.getElementById(id);
//데이터가 존재하고 드래그 대상과 드롭 대상이 같지 않을 경우 드롭 실행
if(optionElement && optionElement.parentNode != event.currentTarget){
optionElement.parentNode.removeChild(optionElement);
//드롭 대상에 데이터 추가
event.currentTarget.appendChild(optionElement);
}
//드롭 완료 후 이벤트 버블링을 막기 위해 호출
event.stopPropagation();
}
</script>
</head>
<body>
<!-- 드래그 대상 요소 -->
<select size= 4 id="select1" ondragstart="onDragStart(event)">
<option id="option1_1" draggable="true">옵션1-1</option> <!-- 드래그 데이터 -->
<option id="option1_2" draggable="true">옵션1-2</option> <!-- 드래그 데이터 -->
<option id="option1_3" draggable="true">옵션1-3</option> <!-- 드래그 데이터 -->
</select>
<!-- 드롭 대상 요소 -->
<select size= 4 id="select2"
ondragenter="onDragEnter(event)"
ondragover="onDragOver(event)"
ondrop="onDrop(event)">
<option id="option2_1">옵션2-1</option>
<option id="option2_2">옵션2-2</option>
<option id="option2_3">옵션2-3</option>
</select>
<br><br><div id="msg"></div>
</body>
</html>
소스코드의 주석에 상세히 설명을 달았지만 간단히 전체적인 흐름을 설명하자면,
드래그 대상(Source)은 왼쪽 select 박스의 option 항목들이며,
드롭 대상(Target)은 오른쪽 select 박스이다
드래그 대상인 option 요소에 draggable="true" 속성을 부여해 드래그 가능한 상태로 설정하였다
그리고 dragstart 이벤트를 구현하여 드래그 액션이 시작될 때 dataTransfer 객체에
드래그 데이터(여기서는 option 의 ID)를 저장하고 있다
드롭 대상인 오른쪽 select 박스에는 dragenter, dragover, drop 이벤트를 구현하여
preventDefault 함수 호출로 select 박스가 드롭이 가능하도록 설정하였으며
dataTransfer 객체에서 드래그 데이터(여기서는 option 의 ID)를 꺼내온다
이렇게 꺼내온 드래그 데이터를 문서객체에서 조회하여 드래그 대상에서는 제거하고 드롭 대상에
추가하는 로직으로 구성되어 있다
그리고 추가로 드래그 관련 이벤트의 호출 순서를 보기 위한 코드가 각 이벤트에 추가되어 있다
아래는 데모의 실행 화면이다. 먼저 드래그가 중에 캡쳐한 화면이며,
아래는 드래그, 드롭이 완룐된 화면이다.
select 박스 하단을 보면 드래그 관련 이벤트의 호출 흐름을 나타내고 있다
본 예제에서는 문서내 요소간 드래그&드롭을 구현해 봤지만, 문서간 문서와 다른 응용프로그램 간
드래그&드롭도 가능하다. 이는 관련 자료를 살펴 보기 바란다
마지막으로 아래 사이트에서 드래그 & 드롭 관련 데모를 추가로 확인해 보자
http://ljouanneau.com/lab/html5/demodragdrop.html
http://html5demos.com/drag
'모바일 > HTML5' 카테고리의 다른 글
[HTML5] 오프라인 웹 어플리케이션 (7) | 2010.08.12 |
---|---|
[HTML5] Web Storage (8) | 2010.08.11 |
[HTML5] Geolocation (7) | 2010.08.09 |
[HTML5] Web Workers (웹 워커) (7) | 2010.08.05 |
HTML5 Demo, A Look At HTML5 and its Canvas Tag (4) | 2010.07.29 |