Hast du eine Frage?


How-to: Hintergrund Grid Editor


Willkommen zum How-to: Hintergrund Grid Editor.
Hier lernst du, wie du ein Werkzeug programmierst mit dem du
Bilder generieren und mittels eines Grid Editors platzieren kannst.

Falls du etwas nicht verstehst, nutze den Chatbot auf der rechten Seite.
Kopiere den Teil vom Code, den du erklärt haben möchtest und stelle deine Frage dazu.



Was brauchen wir für das Werkzeug:
→ Ordnerstruktur & Dateien (siehe How-to: Basic Setup)
→ OpenAI-API Key (siehe How-to: API)
→ Browser (funktioniert am besten mit Chrome)
→ Browser Erweiterung (siehe How-to: CORS Erweiterung)
→ Text-Editor (zb. SublimeText)

HTML index.html

Die index.html beinhaltet u.A.:
→ <h1> Überschrift (optional)
→ <p> Anleitungstext (optional)
→ <input> zum Prompt eingeben und <button> zum Generieren
→ <button> zum Füllen der Zellen
→ <button> zum Löschen der Zellen
→ <canvas> zum Anzeigen der generierten Bilder
→ <div> zum Erstellen des Grids

1. Öffne die index.html

Du kannst den Code kopieren und in deine Datei einfügen:

<!DOCTYPE html>
<html>
<head>
<title>Hintergrund</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>

<h1>Hintergrund Grid Editor</h1>
<p>Generiere Bilder und platziere sie auf deine ausgewählten Pixel.<br>
Prompt eingeben, generieren, Pixel auf der Leinwand ausmalen und auf Füllen drücken!</p>

<input id="userInput" placeholder="Hier Prompt eingeben">
<button id="generateButton">Generieren</button>
<button id="fill-button">Füllen</button>
<button id="delete-button">Löschen</button>

<canvas id="imageCanvas"></canvas>
<div id="grid"></div>

<script src="js/script.js"></script>

</body>
</html>

2. Speicher die index.html

CSS style.css

1. Öffne die style.css

Die style.css beinhaltet:
→ *{} Zücksetzen auf den Default Style
→ h1{}, p{}, input{}, button{} basic Styling (optinal)
→ .grid{}, .cell{} zum Gestalten des Rasters (wichtig)

Du kannst den Code kopieren und in deine style.css Datei einfügen:

* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

h1 {
margin: 20px;
}

p {
margin-left: 20px;
}

body {
height: 100vh;
width: 100vw;
}

canvas {
position: absolute;
top: 0;
right: 0;
margin: 20px;
width: 130px;
height: 130px;
}

input, button {
margin-left: 20px;
margin-top: 20px;
}

#grid {
margin: 20px;
display: grid;
grid-template-columns: repeat(60, 1fr);
grid-template-rows: repeat(30, 1fr);
height: 76vh;
border: 0.1px solid black;
}

.cell {
background-color: white;
width: 100%;
height: 100%;
image-rendering: pixelated;
}

.cell.active {
background-color: black;
}

2. Speicher die style.css


JS script.js

Die script.js beinhaltet:
→ initializeGrid: Diese Funktion wird aufgerufen, um das Raster zu initialisieren
→ handleCellMouseOver, handleCellMouseDown, handleCellMouseUp: ändern die Klasse und fügen Zellen zur Liste der ausgewählten Zellen hinzu, abhängig davon, ob die Maustaste gedrückt ist oder nicht
→ getImages: Ruft Bilder von einer API ab und fügt sie der Seite hinzu
→ drawImageOnCanvas: Zeichnet das generierte Bild auf ein HTML-Canvas-Element.
→ fillShapeWithImage: Füllt die ausgewählten Zellen mit dem generierten Bild.
→ getBoundingBox: berechnet die Begrenzungen (Bounding Box) der ausgewählten Zellen, um den richtigen Ausschnitt des generierten Bildes für jede Zelle zu bestimmen

1. Öffne die script.js

Du kannst den Code kopieren und in deine script.js Datei einfügen:

const grid = document.getElementById("grid");
const cells = [];

const numColumns = 60;
const numRows = 30;

function initializeGrid() {
for (let i = 0; i < numRows; i++) {
for (let j = 0; j < numColumns; j++) {
const cell = document.createElement("div");
cell.classList.add("cell");
cell.addEventListener("mouseover", handleCellMouseOver);
cell.addEventListener("mousedown", handleCellMouseDown);
cell.addEventListener("mouseup", handleCellMouseUp);
grid.appendChild(cell);
cells.push(cell);
}
}
}

let isMouseDown = false;
const selectedCells = [];

function handleCellMouseOver(event) {
if (isMouseDown) {
const cell = event.target;
if (!cell.classList.contains("active")) {
cell.classList.add("active");
selectedCells.push(cell);
}
}
}

function handleCellMouseDown(event) {
isMouseDown = true;
const cell = event.target;
cell.classList.add("active");
selectedCells.push(cell);
}

function handleCellMouseUp() {
isMouseDown = false;
}

const fillButton = document.getElementById("fill-button");
fillButton.addEventListener("click", fillShapeWithImage);

const imageCanvas = document.getElementById("imageCanvas");
const userInput = document.getElementById("userInput");
const generateButton = document.getElementById("generateButton");
let generatedImage;

const API_KEY = "DEIN_API_KEY";

generateButton.addEventListener("click", getImages);

async function getImages() {
generateButton.textContent = "Lädt...";

const options = {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
"origin": window.location.origin
},
body: JSON.stringify({
"prompt": userInput.value,
"n": 1,
"size": "256x256"
})
};

try {
const response = await fetch("https://api.openai.com/v1/images/generations", options);
const data = await response.json();

if (data.data.length > 0) {
const imageUrl = data.data[0].url;

const img = new Image();
img.crossOrigin = "Anonymous";
img.onload = () => {
generatedImage = img;
drawImageOnCanvas();
generateButton.textContent = "Generieren";
};
img.src = imageUrl;
} else {
console.error(error);
generateButton.textContent = "Generieren";
}
} catch (error) {
console.error(error);
generateButton.textContent = "Generieren";
}
}

function drawImageOnCanvas() {
const canvas = imageCanvas;
const canvasContext = canvas.getContext("2d");

canvasContext.clearRect(0, 0, canvas.width, canvas.height);
canvasContext.drawImage(generatedImage, 0, 0, canvas.width, canvas.height);
}

function fillShapeWithImage() {
if (!generatedImage || selectedCells.length === 0) return;

const bbox = getBoundingBox();

const canvas = document.createElement("canvas");
canvas.width = bbox.width;
canvas.height = bbox.height;
const canvasContext = canvas.getContext("2d");
canvasContext.drawImage(generatedImage, 0, 0, bbox.width, bbox.height);

selectedCells.forEach((cell) => {
const rect = cell.getBoundingClientRect();
const cellOffsetX = rect.left - bbox.minX;
const cellOffsetY = rect.top - bbox.minY;

const imageData = canvasContext.getImageData(cellOffsetX, cellOffsetY, rect.width, rect.height);

const cellCanvas = document.createElement("canvas");
cellCanvas.width = rect.width;
cellCanvas.height = rect.height;
const cellContext = cellCanvas.getContext("2d");
cellContext.putImageData(imageData, 0, 0);

const imageUrl = cellCanvas.toDataURL();
cell.style.backgroundImage = `url('${imageUrl}')`;
cell.style.backgroundSize = `${rect.width}px ${rect.height}px`;
cell.style.backgroundPosition = `-${cellOffsetX}px -${cellOffsetY}px`;
});

selectedCells.length = 0;
}

function getBoundingBox() {
let minX = Infinity,
minY = Infinity,
maxX = -Infinity,
maxY = -Infinity;
selectedCells.forEach((cell) => {
const rect = cell.getBoundingClientRect();
minX = Math.min(minX, rect.left);
minY = Math.min(minY, rect.top);
maxX = Math.max(maxX, rect.right);
maxY = Math.max(maxY, rect.bottom);
});
return { minX, minY, width: maxX - minX, height: maxY - minY };
}

const deleteButton = document.getElementById("delete-button");
deleteButton.addEventListener("click", resetCells);

function resetCells() {
selectedCells.forEach((cell) => {
cell.style.backgroundImage = "";
cell.style.backgroundColor = "";
cell.classList.remove("active");
});
selectedCells.length = 0;
}

initializeGrid();

2. Füge deinen API Key in dieses Feld ein: "DEIN_API_KEY"

3. Speicher die script.js


Du kannst jetzt die index.html in deinem Browser öffnen und das Tool testen :)