ctx.lineWidth= 2;
const colors = [
"red", "lime", "blue", "yellow"
]
function onClick(event){
ctx.beginPath();
ctx.moveTo(0,0);
const color = colors[Math.floor(Math.random()*colors.length)];
ctx.strokeStyle = color;
ctx.lineTo(event.offsetX, event.offsetY);
ctx.stroke()
canvas.addEventListener("click", onClick)
}
lineWidth로 브러쉬 두께 잡아주고
lineTo로 클릭시, 그릴 위치 잡아준다.
OffsetX, offsetY는 console.log(event)했을때, 마우스 현 좌표 요소인걸 알 수 있다.
클릭이 아니라 마우스 따라오면서 그려지는걸 하고싶다면, event에서 "click" => "mousemove"
ctx.lineWidth= 2;
let isPainting = false;
function onMove(event){
if(isPainting){
ctx.lineTo(event.offsetX, event.offsetY);
ctx.stroke();
return;
}
ctx.moveTo(event.offsetX, event.offsetY);
}
function onMouseDown(){
isPainting = true;
}
function onMouseUp(){
isPainting = false;
}
canvas.addEventListener("mousemove", onMove);
canvas.addEventListener("mousedown", onMouseDown);
canvas.addEventListener("mouseup", onMouseUp);
마우스를 누르고 이동 있을때는 선 그리기진행 (lineTo)
마우스 떼고 이동 있을때는 손만 이동중 (moveTo) -> 그래야 mousedown 이벤트 일어났을때, 곧바로 그 자리부터 그리기 시작이 되니까
하지만, 그리다가 캔버스 밖으로 뛰쳐나갔을때, onMouseUp 이벤트 실행이 안된다. 다시 마우스가 돌아왔을 때, 여전히 mouseDown상태라 계속 그리게된다.
'다'에서 뛰쳐나갔다가 들어오니까 계속 actvie 상태!
Solution1.
canvas.addEventListener("mouseup", onMouseUp);
canvas.addEventListener("mouseleave", onMouseUp)
이렇게 canvas 영역 떠나면 무조건 onMouseUp이벤트 발생시키게 하거나
Solution2.
document.addEventListener("mouseup", onMouseUp);
document에서 일어나는 모든 mouseUp은 canvas안이든 밖이든 다 인식
우선 html에 선두께 선택하게 input만든다.
<canvas></canvas>
<input id="line-width" type="range" min="1" max="10" value="5" step="0.5"/>
그리고는 javascript로 line-width id가진 element의 value값을 가져와서 ctx의 두께로 던져준다.
const lineWidth = document.getElementById("line-width")
canvas.width = 800;
canvas.height = 800;
ctx.lineWidth= lineWidth.value;
function onLineWidthChange(event){
ctx.lineWidth = event.target.value;
}
lineWidth.addEventListener("change", onLineWidthChange)
<input id="color" type="color"/>
이경우, 팔레트 전체를 줘서 유저 마음대로 선택 가능하게
const color = document.getElementById("color")
function onColorChange(event){
ctx.strokeStyle = event.target.value;
}
color.addEventListener("change", onColorChange)
위와 거의 동일하다.
color id갖는 element 데려와서 이번에는 stroke Color로 쓴다.
<input id="color" type="color"/>
<div class="color-option" style="background-color: #1abc9c;" data-color="#1abc9c"></div>
<div class="color-option" style="background-color: #3498db;" data-color="#3498db"></div>
<div class="color-option" style="background-color: #34495e;" data-color="#34495e"></div>
<div class="color-option" style="background-color: #27ae60;" data-color="#27ae60"></div>
<div class="color-option" style="background-color: #8e44ad;" data-color="#8e44ad"></div>
<div class="color-option" style="background-color: #f1c40f;" data-color="#f1c40f"></div>
<div class="color-option" style="background-color: #e74c3c;" data-color="#e74c3c"></div>
<div class="color-option" style="background-color: #95a5a6;" data-color="#95a5a6"></div>
<div class="color-option" style="background-color: #d35400;" data-color="#d35400"></div>
<div class="color-option" style="background-color: #bdc3c7;" data-color="#bdc3c7"></div>
<div class="color-option" style="background-color: #2ecc71;" data-color="#2ecc71"></div>
<div class="color-option" style="background-color: #e67e22;" data-color="#e67e22"></div>
.color-option{
width: 50px;
height: 50px;
cursor: pointer;
}
이렇게 주면은 일단 화면에 나타나긴해.
그리고서는 javascript로 가서 색 선택 했을때, data-color를 브러쉬 색으로 쓰게 만들자.
살짝 복잡!
const colorOption = Array.from(document.getElementsByClassName("color-option"));
getElementsByClassName으로 데려오면, 같은 class값 가진 애들이 다 오긴 하지만, Array가 아니라서 쓰기 더러워.
Array.from으로 오는 값들을 array로 정리해 놓는거야.
colorOption.forEach(color=> color.addEventListener("click", onColorClick))
이미지 색상자 하나 누를 때 마다 반응 일어나길 바라니까!
function onColorClick(event){
//console.dir(event.target) 으로 하면은 dataset안에 color로 들어가 있는걸 발견!
ctx.strokeStyle = event.target.dataset.color;
// ctx.fillStyle = event.target.dataset.color);
}
html에서처럼 "data-어쩌고" 이렇게 값을 주면, dataset안에 "어쩌고":"렐렐렐" 이렇게 들어가.
이 렐렐렐을 갖다 strokeStyle로 쓰는거지.
마지막으로,
color.value = event.target.dataset.color
이걸 onColorClick안에 넣어주면, 유저가 색상자 선택했을때, 가장 왼쪽 색선택 박스가 바뀌게 할 수 있어.
<button id="mode-btn">Fill</button>
이 버튼으로 붓<->페인팅통 똑딱똑딱한다.
const modeBtn = document.getElementById("mode-btn");
function onModeClick(){
if(isFilling){
isFilling = false;
modeBtn.innerText="fill";
}else{
isFilling=true;
modeBtn.innerText="draw";
}
}
modeBtn.addEventListener("click", onModeClick);
function onCanvasClick(){
if(isFilling){
ctx.fillRect(0,0,800,800);
}
}
canvas.addEventListener("click",onCanvasClick);
만약에 isFilling버튼이 켜있으면은 채우기 고고
const destroyBtn = document.getElementById("destroy-btn");
function onDestroyClick(){
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
const eraserBtn = document.getElementById("eraser-btn");
let backColor = "turquoise";
function onCanvasClick(){
if(isFilling){
ctx.fillRect(0,0,800,800);
backColor = ctx.fillStyle;
}
}
function onEraser(){
isFilling = false;
ctx.strokeStyle = backColor;
}
default값으로 turquoise를 주긴 했지만은, 이전에 배경 채우기 한 경력이 있다면은 그걸 쓰기위해 backColor
is filling 주는거는, brush/paint 중 paint 선택인 상태에서 지우개 들어간다면, brush처럼 부분적으로 지우기가 안되거든.
function onDestroyClick(){
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
backColor = "turquoise";
}
끝
function onSave(){
const url = canvas.toDataURL();
const a = document.createElement("a");
console.log(url);
a.href = url
a.download = "myDrawing.png"
a.click();
}
끝
다음 스텝은 저 url로 firebase에 저장할 수 있는가 실험