(() => {
'use strict';
new class {
#canvas = document.querySelector('canvas');
#penColor = document.getElementById('penColor');
#penMode = document.getElementById('penMode');
#penWidth = document.getElementById('penWidth');
#penClear = document.getElementById('penClear');
#penWidthList = [5, 10, 20, 40];
#cursor = [
'url(./image/cursor_pen5.svg) 2.5 2.5, pointer',
'url(./image/cursor_pen10.svg) 5 5, pointer',
'url(./image/cursor_pen20.svg) 10 10, pointer',
'url(./image/cursor_pen40.svg) 20 20, pointer',
];
#ctx;
#lineWidth = 5;
#isDrawing = false;
#lastX = 0;
#lastY = 0;
#resizeTimer = null;
constructor() {
this.#ctx = this.#canvas.getContext('2d');
this.#init();
}
#init() {
window.addEventListener('resize', () => {
clearTimeout(this.#resizeTimer);
this.#resizeTimer = setTimeout(() => {
this.#onResize();
}, 500);
});
this.#onResize();
this.#penColor.addEventListener('change', () => {
this.#penMode.shadowRoot.querySelector('label').click();
});
this.#penClear.addEventListener('click', () => {
this.#ctx.clearRect(0, 0, this.#canvas.width, this.#canvas.height);
});
this.#penMode.addEventListener('click', () => {
if (this.#penMode.getAttribute('value') == '0') {
this.#penWidth.shadowRoot.querySelector('label').click();
} else {
this.#penWidth.shadowRoot.querySelectorAll('label')[3].click();
}
this.#setCanvasCursor();
});
this.#penWidth.addEventListener('change', () => {
this.#setCanvasCursor();
});
this.#canvas.addEventListener('mouseover', () => {
this.#setCanvasCursor();
});
this.#canvas.addEventListener('mousedown', (event) => {
this.#startDrawing(event.offsetX, event.offsetY);
});
this.#canvas.addEventListener('mouseup', () => {
this.#stopDrawing();
});
this.#canvas.addEventListener('mouseleave', () => {
this.#stopDrawing();
});
this.#canvas.addEventListener('mousemove', (event) => {
if (this.#isDrawing) {
this.#draw(event.offsetX, event.offsetY);
}
});
this.#canvas.addEventListener('touchstart', (event) => {
const touch = event.touches[0];
const rect = this.#canvas.getBoundingClientRect();
this.#startDrawing(touch.clientX - rect.left, touch.clientY - rect.top);
});
this.#canvas.addEventListener('touchend', () => {
this.#stopDrawing();
});
this.#canvas.addEventListener('touchcancel', () => {
this.#stopDrawing();
});
this.#canvas.addEventListener('touchmove', (event) => {
if (this.#isDrawing) {
const touch = event.touches[0];
const rect = this.#canvas.getBoundingClientRect();
this.#draw(touch.clientX - rect.left, touch.clientY - rect.top);
}
});
}
#startDrawing(x, y) {
this.#isDrawing = true;
this.#drawCircle(x, y);
[this.#lastX, this.#lastY] = [x, y];
}
#stopDrawing() {
this.#isDrawing = false;
this.#ctx.beginPath();
}
#draw(x, y) {
this.#drawCircle(x, y);
this.#ctx.lineWidth = this.#penWidthList[this.#penWidth.getAttribute('value')];
if (this.#penMode.getAttribute('value') == '0') {
this.#ctx.strokeStyle = this.#penColor.value;
}
this.#ctx.beginPath();
this.#ctx.moveTo(this.#lastX, this.#lastY);
this.#ctx.lineTo(x, y);
this.#ctx.stroke();
[this.#lastX, this.#lastY] = [x, y];
}
#drawCircle(x, y) {
const radius = this.#penWidthList[this.#penWidth.getAttribute('value')] / 2;
this.#ctx.beginPath();
this.#ctx.arc(x, y, radius, 0, Math.PI * 2);
if (this.#penMode.getAttribute('value') == '0') {
this.#ctx.fillStyle = this.#penColor.value;
this.#ctx.globalCompositeOperation = 'source-over';
this.#ctx.fill();
} else {
this.#ctx.globalCompositeOperation = 'destination-out';
this.#ctx.fillStyle = 'rgba(0, 0, 0, 1)';
this.#ctx.fill();
}
}
#setCanvasCursor() {
this.#canvas.style.cursor = this.#cursor[this.#penWidth.getAttribute('value')];
}
#onResize() {
this.#canvas.width = '';
this.#canvas.height = '';
const rect = this.#canvas.getBoundingClientRect();
this.#canvas.width = rect.width;
this.#canvas.height = rect.height;
}
}
})();