[html]<style>
/* === Основные стили контейнеров === */
#paintContainer {
position: relative;
display: block;
width: 100%;
max-width: 100%;
}
#overlayImage {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: auto;
pointer-events: none;
user-select: none;
z-index: 2;
}
#paintCanvas {
width: 100%;
height: auto;
border: 1px solid #ccc; /* Более светлая рамка */
display: block;
z-index: 1;
cursor: crosshair; /* Курсор для рисования */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Легкая тень для холста */
border-radius: 8px;
}
/* === Панель инструментов (Toolbar) === */
.toolbar {
margin-top: 20px;
padding: 15px;
background: #f4f4f4; /* Светлый фон */
border-radius: 12px; /* Закругленные углы */
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1); /* Более выраженная тень */
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: center;
font-family: Arial, sans-serif;
}
/* === Палитра === */
.palette {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 5px 0;
}
.color {
width: 26px; /* Чуть больше */
height: 26px;
border-radius: 50%;
border: 2px solid transparent; /* Прозрачная рамка для состояния неактивности */
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.color:hover {
transform: scale(1.1);
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
}
.color.active {
border-color: #333; /* Четкая рамка для выбранного цвета */
transform: scale(1.15);
}
/* === Кнопки === */
button {
padding: 8px 15px;
border-radius: 8px;
border: none;
background: #ffffff;
color: #333;
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s, transform 0.1s, box-shadow 0.2s;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
gap: 5px;
}
button:hover {
background: #e0e0e0;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
button:active {
transform: scale(0.98);
}
/* === Инпут цвета и Размера === */
#customColor {
width: 30px;
height: 30px;
padding: 0;
border: 2px solid #ccc;
border-radius: 50%;
cursor: pointer;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
#customColor::-webkit-color-swatch {
border-radius: 50%;
border: none;
}
#customColor::-moz-color-swatch {
border-radius: 50%;
border: none;
}
.toolbar label {
display: flex;
align-items: center;
gap: 10px;
font-weight: 500;
white-space: nowrap;
}
#brushSize {
width: 120px;
cursor: pointer;
}
</style>
<div id="paintContainer">
<canvas id="paintCanvas"></canvas>
<img id="overlayImage" src="https://upforme.ru/uploads/001c/80/ee/3/30321.png">
</div>
<div class="toolbar">
<div class="palette" id="palette"></div>
<input type="color" id="customColor" value="#000000" title="Выбрать свой цвет">
<label>
Размер:
<input type="range" id="brushSize" min="5" max="100" value="20">
</label>
<button id="hardBrush">✏️ Жесткая</button>
<button id="softBrush">💨 Мягкая</button>
<button id="eraser">🩹 Ластик</button>
<button id="saveProgress">💾 Сохранить</button>
<button id="clearCanvas">🧹 Очистить</button>
</div>
<script>
(function() {
const canvas = document.getElementById("paintCanvas");
const ctx = canvas.getContext("2d");
const img = document.getElementById("overlayImage");
const brushSizeInput = document.getElementById("brushSize");
const customColorInput = document.getElementById("customColor");
let painting = false;
let brushType = "hard";
let currentColor = customColorInput.value;
let erasing = false;
// --- Утилиты для стилизации активных элементов ---
function setActiveColor(targetColor) {
document.querySelectorAll('.color').forEach(el => el.classList.remove('active'));
currentColor = targetColor;
erasing = false;
}
function setActivePaletteColor(el, color) {
setActiveColor(color);
el.classList.add('active');
customColorInput.value = color; // Обновляем инпут цвета
}
// === Палитра ===
const colors = [
"#000000", "#ffffff", "#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ff00ff", "#00ffff",
"#808080", "#804000", "#ff8000", "#8000ff", "#0080ff", "#80ff00", "#ff0080", "#008080",
"#404040", "#c0c0c0", "#a52a2a", "#add8e6"
];
const palette = document.getElementById("palette");
colors.forEach(c => {
const el = document.createElement("div");
el.className = "color";
el.style.backgroundColor = c;
el.onclick = () => setActivePaletteColor(el, c);
palette.appendChild(el);
});
// Изначальная активация первого цвета (черного)
if (palette.firstChild) {
palette.firstChild.classList.add('active');
}
customColorInput.oninput = e => setActiveColor(e.target.value);
// === Настройки ===
document.getElementById("hardBrush").onclick = () => { brushType = "hard"; erasing = false; setActiveColor(customColorInput.value); };
document.getElementById("softBrush").onclick = () => { brushType = "soft"; erasing = false; setActiveColor(customColorInput.value); };
document.getElementById("eraser").onclick = () => { erasing = true; document.querySelectorAll('.color').forEach(el => el.classList.remove('active')); };
document.getElementById("clearCanvas").onclick = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
localStorage.removeItem("coloringProgress");
};
document.getElementById("saveProgress").onclick = () => {
localStorage.setItem("coloringProgress", canvas.toDataURL());
alert("✅ Прогресс сохранён!");
};
// Обработчики кнопок showCode и copyCode удалены.
// === Размер под страницу ===
function resizeCanvas() {
if (img.naturalWidth === 0) return;
const ratio = img.naturalWidth / img.naturalHeight;
const container = document.getElementById("paintContainer");
const clientWidth = container.clientWidth;
canvas.width = clientWidth;
canvas.height = clientWidth / ratio;
restoreProgress();
}
img.onload = resizeCanvas;
window.onresize = resizeCanvas;
if (img.complete) {
resizeCanvas();
}
// === Рисование ===
function startDraw(e) { painting = true; draw(e); }
function endDraw() { painting = false; ctx.beginPath(); saveProgress(); }
function draw(e) {
if (!painting) return;
const rect = canvas.getBoundingClientRect();
const clientX = e.clientX || e.touches?.[0]?.clientX;
const clientY = e.clientY || e.touches?.[0]?.clientY;
if (clientX === undefined || clientY === undefined) return;
const x = clientX - rect.left;
const y = clientY - rect.top;
const brushSize = brushSizeInput.value;
if (brushType === "soft") {
softStroke(x, y, brushSize);
} else if (erasing) {
ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
ctx.arc(x, y, brushSize / 2, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
} else {
ctx.globalCompositeOperation = "source-over";
ctx.lineWidth = brushSize;
ctx.lineCap = "round";
ctx.strokeStyle = currentColor;
ctx.globalAlpha = 1;
ctx.lineTo(x, y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x, y);
}
}
// === Мягкая кисть ===
function softStroke(x, y, size) {
const hexToRgb = hex => {
const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? `${parseInt(result[1], 16)},${parseInt(result[2], 16)},${parseInt(result[3], 16)}` : '0,0,0';
};
const rgbColor = hexToRgb(erasing ? '#ffffff' : currentColor);
const grd = ctx.createRadialGradient(x, y, 0, x, y, size / 2);
grd.addColorStop(0, `rgba(${rgbColor}, 0.8)`);
grd.addColorStop(1, `rgba(${rgbColor}, 0)`);
ctx.globalCompositeOperation = erasing ? 'destination-out' : 'source-over';
ctx.globalAlpha = 0.4;
ctx.fillStyle = grd;
ctx.beginPath();
ctx.arc(x, y, size / 2, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
}
// === Сохранение/Восстановление прогресса ===
function saveProgress() {
localStorage.setItem("coloringProgress", canvas.toDataURL());
}
function restoreProgress() {
const saved = localStorage.getItem("coloringProgress");
if (saved) {
const imgData = new Image();
imgData.onload = () => ctx.drawImage(imgData, 0, 0, canvas.width, canvas.height);
imgData.src = saved;
}
}
// === События ===
canvas.addEventListener("mousedown", startDraw);
canvas.addEventListener("mouseup", endDraw);
canvas.addEventListener("mouseout", endDraw);
canvas.addEventListener("mousemove", draw);
canvas.addEventListener("touchstart", startDraw);
canvas.addEventListener("touchend", endDraw);
canvas.addEventListener("touchcancel", endDraw);
canvas.addEventListener("touchmove", draw);
})();
</script>[/html]


















































