[HTML | CSS | JavaScript | jQuery] 정리/JavaScript

JavaScript - CSS 드래그

쎈코 2023. 5. 8. 00:11

<!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="css/example.css">
    <style>
        .draggable {
            position: relative;   <- 자기 자신이 좌표의 꼭짓점 기준
            left: 0;
            top: 0;
            user-select: none; 
        }
    </style>
</head>
<body onselectstart="return false;">
    <img src="images/catty01.png" class="draggable">
    <h1 class="draggable">제목입니다.</h1>
    <div class="box bg-red draggable">상자1</div>
    <div class="box bg-yellow draggable">상자2</div>
    <div class="box bg-blue draggable">상자3</div>
    <button class="draggable">버튼</button>
    
    <script>

        let isDown = false;
        let x = 0, y = 0;
        let obj; //드래그 대상
        let zindex = 0;

        // let ox = 0, oy = 0; //정적인 상태의 객체 위치값
        let olist = [];       //배열 생성

        const list = document.getElementsByClassName('draggable');

        for (let i=0; i<list.length; i++) {
            olist.push({
                obj: list[i],        list[i]에 있는 모든 요소들의 위치정보(x, y)를 olist에 저장
                x : list[i].getBoundingClientRect().left,          요소의 위치정보를 저장
                y : list[i].getBoundingClientRect().top
            });
        }
        ※ .getBoundingClientRect() : 요소의 크기와 위치 정보를 제공하는 메소드

                                                          요소의 상대적인 위치와 크기, 스크롤 위치 등의 정보를 가져올 수 있음
        console.log(olist);

        window.onmousedown = function() {
            
            if (event.target.classList.contains('draggable')) {
                obj = event.target;     //드래그 대상
                isDown = true;          <- 마우스가 눌려있는 상태
                x = event.offsetX;     <- 마우스가 클릭한 위치
                y = event.offsetY;

                ox = getLeft(obj);       <- obj의 초기 위치 저장
                oy = getTop(obj);

                zindex++;
                obj.style.zIndex = zindex;
            }
        };

        function getLeft(obj) {                            <- obj 매개변수로 전달된 요소의 초기 x 좌표값 반환
            for (let i=0; i<olist.length; i++) {
                if (olist[i].obj == obj) {                    <- olist배열에서 obj와 일치하는 요소를 찾아서 해당 요소의 x좌표값 반환
                    return olist[i].x;
                }
            }
        }

        function getTop(obj) {
            for (let i=0; i<olist.length; i++) {
                if (olist[i].obj == obj) {
                    return olist[i].y;
                }
            }
        }

        window.onmousemove = function() {
            if (isDown) {
                obj.style.left = event.clientX + window.pageXOffset - x - ox + 'px';
                obj.style.top = event.clientY + window.pageYOffset - y - oy + 'px';

              -> event.clientX/Y : 현재 마우스 커서의 위치

                  window.pageX/YOffset : 현재 스크롤된 페이지의 x/y축 위치

                  x와 y는 마우스 다운 시점에서 요소 내부의 마우스 좌표값, ox와 oy는 드래그 대상 요소의 초기 위치값.

                 드래그 대상 요소를 이동시키기 위해서는 (현재 마우스 위치값 - 마우스 다운 시점의 위치값) - (초기 위치값)


                //고스트 이미지 현상 제거
                event.stopPropagation();
                return false;
            }
        };

        window.onmouseup = function() {
            isDown = false;
        };

    </script>
</body>
</html>