[Javascript] 스크린 영역 드래그 및 이미지 캡쳐와 다운로드

Arin·2021년 4월 27일
0

Javascript

목록 보기
1/1

순수 자바스크립트로 드래그 한 영역을 이미지로 캡쳐하여 다운로드를 해 보았다.

html2canvas라이브러리를 같이 사용해야 한다.

html, script파일


<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>이미지 캡쳐</title>
        
        <link rel="stylesheet" type="text/css" href="./style.css">
    </head>
    <body>
        <div id="page">
            <div class="title">순수자바스크립트 영역 캡쳐 후 저장</div>
            <button type="button" class="btn" id="edit">캡쳐하기</button>
            <div>
                <img src="image/bunny.jpg" alt="bunny" id="image" />
            </div>
            <a id="target"></a>
            
        </div>
        <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
        <script>
            window.onload = function (){
                document.getElementById("edit").addEventListener("click", function(e){
                    document.querySelector("body").classList.add('edit_cursor');
                    screenshot(e)
                })
            }

            function screenshot(e){
                let startX, startY;
                let height = window.innerHeight;
                let width = window.innerWidth;

                //배경을 어둡게 깔아주기 위한 div 객체 생성
                let screenBg = document.createElement("div");
                screenBg.id = "screenshot_background";
                screenBg.style.borderWidth = "0 0"+ height + "px 0";

                //마우스 이동하면서 선택한 영역의 크기를 보여주기 위한 div 객체 생성
                let screenShot = document.createElement("div");
                screenShot.id = "screenshot";

                document.querySelector("body").appendChild(screenBg)
                document.querySelector("body").appendChild(screenShot)

                let selectArea = false;
                let body = document.querySelector('body');

                //마우스 누르는 이벤트 함수
                const mouseDown = function(e){
                    e.preventDefault();
                    selectArea = true;
                    startX = e.clientX;
                    startY = e.clientY;
                    console.log("mousedown", startX, startY)
                    body.removeEventListener("mousedown", mouseDown);
                }

                function mouseMove(e){
                    let x = e.clientX;
                    let y = e.clientY;
                    screenShot.style.left = x;
                    screenShot.style.top = y;
                    if(selectArea){
                        let top = Math.min(y, startY);
                        let right = width - Math.max(x, startX)
                        let bottom = height - Math.max(y, startY)
                        var left = Math.min(x, startX)
                        screenBg.style.borderWidth = `${top}px ${right}px ${bottom}px ${left}px`;
                        console.log("screenBg", screenBg.style.borderWidth)
                    }
                }

                function save(canvas){
                    if(navigator.msSaveBlob){
                        let blob = cnavas.msSaveBlob()
                        return navigator.msSaveBlob(blob, '파일명.jpg');
                    }else {
                        let el = document.getElementById('target');
                        el.href = canvas.toDataURL("image/jpeg");
                        el.download = "bunny.jpg";
                        el.click();
                    }
                }

                function mouseUp (e){
                    selectArea = false;
                    //(초기화) 마우스 떼면서 마우스 무브 이벤트 삭제
                    body.removeEventListener("mousemove", mouseMove);
                    //(초기화) 스크린샷을 위해 생성한 객체 삭제
                    screenShot.parentNode.removeChild(screenShot);
                    screenBg.parentNode.removeChild(screenBg);
                    let x = e.clientX;
                    let y = e.clientY;
                    let top = Math.min(y, startY)
                    let left = Math.min(x, startX)
                    let width = Math.max(x, startX) - left;
                    let height = Math.max(y, startY) - top;
                    console.log("mouseup", left,top, width, height)

                    html2canvas(document.body).then(
                        function(canvas){
                            let img = canvas.getContext('2d').getImageData(left, top, width, height);
                            console.log(img);
                            let c = document.createElement('canvas');
                            c.width = width;
                            c.height = height;
                            c.getContext('2d').putImageData(img, 0, 0);
                            save(c); // crop한 이미지 저장
                        }
                    )
                    body.removeEventListener("mouseup", mouseUp);
                 document.querySelector('body').classList.remove('edit_cursor');
                }
                body.addEventListener("mousedown", mouseDown);
                body.addEventListener("mousemove", mouseMove);
                body.addEventListener("mouseup", mouseUp);
                
            }

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

css파일


#page{
    width: 70%;
    min-height: 900px;
    margin: 0 auto;
}

#target {
    display: none;
}

.title{
    margin: 30px 0;
    font-size: 24px;
    font-weight: 700;
}

#image{
    width: 100%;
    max-width: 700px;
}

.btn{
    background: darkmagenta;
    border: transparent;
    outline: none;
    padding: 8px 24px;
    color: white;
    font-size: 17px;
    border-radius: 4px;
    margin-bottom: 15px;
}
.btn:hover{
    cursor:pointer;
    background: rgb(206, 10, 206);
}

/* 캡쳐 시 배경 어둡게 */
#screenshot_background {
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    display:block;
    opacity: 0.3;
    text-align: center;
    box-sizing: border-box;
    z-index: 9999;
    border: 1px solid black;
}

/* 캡쳐 영역만 밝게 하기 위한 요소 */
#screenshot:before, #screenshot:after {
    border: none ;
    content: "";
    height: 100%  ;
    position: absolute;
    width: 100%;
}

#screenshot::before{
    border-right: 1px solid white;
    border-bottom: 1px solid white;
    left: -100%;
    top: -100%;
}

#screenshot:after{
    border-top: 1px solid white;
    border-left: 1px solid white;
    left: 0;
    top:0;
}


#screenshot{
    height: 100%;
    position:fixed;
    width: 100%;
    z-index: 99999;
}

body.edit-cursor {
    cursor: crosshair;
}


핵심요점

위의 코드에서는 배경을 div의 배경색이 아니라 border의 두께값을 계산하여 검은 색상을 채웠다. 배경색상을 넣으면 캡쳐된 내용물이 가려지기 때문이다.

mousedown, mousemove, mouseup 이렇게 3가지 단계에 함수를 각각 만든다.

  • mousedown : 이미지캡쳐가 시작될 위치값을 알아낸다.
  • mousemovve : 캡쳐될 이미지 영역이 그려지도록 마우스 위치값과 노드의 스타일 값을 조절한다.
  • mouseup : canvas를 만들 값을 구하고 html2canvas를 이용하여 canvas를 image데이터로 만들어 다운로드 시킨다.
profile
2년차 프론트앤드

0개의 댓글