Individuelle Valentinskarten mit Transloadit & Uppy erstellen
Da der Valentinstag näher rückt, möchten wir ein unterhaltsames Projekt vorstellen, das Sie mit Transloadit und Uppy umsetzen können. Wir verwenden dafür den Robot /image/resize, um einen individuellen Generator für Valentinstagskarten zu erstellen. Fügen Sie der Karte auch einen Namen hinzu, und Sie erhalten eine personalisierte Karte für Ihren Lieblingsmenschen.

Unsere Assembly Instructions
Werfen wir zunächst einen Blick auf die Assembly Instructions, die wir verwenden.
{
"steps": {
"watermark": {
"use": ":original",
"robot": "/image/resize",
"width": "1921",
"height": "1921",
"resize_strategy": "fillcrop",
"watermark_url": "https://transloadit.com/assets/images/blog/2023-01-26-valentines-card-generator-1.png",
"watermark_size": "100%",
"watermark_position": "center",
"imagemagick_stack": "v3"
},
"add_text": {
"use": "watermark",
"robot": "/image/resize",
"text": [
{
"text": "${fields.message}",
"size": 80,
"color": "#ffffff",
"valign": "bottom",
"y_offset": -90,
"x_offset": 0
}
],
"imagemagick_stack": "v3",
"result": true
}
}
}
Hier benötigen wir zwei separate Steps mit /image/resize. Unser erster Step fügt einen dekorativen Rahmen um unser Originalbild hinzu und schneidet es zugleich passend zu und passt seine Größe an. Der zweite Step fügt dann Text über unser Bild mit Wasserzeichen hinzu, den wir später mit JavaScript anpassen. Würden wir dies im selben Step tun, läge unser Bildrahmen vor dem Text – und würde ihn im Endergebnis verdecken.
Speichern Sie diese Instructions als Template. Das JavaScript unten sendet die Nachricht als Feld, sodass die Instructions zur Verarbeitung an einer Stelle bleiben. Verwenden Sie vor einem öffentlichen Deployment serverseitig generierte Signaturen und validieren Sie die Nachricht auf Ihrem Server. Fügen Sie niemals ein Auth Secret in Browser-Code ein.
Die generierte Karten-URL ist temporär und läuft nach 24 Stunden ab. Speichern Sie die Karte, bevor sie abläuft, oder ergänzen Sie einen Export-Robot wie /s3/store für eine dauerhafte Speicherung.
HTML & CSS
Leider haben wir noch keinen Ort, an dem wir unser neues Template zeigen können. Ändern wir das! Kopieren Sie das folgende HTML in eine neue HTML-Datei.
Beachten Sie dabei besonders unser Element input. Wir nutzen es im nächsten Abschnitt, damit
Nutzerinnen und Nutzer ändern können, welcher Name auf ihrer Karte ergänzt wird.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Transloadit Valentine</title>
<link href="https://releases.transloadit.com/uppy/v3.3.1/uppy.min.css" rel="stylesheet" />
</head>
<style></style>
<body>
<h1>Transloadit Valentine</h1>
<p>Upload a picture of your Valentine and we'll make it a Valentine's Day card!</p>
<div class="input-container">
<label for="name">Name:</label>
<input id="name" name="name" maxlength="12" />
</div>
<div id="drag-drop-area"></div>
<img id="result" alt="Your personalized Valentine's Day card" hidden />
<p id="status" role="status"></p>
</body>
</html>
Fügen wir unserer Seite nun ein ansprechendes Styling hinzu. Ergänzen Sie innerhalb des Tags style das folgende CSS.
:root {
--primary: #7f626a;
--secondary: #f8edeb;
--accent: #ff4d6d;
--accent-highlight: #f9ccd2;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--secondary);
color: var(--primary);
font-family: sans-serif;
}
h1,
p {
margin: 0 0 0.5rem;
}
#result {
border-radius: 10px;
width: 480px;
max-width: calc(100vw - 2rem);
border: none;
contain: content;
aspect-ratio: 1/1;
margin: 2rem;
}
.input-container {
margin: 1rem;
color: var(--primary);
}
input {
border: none;
border-bottom: 2px var(--primary) dashed;
background-color: transparent;
text-align: start;
font: inherit;
color: var(--accent);
}
input:focus {
outline: 2px solid currentColor;
outline-offset: 2px;
}
.uppy-Dashboard {
max-width: 90vw;
}
.uppy-Dashboard-innerWrap {
background-color: var(--secondary);
border: var(--primary) 2px dashed;
}
.uppy-Dashboard-AddFiles {
border: 0 !important;
}
.uppy-Dashboard-poweredBy,
.uppy-Dashboard-poweredByIcon {
color: var(--primary) !important;
stroke: var(--primary);
}
.uppy-Dashboard-AddFiles-title,
.uppy-DashboardTab-name {
color: var(--primary);
}
.uppy-DashboardTab-btn:hover {
background-color: var(--accent-highlight) !important;
}
.uppy-Dashboard-browse,
.uppy-ProviderIconBg,
.uppy-DashboardContent-back,
.uppy-StatusBar-actionBtn {
color: var(--accent);
fill: var(--accent);
}
.uppy-DashboardContent-bar,
.uppy-StatusBar-actions,
.uppy-StatusBar,
.uppy-StatusBar::before {
border: none !important;
background-color: transparent !important;
}
.uppy-StatusBar-actionBtn--upload {
background-color: var(--accent) !important;
color: var(--secondary) !important;
border: none;
border-radius: 5px;
}
Auch wenn es einschüchternd wirken mag: Der Großteil unseres CSS dient hier nur dazu, unsere Uppy-Dashboard-Komponente neu zu gestalten. Ansonsten verwenden wir lediglich eine Farbpalette, die mit Coolors generiert wurde.
So sollte unsere Seite jetzt aussehen:

JS
Nun zum spannenden Teil! Ergänzen Sie nach dem HTML das folgende JavaScript innerhalb eines Tags <script type="module">
und ersetzen Sie die Platzhalter für Auth Key und Template ID durch Ihre eigenen Werte.
import {
Uppy,
Dashboard,
Transloadit,
ImageEditor,
} from 'https://releases.transloadit.com/uppy/v3.3.1/uppy.min.mjs'
const nameInput = document.getElementById('name')
const status = document.getElementById('status')
function cardMessage(name) {
const recipient = name.trim()
return recipient ? `Happy Valentine's Day, ${recipient}!` : "Happy Valentine's Day!"
}
const uppy = new Uppy({
restrictions: {
maxNumberOfFiles: 1,
allowedFileTypes: ['image/*'],
},
})
.use(Dashboard, {
inline: true,
target: '#drag-drop-area',
})
.use(ImageEditor, {
target: Dashboard,
quality: 0.8,
cropperOptions: {
aspectRatio: 1 / 1, // Same aspect ratio as our overlay
},
})
.use(Transloadit, {
waitForEncoding: true,
getAssemblyOptions: () => ({
params: {
auth: { key: 'YOUR_AUTH_KEY' },
template_id: 'YOUR_TEMPLATE_ID',
},
fields: { message: cardMessage(nameInput.value) },
}),
})
uppy.on('transloadit:complete', (assembly) => {
const url = assembly.results.add_text?.[0]?.ssl_url
if (typeof url !== 'string') {
status.textContent = 'No card was returned. Please try again.'
return
}
const resultImg = document.getElementById('result')
resultImg.src = url
resultImg.hidden = false
status.textContent = 'Your card is ready.'
})
uppy.on('upload', () => {
document.getElementById('result').hidden = true
status.textContent = 'Creating your card.'
})
uppy.on('error', () => {
status.textContent = 'Card generation failed. Please try again.'
})
Wir nutzen hier die Uppy-Komponenten Dashboard, ImageEditor und Transloadit, und glücklicherweise können wir größtenteils die Standardeinstellungen verwenden. Bemerkenswert ist jedoch, dass wir das Seitenverhältnis des Zuschneidewerkzeugs im ImageEditor auf dasselbe wie bei unserem Overlay-Bild setzen. In unserem Fall ist es 1:1.
Die gepinnte Uppy-Version ruft getAssemblyOptions auf, sobald ein Upload startet. Dabei wird der aktuelle
Name ausgelesen; wenn Sie das Eingabefeld leeren, wird also wieder die allgemeine Begrüßung
verwendet, statt den vorherigen Empfänger beizubehalten.
Zum Abschluss
Kombinieren Sie HTML, CSS und das Modul-Skript, konfigurieren Sie Ihr eigenes Template und stellen Sie die Seite lokal bereit, um sie auszuprobieren. Der Screenshot zeigt den ursprünglichen Prototyp; der Code oben enthält die korrigierte Wasserzeichen-URL sowie die Verarbeitung von Nachricht und Ergebnis.
Das war es fürs Erste von uns. Wir wünschen Ihnen einen schönen Valentinstag und denken Sie daran, Ihrem Lieblingsmenschen eine schöne, personalisierte Karte zu schicken. Und wenn Sie die Werkzeuge aus diesem Blogbeitrag noch weiter ausgebaut haben, würden wir auf Twitter gerne davon hören!
