const canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.lineJoin = 'round';
ctx.fillStyle = 'black';
var previous,
inputSize = document.querySelector("[name='size']"),
rect;
function Paint(elem) {
var x,
y,
width,
height;
this.image = {
x: 0,
y: 0,
color: 'black',
tool: null,
coordsOfCanvas: () => {
return canvas.getBoundingClientRect();
},
};
this.mouseDown = false;
this.pencil = () => {
this.image.tool = 'pencil';
ctx.lineWidth = inputSize.value = '5';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
inputSize.parentNode.style.display = 'table-cell';
};
this.brush = () => {
this.image.tool = 'brush';
ctx.lineWidth = inputSize.value = '25';
ctx.lineCap = 'butt';
ctx.strokeStyle = 'black';
inputSize.parentNode.style.display = 'table-cell';
};
this.fill = () => {
this.image.tool = 'fill';
ctx.fillStyle = 'black'
inputSize.parentNode.style.display = 'none';
};
this.clear = () => {
this.image.tool = 'clear';
ctx.strokeStyle = 'white';
ctx.lineWidth = inputSize.value = '20';
ctx.lineCap = 'butt';
inputSize.parentNode.style.display = 'table-cell';
};
this.rectangle = () => {
this.image.tool = 'rectangle';
inputSize.parentNode.style.display = 'none';
};
//Координаты мыши относительно canvas
this.getCoords = () => {
this.image.x = event.clientX - this.image.coordsOfCanvas().left;
this.image.y = event.clientY - this.image.coordsOfCanvas().top;
}
elem.addEventListener('mousedown', () => {
this.mouseDown = true;
this.getCoords();
if (this.image.tool == 'fill') {
ctx.fillRect(0, 0, canvas.width, canvas.height);
} else if ((this.image.tool == 'pencil' ||
this.image.tool == 'brush' ||
this.image.tool == 'clear') && this.mouseDown) {
ctx.beginPath();
ctx.moveTo(this.image.x, this.image.y);
} else if (this.image.tool == 'rectangle' && this.mouseDown) {
//Фиксируем начальные координаты
x = this.image.x;
y = this.image.y;
}
elem.addEventListener('mousemove', () => {
this.getCoords();
if ((this.image.tool == 'pencil' ||
this.image.tool == 'brush' ||
this.image.tool == 'clear') && this.mouseDown) {
ctx.lineWidth = inputSize.value;
ctx.lineTo(this.image.x, this.image.y);
ctx.stroke();
}
if (this.image.tool == 'rectangle' && this.mouseDown) {
ctx.clearRect(x, y, width - x, height - y)
ctx.fillRect(x, y, this.image.x - x, this.image.y - y)
ctx.fillStyle = 'black'
//Сохраняем предыдущие координаты мыши
width = this.image.x;
height = this.image.y;
}
});
});
elem.addEventListener('mouseup', () => {
this.mouseDown = false;
if (this.image.tool == 'rectangle') {
x = y = height = width = null;
}
});
document.body.addEventListener('click', () => {
let target = event.target;
let action = target.getAttribute('data-type');
if (action) {
if (previous) {
previous.classList.remove('active');
}
target.classList.add('active');
previous = target;
this[action]();
};
});
};
new Paint(canvas);
body {
position: relative;
min-height: 100vh;
background: gray;
margin: 0;
}
.draw {
position: absolute;
top: 0;
right: 10%;
bottom: 0;
left: 10%;
display: flex;
justify-content: center;
}
.options {
position: absolute;
top: 0;
right: 0;
left: 48px;
height: 48px;
background: #575a5e;
z-index: 1;
}
.options label {
display: block;
}
.options ul {
list-style: none;
margin: 0;
margin-left: -40px;
}
.options ul li {
display: none;
height: 48px;
color: white;
font-size: 14px;
padding: 0 5px;
vertical-align: middle;
}
.tools {
position: absolute;
top: 0%;
left: 0%;
bottom: 0%;
width: 48px;
background: #575a5e;
z-index: 2;
}
.tools>div {
width: 48px;
height: 48px;
}
.tools div:hover {
cursor: pointer;
}
.pencil {
background: url('icons.png');
background-position-x: 0;
}
.brush {
background: url('icons.png');
background-position-x: -48px;
}
.clear {
background: url('icons.png');
background-position-x: -96px;
}
.fill {
background: url('icons.png');
background-position-x: -144px;
}
.rectangle {
background: url('icons.png');
background-position-x: -48px;
background-position-y: -48px;
}
.active {
background-color: #cdd0d6;
}
canvas {
border: 1px solid black;
background: white;
margin-top: 150px;
margin-bottom: 150px;
}
<div class='tools'>
<div class='pencil' data-type='pencil'></div>
<div class='brush' data-type='brush'></div>
<div class='fill' data-type='fill'></div>
<div class='clear' data-type='clear'></div>
<div class='rectangle' data-type='rectangle' style='background: green'></div>
</div>
<div class='options'>
<ul>
<li class='size'>
<label for="size">Size(1-50): </label>
<input type="number" id="size" name='size' min="1" max="50" value=''>
</li>
</ul>
</div>
<div class='draw'>
<canvas width='800px' height='500px' id='canvas'></canvas>
</div>
У меня 2 вопроса:
1) Возможно ли как-нибудь образом реализовать наложение рисованных фигур одну на вторую? На данный момент, если наложить 1 прямоугольник на 2, не отпуская лкм, а затем 1-ому уменьшить размер - сотрёт часть уже нарисованного.
2) Если нарисовать несколько прямоугольников, некоторые их части пропадают с canvas чудесным образом :) Из-за чего?
P.S. Выбрать рисование прямоугольником - нажать на зелёный div
Вот примерно то, о чем я писал в комментарии
let a, c = canvas.getContext('2d'), s = canvas.width, r = [];
canvas.addEventListener('mousedown', e =>
r.push(a = [e.x,e.y,0,0,`hsl(${Math.random()*360},55%,55%)`]));
canvas.addEventListener('mouseup', e => a = null);
canvas.addEventListener('mousemove', e => {
if (!a) return;
a[2] = e.x - a[0], a[3] = e.y - a[1];
c.clearRect(0, 0, s, s);
let t = new Date;
r.forEach(r => (c.fillStyle = r[4]) && c.fillRect(...r));
c.fillText(r.length + ' - ' + (new Date - t) + 'ms', 3, 10);
})
body{margin:0}canvas{background-color:rgba(0,0,0,0.05)}
<canvas id="canvas" width="635" height="175"></canvas>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Проблема в том, что IntersectionObserver API не работает в декстопной версии на VueКак только включаешь режим Mobile, всё грузится
Можно ли как-нибудь получить значение элемента на который я нажал? (при нажатии на блок со значением 1 выводило 1, 2-2, 3-3 и тд)