166 行
4.6 KiB
JavaScript
166 行
4.6 KiB
JavaScript
|
|
//ほとんど理解できない
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
const canvas = document.getElementById('canvas');
|
|
const context = canvas.getContext('2d');
|
|
const colorPicker = document.getElementById('colorPicker');
|
|
const currentColorDisplay = document.getElementById('currentColorDisplay');
|
|
const R = document.getElementById('R');
|
|
const G = document.getElementById('G');
|
|
const B = document.getElementById('B');
|
|
const thicknessSlider = document.getElementById('thicknessSlider');
|
|
const undo_btn = document.getElementById('undo_btn');
|
|
const redo_btn = document.getElementById('redo_btn');
|
|
const clear_btn = document.getElementById('clear_btn');
|
|
const download_btn = document.getElementById('download_btn');
|
|
const eraser_btn = document.getElementById('eraser_btn');
|
|
|
|
let isDrawing = false;
|
|
let isErasing = false;
|
|
let undoStack = [];
|
|
let redoStack = [];
|
|
|
|
function initColorPicker(){
|
|
updateColorDisplay();
|
|
R.addEventListener('input', updateColorDisplay);
|
|
G.addEventListener('input', updateColorDisplay);
|
|
B.addEventListener('input', updateColorDisplay);
|
|
}
|
|
|
|
function updateColorDisplay(){
|
|
const red = R.value;
|
|
const green = G.value;
|
|
const blue = B.value;
|
|
const color = `rgb(${red},${green},${blue})`;
|
|
currentColorDisplay.style.backgroundColor = color;
|
|
context.strokeStyle = color;
|
|
cv.setAttribute('style', 'color:rgb('+R.value+','+G.value+','+B.value+');');
|
|
}
|
|
|
|
function getColorFromPicker(){
|
|
const red = R.value;
|
|
const green = G.value;
|
|
const blue = B.value;
|
|
return `rgb(${red},${green},${blue})`;
|
|
}
|
|
|
|
function startDrawing(event){
|
|
if (isErasing) {
|
|
context.globalCompositeOperation = 'destination-out';
|
|
} else {
|
|
context.globalCompositeOperation = 'source-over';
|
|
updateColorDisplay();
|
|
}
|
|
isDrawing = true;
|
|
context.beginPath();
|
|
context.moveTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop);
|
|
|
|
}
|
|
|
|
function stopDrawing(){
|
|
isDrawing = false;
|
|
context.closePath();
|
|
saveState();
|
|
}
|
|
|
|
function draw(event){
|
|
if (!isDrawing) return;
|
|
context.lineWidth = thicknessSlider.value;
|
|
context.lineTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop);
|
|
context.stroke();
|
|
context.beginPath();
|
|
context.moveTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop);
|
|
}
|
|
|
|
function clearCanvas(){
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
saveState();
|
|
}
|
|
|
|
function downloadImage(){
|
|
const dataUrl = canvas.toDataURL('image/png');
|
|
const link = document.createElement('a');
|
|
link.href = dataUrl;
|
|
link.download = 'draw.png';
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
}
|
|
|
|
function saveState(){
|
|
undoStack.push(canvas.toDataURL());
|
|
redoStack = [];
|
|
updateUndoRedoButtons();
|
|
}
|
|
|
|
function updateUndoRedoButtons(){
|
|
undo_btn.disabled = undoStack.length === 0;
|
|
redo_btn.disabled = redoStack.length === 0;
|
|
}
|
|
|
|
function undo(){
|
|
if (undoStack.length > 1){
|
|
redoStack.push(undoStack.pop());
|
|
const img = new Image();
|
|
img.src = undoStack[undoStack.length - 1];
|
|
img.onload = function(){
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
context.drawImage(img, 0, 0);
|
|
updateUndoRedoButtons();
|
|
};
|
|
}
|
|
}
|
|
|
|
function redo(){
|
|
if (redoStack.length > 0){
|
|
undoStack.push(redoStack.pop());
|
|
const img = new Image();
|
|
img.src = undoStack[undoStack.length - 1];
|
|
img.onload = function(){
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
context.drawImage(img, 0, 0);
|
|
updateUndoRedoButtons();
|
|
};
|
|
}
|
|
}
|
|
|
|
function toggleEraser() {
|
|
isErasing = !isErasing;
|
|
eraser_btn.textContent = isErasing ? 'ペン' : '消しゴム';
|
|
}
|
|
|
|
canvas.addEventListener('mousedown', startDrawing);
|
|
canvas.addEventListener('mouseup', stopDrawing);
|
|
canvas.addEventListener('mouseout', stopDrawing);
|
|
canvas.addEventListener('mousemove', draw);
|
|
thicknessSlider.addEventListener('input', saveState);
|
|
undo_btn.addEventListener('click', undo);
|
|
redo_btn.addEventListener('click', redo);
|
|
clear_btn.addEventListener('click', clearCanvas);
|
|
download_btn.addEventListener('click', downloadImage);
|
|
eraser_btn.addEventListener('click', toggleEraser);
|
|
|
|
initColorPicker();
|
|
|
|
canvas.addEventListener('touchstart', function (event){
|
|
event.preventDefault();
|
|
startDrawing({ clientX: event.touches[0].clientX, clientY: event.touches[0].clientY });
|
|
});
|
|
|
|
canvas.addEventListener('touchend', function (event){
|
|
event.preventDefault();
|
|
stopDrawing();
|
|
});
|
|
|
|
canvas.addEventListener('touchmove', function (event){
|
|
event.preventDefault();
|
|
draw({clientX:event.touches[0].clientX, clientY: event.touches[0].clientY});
|
|
});
|
|
|
|
context.lineJoin = 'round';
|
|
context.lineCap = 'round';
|
|
context.strokeStyle = getColorFromPicker();
|
|
context.lineWidth = thicknessSlider.value;
|
|
saveState();
|
|
});
|