Canvas라는 elements를 이용해 그림을 그릴 수 있는 기능을 사용할 수 있다. 

해당 캔버스엔 선, 원과 같은 그림을 그리는 기능을 사용할 수 있는데. 

Script 에서 제공하는 이벤트 기능과 합쳐 그림판을 만들 수 있는 것이다.

 

어떻게 동작하는건지 알아보자 

원리는 간단하다!

canvas위 마우스 클릭 이벤트를 감지해서 현재 마우스가 위치한 영역에 좌표를 구하고,

그 좌표에 작은 원을 그려준다. 

마우스가 이동할때 감지되는 mousemove 이벤트는 계속해서 현재 마우스의 위치를 

가져오고 그 위치에 계속해서 원을 그려주는 것이다. 

이렇게 되면 마치 우리가 연필로 그림을 그리듯한 모습을 볼수있다. 

마우스가 움직일때마다 그림을 그려주면 마우스가 움직일때마다 그림을 그리기 떄문에 

아래 코드를 보면 painting 이라는 flag를 추가했다. 

마우스가 클릭되면 이 flag를 true로 변경해 그림을 그리게 시키고.. 

마우스 클릭이 off되면 flag를 false로 변경해서 더이상 그림을 그리지 않도록 처리되는 것이다. 

 

touch 이벤트도 감지하도록 아래 코드에 적어뒀기 때문에 

아이패드, 노트북 펜슬 등으로 터치해도 기능이 잘 동작한다! 

 

아래 샘플코드를 그대로 복사하면

샘플을 확인할 수 있다~ 

 

<canvas id="canvas" ></canvas>
<script src="https://code.jquery.com/jquery-2.1.0.min.js"></script>
<script>
	
	// 캔버스 객체를 가져온다.
	var canvas = document.getElementById("canvas"),
	ctx = canvas.getContext("2d"),
	painting = false, // 그림을 그릴 상황인지 체크하는  flag
	lastX = 0, // 마지막 x 좌표 
	lastY = 0, // 마지막 y 좌표 
	lineThickness = 1; // 펜 굵기 
	
	
	// canvas 사이즈설정	
	canvas.width  = window.innerWidth;
	canvas.height = window.innerHeight;
	
	
	// 터치감지 이벤트  
	 document.body.addEventListener("touchstart", function (e) {
		if (e.target == canvas) {e.preventDefault(); }
		var touch = e.touches[0];
    	var mouseEvent = new MouseEvent("mousedown", {
			clientX: touch.clientX,
			clientY: touch.clientY
		});
		canvas.dispatchEvent(mouseEvent);
				
	}, false);
	
	
	document.body.addEventListener("touchend", function (e) {
		if (e.target == canvas) {
			e.preventDefault();
		}
		
		var touch = e.touches[0];
    	var mouseEvent = new MouseEvent("mouseup", {
			clientX: touch.clientX,
			clientY: touch.clientY
		});
		canvas.dispatchEvent(mouseEvent);
		
	}, false);
	document.body.addEventListener("touchmove", function (e) {
		if (e.target == canvas) {
			e.preventDefault();
		}
		
		var touch = e.touches[0];
		var mouseEvent = new MouseEvent("mousemove", {
			clientX: touch.clientX,
			clientY: touch.clientY
		});
		canvas.dispatchEvent(mouseEvent);
		
	}, false);
		
    
	// 마우스 이벤트 	
	canvas.onmousedown = function(e) {
	    painting = true;
	    ctx.fillStyle = "#000";
	    lastX = e.pageX - this.offsetLeft;
	    lastY = e.pageY - this.offsetTop;
	};

	canvas.onmouseup = function(e){
	    painting = false; // 마우스로 그림그리기가 끝나면 플래그를 변경해준다. 
	}

	
	// 그림을 그려주는 function
	canvas.onmousemove = function(e) {
		
	    if (painting) {
	        mouseX = e.pageX - this.offsetLeft;
	        mouseY = e.pageY - this.offsetTop;

	        // find all points between        
	        var x1 = mouseX,
	            x2 = lastX,
	            y1 = mouseY,
	            y2 = lastY;


	        var steep = (Math.abs(y2 - y1) > Math.abs(x2 - x1));
	        if (steep){
	            var x = x1;
	            x1 = y1;
	            y1 = x;

	            var y = y2;
	            y2 = x2;
	            x2 = y;
	        }
	        if (x1 > x2) {
	            var x = x1;
	            x1 = x2;
	            x2 = x;

	            var y = y1;
	            y1 = y2;
	            y2 = y;
	        }

	        var dx = x2 - x1,
	            dy = Math.abs(y2 - y1),
	            error = 0,
	            de = dy / dx,
	            yStep = -1,
	            y = y1;
	        
	        if (y1 < y2) {
	            yStep = 1;
	        }
	       
	        lineThickness = 3 - Math.sqrt((x2 - x1) *(x2-x1) + (y2 - y1) * (y2-y1))/10;
	        if(lineThickness < 1){
	            lineThickness = 1;   
	        }

	        for (var x = x1; x < x2; x++) {
	            if (steep) {
	                ctx.fillRect(y, x, lineThickness , lineThickness );
	            } else {
	                ctx.fillRect(x, y, lineThickness , lineThickness );
	            }
	            
	            error += de;
	            if (error >= 0.5) {
	                y += yStep;
	                error -= 1.0;
	            }
	        }

	        lastX = mouseX;
	        lastY = mouseY;

	    }
	}
    
	
	// 캔버스에 이미지를 그려준다. 
	// 나의 경우 이미지 위에 그림을 그려야해서 사용함. 
	// 생략가능 
    setBackground();
    function setBackground() {
	    var image = new Image();
	    image.onload = function() {
		    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
	    }
	    image.src = "/resources/images/suit.png";

    }
    

</script>

 

 

결과 

 

 

* 추가적으로  Hammer.js 를 사용하면  모바일 환경에서 발생되는 더 많은 터치기능(확대, swipe, tab)을 처리할 수 있다. 

 

 

[사전환경]  * jquery 설정이 되어있을것! 

코드시작!! 

 

1. file을 받는 input과 미리보기할 이미지를 코드를 작성한다.

<input type="file" id="file" class="imgs" name="mainImg">
<img src="" />

 

2. 스크립트 작성

파일을 여러개 입력하더라도 각각 미리보기를 띄울 수 있다.

<script>
	$(function() { 
		$("input[type='file']").change(function(){
		  $(this).siblings("img").attr('src', URL.createObjectURL(this.files[0]));
	    });
	})
</script>

 

@ 주제 

자바스크립트가 할수없는것

 

@ 목적 

CORS 작업을 진행하며 알게된 내역정리 

 

@ 내용 

1. 자바스크립트는 클라이언트 컴퓨터에서 임의로 디렉터리와 파일을 만들거나 지울 수 없다. 이런 기능 제약으로 인해서 자바스크립트 프로그램은 클라이언트 컴퓨터의 데이터를 삭제하거나 바이러스를 침투시킬 수 없다. 그러나 HTML5에서는 사용자가 직접 선택한 파일을 불러오는 방법과 일고 쓰기가 가능한 보안 전용 파일 시스템을 확득하는 방법이 있다.

 

2.  자바스크립트는 브라우저에서 새 창을 열 수 있다. 하지만 광고주들의 팝업 남용을 막기 위해 대부분의 브라우저는 새 창 열기를 막아 두고 마우스 클릭 같은 행동으로 사용자가 직접 새 창을 열게 한다.

 

3. 자바스크립트는 스스로 연 새 창은 다시 닫을 수 있지만, 다른 창을 닫으려면 사용자가 확인 창에서 승인을 해주어야 한다.

 

4. HTML FileUpload 요소(<input type="file">)의 value 속성은 값을 불러올 수는 있지만 지정할 수는 없다. 이것이 가능하면 자바스크립트로 원하는 파일을 value 속성에 지정할 수 있으므로, 서버로 특정 파일의 내용(예를 들면 계정 암호)을 업로드하는 폼을 만들 수 있기 때문이다.

 

5. 스크립트는 자신이 실행된 문서의 서버와 다른 서버에서 불러온 문서의 내용은 읽을 수 없다. 비슷한 의미로 스크립트는 다른 서버에서 불러온 문서에 이벤트 리스너를 등록할 수 없다. 이 제약 사항이 다른 페이지에서 (암호를 입력할 때 생기는 키보드 입력 같은) 사용자 입력을 가로체는 스크립트를 심지 못하게 한다. 이 제약 사항을 동일 출처 정책(same-origin policy)이라고 한다. 

 

'기능 정리' 카테고리의 다른 글

Git ignore white space 설정  (0) 2021.01.14
CORS (Cross-origin resource sharing) 사이트간 데이터 주고 받기  (0) 2020.08.14
Same-Origin Policy  (0) 2020.08.12
util 태그 라이브러리의 사용  (0) 2020.08.11
JSTL 이란  (0) 2020.08.11

+ Recent posts