To są zaledwie 3 prompty:
- Zbuduj MS Paint z zaawansowanymi ustawieniami. Użyj CSS, JS i HTML w jednym pliku HTML - 19s
- Dodaj funkcje "cofnij" "wróć" zmianę - 32s
- Niech UI programu korzysta z kolorystyki serwisu 4programmers.net 32s
Wszystko zadziałało przy pierwszej próbie odpalenia. Zero bugów. Czy to nie jest gigantyczny postęp?
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8" />
<title>Advanced MS Paint z Cofnij/Wróć</title>
<style>
/* Ogólna kolorystyka inspirowana 4programmers.net */
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #ecf0f1; /* jasny szary */
}
/* Pasek narzędzi – ciemne tło z jasnym tekstem */
#toolbar {
background-color: #2c3e50; /* ciemny niebiesko-szary */
color: #ecf0f1; /* jasny tekst */
padding: 10px;
display: flex;
flex-wrap: wrap;
align-items: center;
}
#toolbar > * {
margin: 5px;
}
#toolbar label {
margin-right: 5px;
}
/* Stylizacja pól wyboru, inputów i select */
#toolbar input[type="color"],
#toolbar input[type="range"],
#toolbar select {
padding: 5px;
border-radius: 3px;
border: none;
}
/* Przyciski – pomarańczowe akcenty */
#toolbar button {
background-color: #d35400; /* intensywny pomarańczowy */
color: #ecf0f1;
border: none;
padding: 8px 12px;
cursor: pointer;
border-radius: 3px;
transition: background-color 0.3s;
}
#toolbar button:hover {
background-color: #e67e22;
}
/* Kontener płótna */
#canvasContainer {
position: relative;
border: 1px solid #bdc3c7;
margin: 10px auto;
background-color: #fff;
width: 800px;
height: 600px;
}
canvas {
position: absolute;
left: 0;
top: 0;
}
/* Główny canvas (na spodzie) */
#canvas {
z-index: 1;
}
/* Tymczasowy canvas do podglądu kształtów */
#tempCanvas {
z-index: 2;
}
</style>
</head>
<body>
<div id="toolbar">
<label for="tool">Narzędzie:</label>
<select id="tool">
<option value="pencil">Ołówek</option>
<option value="line">Linia</option>
<option value="rectangle">Prostokąt</option>
<option value="circle">Koło</option>
<option value="eraser">Gumka</option>
</select>
<label for="brushSize">Grubość pędzla:</label>
<input type="range" id="brushSize" min="1" max="50" value="5" />
<label for="strokeColor">Kolor obrysu:</label>
<input type="color" id="strokeColor" value="#000000" />
<label for="fillColor">Kolor wypełnienia:</label>
<input type="color" id="fillColor" value="#000000" />
<label for="fillShape">Wypełnienie:</label>
<input type="checkbox" id="fillShape" />
<button id="clearCanvas">Wyczyść</button>
<button id="saveCanvas">Zapisz</button>
<button id="undo">Cofnij</button>
<button id="redo">Wróć</button>
</div>
<div id="canvasContainer">
<canvas id="canvas" width="800" height="600"></canvas>
<canvas id="tempCanvas" width="800" height="600"></canvas>
</div>
<script>
// Pobierz elementy i konteksty
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const tempCanvas = document.getElementById('tempCanvas');
const tempCtx = tempCanvas.getContext('2d');
const toolSelect = document.getElementById('tool');
const brushSize = document.getElementById('brushSize');
const strokeColor = document.getElementById('strokeColor');
const fillColor = document.getElementById('fillColor');
const fillShape = document.getElementById('fillShape');
const clearCanvasBtn = document.getElementById('clearCanvas');
const saveCanvasBtn = document.getElementById('saveCanvas');
const undoBtn = document.getElementById('undo');
const redoBtn = document.getElementById('redo');
let drawing = false;
let currentTool = toolSelect.value;
let startX = 0, startY = 0;
// Stosy do cofania i ponawiania zmian
let undoStack = [];
let redoStack = [];
// Zapisz aktualny stan płótna
function pushState() {
// Nowe działanie – czyścimy stos do ponawiania
redoStack = [];
// Zapisujemy aktualny stan (ImageData)
undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
}
function undo() {
if (undoStack.length > 0) {
// Zapisz bieżący stan do stosu "redo"
redoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
// Przywróć ostatni stan
const state = undoStack.pop();
ctx.putImageData(state, 0, 0);
}
}
function redo() {
if (redoStack.length > 0) {
// Zapisz bieżący stan do stosu "undo"
undoStack.push(ctx.getImageData(0, 0, canvas.width, canvas.height));
// Przywróć ostatni stan ze stosu "redo"
const state = redoStack.pop();
ctx.putImageData(state, 0, 0);
}
}
// Inicjalizacja – zapis pustego płótna
pushState();
// Aktualizacja narzędzia przy zmianie wyboru
toolSelect.addEventListener('change', function () {
currentTool = this.value;
});
// Obsługa zdarzeń myszy na tymczasowym canvasie
tempCanvas.addEventListener('mousedown', startDrawing);
tempCanvas.addEventListener('mousemove', draw);
tempCanvas.addEventListener('mouseup', finishDrawing);
tempCanvas.addEventListener('mouseout', finishDrawing);
function getMousePos(e) {
const rect = tempCanvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top,
};
}
function startDrawing(e) {
drawing = true;
const pos = getMousePos(e);
startX = pos.x;
startY = pos.y;
// Dla narzędzi typu "pencil" i "eraser" zaczynamy natychmiast ścieżkę
if (currentTool === 'pencil' || currentTool === 'eraser') {
ctx.beginPath();
ctx.moveTo(startX, startY);
}
}
function draw(e) {
if (!drawing) return;
const pos = getMousePos(e);
const mouseX = pos.x;
const mouseY = pos.y;
if (currentTool === 'pencil') {
ctx.lineTo(mouseX, mouseY);
ctx.strokeStyle = strokeColor.value;
ctx.lineWidth = brushSize.value;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.stroke();
} else if (currentTool === 'eraser') {
ctx.globalCompositeOperation = 'destination-out';
ctx.lineTo(mouseX, mouseY);
ctx.strokeStyle = 'rgba(0,0,0,1)';
ctx.lineWidth = brushSize.value;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.stroke();
ctx.globalCompositeOperation = 'source-over';
} else {
// Dla narzędzi kształtów – czyścimy podgląd i rysujemy tymczasowy kształt
tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
tempCtx.lineWidth = brushSize.value;
tempCtx.strokeStyle = strokeColor.value;
tempCtx.fillStyle = fillColor.value;
tempCtx.lineCap = 'round';
tempCtx.lineJoin = 'round';
if (currentTool === 'line') {
tempCtx.beginPath();
tempCtx.moveTo(startX, startY);
tempCtx.lineTo(mouseX, mouseY);
tempCtx.stroke();
} else if (currentTool === 'rectangle') {
const width = mouseX - startX;
const height = mouseY - startY;
if (fillShape.checked) {
tempCtx.fillRect(startX, startY, width, height);
}
tempCtx.strokeRect(startX, startY, width, height);
} else if (currentTool === 'circle') {
const radius = Math.sqrt(Math.pow(mouseX - startX, 2) + Math.pow(mouseY - startY, 2));
tempCtx.beginPath();
tempCtx.arc(startX, startY, radius, 0, Math.PI * 2);
if (fillShape.checked) {
tempCtx.fill();
}
tempCtx.stroke();
}
}
}
function finishDrawing(e) {
if (!drawing) return;
drawing = false;
const pos = getMousePos(e);
const mouseX = pos.x;
const mouseY = pos.y;
// Dla narzędzi kształtów – przenosimy tymczasowy kształt na główny canvas
if (currentTool === 'line' || currentTool === 'rectangle' || currentTool === 'circle') {
ctx.lineWidth = brushSize.value;
ctx.strokeStyle = strokeColor.value;
ctx.fillStyle = fillColor.value;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
if (currentTool === 'line') {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
} else if (currentTool === 'rectangle') {
const width = mouseX - startX;
const height = mouseY - startY;
if (fillShape.checked) {
ctx.fillRect(startX, startY, width, height);
}
ctx.strokeRect(startX, startY, width, height);
} else if (currentTool === 'circle') {
const radius = Math.sqrt(Math.pow(mouseX - startX, 2) + Math.pow(mouseY - startY, 2));
ctx.beginPath();
ctx.arc(startX, startY, radius, 0, Math.PI * 2);
if (fillShape.checked) {
ctx.fill();
}
ctx.stroke();
}
// Czyścimy warstwę podglądu
tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
}
// Po zakończeniu rysowania zapisujemy aktualny stan dla cofania
pushState();
}
// Czyścimy canvas po kliknięciu przycisku "Wyczyść"
clearCanvasBtn.addEventListener('click', function () {
pushState(); // Zapisz stan przed czyszczeniem
ctx.clearRect(0, 0, canvas.width, canvas.height);
pushState(); // Zapisz stan pustego płótna
});
// Zapisujemy rysunek jako obrazek
saveCanvasBtn.addEventListener('click', function () {
// Łączymy główny canvas z ewentualnym podglądem
const mergedCanvas = document.createElement('canvas');
mergedCanvas.width = canvas.width;
mergedCanvas.height = canvas.height;
const mergedCtx = mergedCanvas.getContext('2d');
mergedCtx.drawImage(canvas, 0, 0);
mergedCtx.drawImage(tempCanvas, 0, 0);
const link = document.createElement('a');
link.download = 'my_painting.png';
link.href = mergedCanvas.toDataURL();
link.click();
});
// Przypisujemy funkcje cofania i ponawiania do przycisków
undoBtn.addEventListener('click', undo);
redoBtn.addEventListener('click', redo);
</script>
</body>
</html>
- Markup 2025-02-13 at 13.30.37.png (7 KB) - ściągnięć: 10
temu to każdemu oczy by wyskoczyły
- chyba ktoś nie widział systemów eksperckich :)