-
듀자이크 생성기 만들기토이 프로젝트 2022. 3. 21. 23:24
메이플 인벤 일명 메벤에서는
사진에 모자이크를 넣을때
해당 게임의 직업중 하나인 듀블을,
일명 "듀자이크"를 넣는 문화(?)가 있다.
https://khs20010327.tistory.com/33
짤방 생성기 만들기
커뮤니티에서 이런 댓글을 봤다. 저 만화의 짤방은 여러 커뮤니티에서 자주 사용하는 짤이고, 인벤 커뮤니티는 고유의 특징으로 커뮤니티를 많이하면 레벨이 오르고 레벨에 따라 일명 '딱지색"
khs20010327.tistory.com
이 사이트를 만들어서 커뮤에 올리고 얼마 지나지 않아
듀자이크를 넣은 살짝 야한(...) 사진이 올라왔더라.
마침 개발 의지가 타올랐을때,
저것도 한번 만들어보자 싶어서 바로 제작에 들어갔다.
듀자이크 사이트의 순서는 이러하다.
1.듀자이크를 넣을 사진을 입력받는다.
2.그러면 똑같은 사진이 3장 뜬다.
3.첫번째 사진을 누르면 해당 위치에 듀자이크가 생성된다.
4.두번째 사진을 누르면 해당 위치에 2번째 듀자이크가 생성된다.
-아무래도 모자이크는 위 아래로 2개 넣는 경우가 많다보니(...)-
5.그렇게 최종적으로 완성된 3번째 사진을 다운받으면 완료
지금이야 이렇게 정리할 수 있지만,
이번 프로젝트에도 역시 수많은 시행착오가 있었다.
일단 가장 어려운점은, "편리"해야됐다.
저번에 만든 사이트야, 레벨만 입력하면 바로 짤방이 생성되니
확실히 "편리"했다.
그러니 이번에 만들 듀자이크 사이트도,
인터넷에서 듀블 사진을 받아 갤러리에서 편집하는것보다
"편리"해야했다.
아니면 만드는 의미가 없으니까.
여기에 겹쳐진 문제점은 주 사용처가 모바일이라는것.
이미지를 드래그로 옮기거나
마우스 휠로 크기를 조정하는 것은 쉬운 예제로
나도 학교에서 배울때 만들어봤고
인터넷에서도 널린게 예제이다.
문제는 모바일에는 휠도 없고,
드래그도 구현하기 빡셌다.
그렇게 나는 1차 코드를 폐기하고 새로 짜기 시작했다.
일단 첫번째로 바꾼점은,
이벤트 리스너를 "클릭" 단 하나만 사용했다.
클릭은 마우스로도, 터치로도 되므로
컴퓨터 모바일 둘다 사용 가능했고
무엇보다 간단했다.
기존에는 듀블 이미지가 자동으로 생성되고
이를 원하는 위치로 "드래그"해서 옮기는 방시이였는데,
이미지를 "클릭/터치"했을때 해당 위치에 듀자이크가 생성되도록 바꿨고
이를 베이스로 최대한 사용자의 편의성에 초점을 맞춰봤다.
그렇게 생성된 듀자이크 생성기. 이제 코드를 하나하나 살펴보자.
이번에는 html 코드를 바탕으로,
각 파트에 적용된 자바 스크립트를 설명하는게 이해하기 좋을것같다.
일단 맨 위에는 "파일 선택" 버튼을 통해
듀자이크를 넣을 사진을 업로드한다.
<br><br><br><ul> <li><input type="file" id="getfile" accept="image/*" style="font-size:100px;"></li></ul> <br><br><br><br>
html 코드.
input 버튼의 타입을 file로 해주고, 이미지 파일만 받도록 accept는 이미지로 해준다.
이 파트에 대한 js 코드를 살펴보자면
var canvas = document.querySelector('#mycanvas'); var context = canvas.getContext("2d"); context.globalCompositeOperation = "source-over"; var canvas2 = document.querySelector('#mycanvas2'); var context2 = canvas2.getContext("2d"); context2.globalCompositeOperation = "source-over";
일단 캔버스를 2개 생성하고
var $file = document.querySelector('#getfile'); var baseImage = new Image(); var dusrc; var dusrc2;
file과 이미지 src들을 선언해준다.
$file.onchange = function () { var fileList = $file.files; var reader = new FileReader(); reader.readAsDataURL(fileList [0]); reader.onload = function () { baseImage.src = reader.result; //data-uri를 이미지 객체에 주입 baseImage.onload = function () { canvas.width = baseImage.width; canvas.height = baseImage.height; canvas2.width = baseImage.width; canvas2.height = baseImage.height; context.drawImage(this, 0, 0, baseImage.width, baseImage.height); context2.drawImage(this, 0,0, baseImage.width, baseImage.height); var dataURI = canvas.toDataURL("image/jpeg"); document.querySelector('#preview').width = baseImage.width; document.querySelector('#preview').height = baseImage.height; document.querySelector('#preview').src = dataURI; }; }; };
그리고 파일이 업로드/수정되었을때 작동하는 함수를 넣어준다.
파일을 읽어 베이스 이미지의 src를 변경하고, 이를 1번 캔버스와 2번 캔버스에 넣는다.
이때 캔버스의 크기도 해당 이미지의 크기로 맞춰준다.
그리고 캔버스의 이미지를 toDataURL 메서드를 통해 추출하여
3번째 <IMG>객체에 반환한다.
쉽게 요약하자면
업로드한 파일을
1번 캔버스와 2번 캔버스에,
그리고 캔버스의 이미지를 3번 <IMG>에 넣어
똑같은 이미지를 3개 출력하게 된다.
https://jsfiddle.net/eu81273/g60v7wp8/
두 이미지 합성 - JSFiddle - Code Playground
jsfiddle.net
해당 코드는 저번 사이트를 만들때 참조했던 코드를 다시 한번 참조했다.
저번보다 이번에 더 알차게 써먹은것같다.
<canvas onclick ="dualss(event);" id="mycanvas" ></canvas> <ul> <li>1번 모자이크 가로 길이 <br><input id='dw' onkeyup='dwv()' > <br> 현재값 <a id='result1'></a> <br><br><br> <a onclick="one100()">[+100]</a><a>//</a> <a onclick="one10()">[+10]</a><a>//</a> <a onclick="onem10()">[-10]</a><a>//</a> <a onclick="onem100()">[-100]</a></li> <br><br><br> <li>1번 모자이크 세로 길이 <br><input id='dh' onkeyup='dhv()'/> <br> 현재값 <a id='result2'></a> <br><br><br> <a onclick="two100()">[+100]</a> <a>//</a> <a onclick="two10()">[+10]</a> <a>//</a> <a onclick="twom10()">[-10]</a> <a>//</a> <a onclick="twom100()">[-100]</a></li> <br><br><br> <li>1번 이미지 선택 <br> </li> 현재값 <a id='image1'></a><br><br> <a onclick="q11()">1.구 듀블 (배경 투명)</a><br> <a onclick="q12()">2.구 듀블 (배경 불투명)</a><br> <a onclick="q13()">3.신 듀블 (배경 투명)</a><br> <a onclick="q14()">4.신 듀블 (배경 불투명)</a><br> <a onclick="q15()">5.필요한 만큼은 보여줬다</a><br> <a onclick="q16()">6.너굴맨이 처리했으니 안심하라구!</a><br> </ul>
다시 HTML 코드로 돌아와서,
1번 캔버스의 이미지와 함께
듀자이크의 크기와 종류를 조절할수 있는 버튼들을 출력한다.
일단 듀자이크의 가로와 세로 길이는 300과 200이 고정값이고,
이를 값을 직접 입력하거나 밑의 크기 조절 버튼으로 간단하게 조절할 수 있다.
조금 아쉽지만, 스프레드
(화면은 두 손가락으로 누른 상태로 두 손가락 사이 거리를 벌리는것.
모바일에서 주로 확대를 나타내는 이벤트)
를 구현하는 것보다 이쪽이 훨씬 간단할것같아서
일단 이와 같이 구현했다.
이는 다음에 더 실력을 늘려 구현해보도록 하고,
마찬가지로 버튼을 눌러 듀자이크의 종류도 변경할 수 있도록 한다.
개인적으로 이 기능이 없다면 이 사이트를 굳이 쓸 필요가 있나 싶었지만
(아무리 크기를 최대한 쉽게 조절할 수 있게 바꿨더라도
스프레드 기능이 존재하는 기본 편집기보다는 불편하니까...)
다양한 이미지를 기본으로 제공하고
터치 한번으로 바꿀 수 있다면,
이 역시 제법 편리한 사이트가 될테니까,
나름 생각해낸 핵심 기능이였다.
이미지는 듀블의 구 일러스트와 신 일러스트,
역시나 커뮤에 주로 돌아다니는 짤과 합쳐진 듀블 일러스트,
그리고 듀블은 아니지만 이와 비슷하게 쓰이는 너굴맨(...)
듀블의 일러스트는 배경이 투명한 버전과 아닌 버전 둘다 제공한다.
둘다 용도(?)에 따라 필요할 수 도 있으니까.
이미지에서 배경 제거 – remove.bg
한 번의 클릭으로 5 초 안에 이미지 배경을 자동으로 제거합니다. 수동으로 픽셀을 선택하는 데 시간을 소비하지 마십시오. 지금 사진을 업로드하고 마법을 확인하세요.
www.remove.bg
듀블 이미지는 배경이 투명한게 없어서 누끼를 따야했는데,
요즘은 그냥 인터넷에서 쉽고 빠르게 배경을 없앨수있다.
세상 참 좋아졌다.
<canvas onclick ="dualss2(event);" id="mycanvas2" ></canvas> <ul> <li>2번 모자이크 가로 길이 <br><input id='dw2' onkeyup='dwv2()'/> <br> 현재값 <a id='result3'></a> <br><br><br> <a onclick="three100()">[+100]</a> <a>//</a> <a onclick="three10()">[+10]</a> <a>//</a> <a onclick="threem10()">[-10]</a> <a>//</a> <a onclick="threem100()">[-100]</a></li> <br><br><br> <li>2번 모자이크 세로 길이 <br><input id='dh2' onkeyup='dhv2()'/> <br> 현재값 <a id='result4'></a><br><br><br> <a onclick="four100()">[+100]</a> <a>//</a> <a onclick="four10()">[+10]</a> <a>//</a> <a onclick="fourm10()">[-10]</a> <a>//</a> <a onclick="fourm100()">[-100]</a></li> <br><br><br> <li>2번 이미지 선택 <br> </li> 현재값 <a id='image2'></a><br><br> <a onclick="q21()">1.구 듀블 (배경 투명)</a><br> <a onclick="q22()">2.구 듀블 (배경 불투명)</a><br> <a onclick="q23()">3.신 듀블 (배경 투명)</a><br> <a onclick="q24()">4.신 듀블 (배경 불투명)</a><br> <a onclick="q25()">5.필요한 만큼은 보여줬다</a><br> <a onclick="q26()">6.너굴맨이 처리했으니 안심하라구!</a><br> </ul> <br><br><br><br>
2번 캔버스 파트.
1번과 코드는 똑같다 봐도 된다.
다른 캔버스를 사용해서 듀자이크를 2개 넣을수 있게 했을 뿐.
이제 캔버스들의 JS 코드를 살펴보자면
var ddw=300; document.getElementById("result1").innerText = ddw; var ddh=200; document.getElementById("result2").innerText = ddh; var ddw2=300; document.getElementById("result3").innerText = ddw2; var ddh2=200; document.getElementById("result4").innerText = ddh2; var im1 =1; document.getElementById("image1").innerText = im1; var im2 =1; document.getElementById("image2").innerText = im2; var x1; var y1; var x2; var y2;
일단 듀자이크의 기본값을 변수로 선언해준다.
function dwv() { ddw = document.getElementById('dw').value; ddw = parseInt(ddw); document.getElementById("result1").innerText = ddw; } function dhv() { ddh = document.getElementById('dh').value; ddh = parseInt(ddh); document.getElementById("result2").innerText = ddh; } function dwv2() { ddw2 = document.getElementById('dw2').value; ddw2 = parseInt(ddw2); document.getElementById("result3").innerText = ddw2; } function dhv2() { ddh2 = document.getElementById('dh2').value; ddh2 = parseInt(ddh2); document.getElementById("result4").innerText = ddh2; }
그리고 input에서 받은 값을
듀자이크의 가로, 세로 길이값 변수에 넣고,
이를 사용자에게 보여주는 함수.
function one100(){ ddw +=100; document.getElementById("result1").innerText = ddw; } function one10(){ ddw +=10; document.getElementById("result1").innerText = ddw; } function onem10(){ ddw -=10; document.getElementById("result1").innerText = ddw; } function onem100(){ ddw -=100; document.getElementById("result1").innerText = ddw; } function two100(){ ddh +=100; document.getElementById("result2").innerText = ddh; } function two10(){ ddh +=10; document.getElementById("result2").innerText = ddh; } function twom10(){ ddh -=10; document.getElementById("result2").innerText = ddh; } function twom100(){ ddh -=100; document.getElementById("result2").innerText = ddh; } function three100(){ ddw2 +=100; document.getElementById("result3").innerText = ddw2; } function three10(){ ddw2 +=10; document.getElementById("result3").innerText = ddw2; } function threem10(){ ddw2 -=10; document.getElementById("result3").innerText = ddw2; } function threem100(){ ddw2 -=100; document.getElementById("result3").innerText = ddw2; } function four100(){ ddh2 +=100; document.getElementById("result4").innerText = ddh2; } function four10(){ ddh2 +=10; document.getElementById("result4").innerText = ddh2; } function fourm10(){ ddh2 -=10; document.getElementById("result4").innerText = ddh2; } function fourm100(){ ddh2 -=100; document.getElementById("result4").innerText = ddh2; }
1번/2번 듀자이크의 가로/세로 길이를 +100/+10/-10/-100 해주는
2*2*4= 총 16개의 함수.
아무래도 각기 사용처가 다르고 값도 미묘하게 다르다보니
그냥 복붙해서 16번 구현하는게 최선인것같았다.
function dualss() { var canvas = document.querySelector('#mycanvas'); var context = canvas.getContext('2d'); x1 = event.offsetX; y1 = event.offsetY; context.drawImage(baseImage, 0, 0, baseImage.width, baseImage.height); var duImage2 = new Image(); //drawImage 메서드에 넣기 위해 이미지 객체화 duImage2.src = dusrc2; var duImage = new Image(); //drawImage 메서드에 넣기 위해 이미지 객체화 duImage.src = dusrc; duImage.onload = function(){ context.drawImage(this, x1-(ddw/2), y1-(ddh/2), ddw, ddh); context.drawImage(duImage2, x2-(ddw2/2), y2-(ddh2/2), ddw2, ddh2); var dataURI = canvas.toDataURL("image/jpeg"); document.querySelector('#preview').src = dataURI; document.querySelector('#download').href = dataURI; } }
그리고 캔버스의 터치한 위치에 듀자이크를 생성하는 함수.
canvas를 document.querySelector로 읽어 변수로 지정하고,
클릭/터치했을때의 좌표를 저장해
해당 위치에 context.drawImage로 듀자이크를 생성한다.
그리고 이때 문제점이 하나 발생했는데,
터치하여 듀자이크를 한번 생성한 다음,
해당 캔버스를 다시 한번 누른다는 것은
듀자이크를 추가로 생성한다는 것이 아니라
기존의 듀자이크 위치를 새로운 위치로 수정하고 싶다는 것을 의미한다.
즉 기존의 듀자이크를 삭제하고 새로운 위치에 듀자이크를 생성해야한다.
다만 이 듀자이크는 따로 <img> 객체를 사용한것도 아니고,
그냥 캔버스에 그려 넣은것이다보니 이를 수정할 수 있는 메서드가 존재하지 않았다.
그래서 이를 처음부터 뜯어고쳐야하나 머리를 굴린결과...
그냥 캔버스를 덮어 씌어버리면 되는구나!
캔버스에는 베이스가 되는 이미지 위에 듀자이크가 생성되는 구조이므로,
터치를 했을때 듀자이크가 아닌,
베이스 이미지를 한번 더 깔고, 그 위에 듀자이크를 올린다면
그 이전에 있던 듀자이크는 새로운 베이스 이미지에 덮혀 안보이게 된다.
(베이스)-(듀자이크)-(듀자이크)
기존의 방식이라면 2번 터치시 듀자이크가 2개가 보이겠지만
(베이스)-(베이스)-(듀자이크)-(베이스)-(듀자이크)
이렇게 해버리면 마지막 베이스 이전의 이미지는 전부 가려지니까
듀자이크는 하나만 보인다!
정말 기깔난 꼼수였다.
아마 이게 아니라면
코드를 처음부터 뜯어 고치다가 포기했을것이다.
다시한번 내 잔머리와 꼼수가 기특하게 느껴졌다(...)
function dualss2() { var canvas2 = document.querySelector('#mycanvas2'); var context2 = canvas2.getContext('2d'); x2 = event.offsetX; y2 = event.offsetY; context2.drawImage(baseImage, 0, 0, baseImage.width, baseImage.height); var duImage = new Image(); //drawImage 메서드에 넣기 위해 이미지 객체화 duImage.src = dusrc; var duImage2 = new Image(); //drawImage 메서드에 넣기 위해 이미지 객체화 duImage2.src = dusrc2; duImage2.onload = function(){ context2.drawImage(duImage, x1-(ddw/2), y1-(ddh/2), ddw, ddh); context2.drawImage(duImage2, x2-(ddw2/2), y2-(ddh2/2), ddw2, ddh2); var dataURI = canvas2.toDataURL("image/jpeg"); document.querySelector('#preview').src = dataURI; document.querySelector('#download').href = dataURI; } }
2번 캔버스를 터치해 2번쨰 듀자이크를 만드는 함수.
1번 코드와 사실상 동일하다.
그리고 1번 이미지를 터치했을때 2번 듀자이크가 있을경우,
반대로 2번 이미지를 터치했을때 1번 듀자이크가 존재하는 경우,
듀자이크를 둘다 넣는다.
아무래도 이쪽이 조금 더 가시성이 좋다 생각되서 코드를 추가했다.
자바 스크립트가 편한게
1/2번 이미지를 눌렀을떄 2/1번 듀자이크가 없을 경우를 따로 제외하지 않아도
없으면 알아서 코드가 실행되지 않는다.
편리하다.
그 다음에는, 듀자이크 이미지를 base64로 변경하여 코드로 넣어준다.
이에 대한 설명은 저번 글 참고
dusrc = guduy; dusrc2 = guduy; function q11(){ dusrc = guduy; document.getElementById("image1").innerText = 1; } function q12(){ dusrc = gudun; document.getElementById("image1").innerText = 2; } function q13(){ dusrc = sinduy; document.getElementById("image1").innerText = 3; } function q14(){ dusrc = sindun; document.getElementById("image1").innerText = 4; } function q15(){ dusrc = pill; document.getElementById("image1").innerText = 5; } function q16(){ dusrc = nugulman; document.getElementById("image1").innerText = 6; } function q21(){ dusrc2 = guduy; document.getElementById("image2").innerText = 1; } function q22(){ dusrc2 = gudun; document.getElementById("image2").innerText = 2; } function q23(){ dusrc2 = sinduy; document.getElementById("image2").innerText = 3; } function q24(){ dusrc2 = sindun; document.getElementById("image2").innerText = 4; } function q25(){ dusrc2 = pill; document.getElementById("image2").innerText = 5; } function q26(){ dusrc2 = nugulman; document.getElementById("image2").innerText = 6; }
마지막으로 듀자이크 이미지의 기본값을 지정하고
이를 버튼을 누르면 변경하는 함수를 마지막에 넣어주면 끝!
메이플스토리 인벤 : ㅎㅂ)듀자이크 사이트 만들어왔어 - 메이플스토리 인벤 자유게시판
어제 이거 만들어서 올린 새끼입니다듀자이크를 쉽게 넣는 사이트도 심심해서 한번 만들어봤습니다이런짓을 왜하냐구요?그야... 재밌으니까...https://gillyongs.github.io/github.io-dualblade/사이트 링크
www.inven.co.kr
커뮤니티에 공유한 결과
반응은 다른 의미로 폭발적(...)
https://gillyongs.github.io/github.io-dualblade/
title
gillyongs.github.io
사이트 링크.
'토이 프로젝트' 카테고리의 다른 글
네모네모 멈뭄미 변환기 사이트 만들기 (0) 2022.03.23 포켓몬 빵 시뮬레이터 만들기 (0) 2022.03.23 짤방 생성기 만들기 (0) 2022.03.21 러브라떼 변환기 업데이트 (1) 2022.03.21 러브라떼 변환기 개발일지 (4) 2022.03.19