feat(frontend): Ersetze Lottie-Animation durch custom 3D SVG Logo-Animation
- Lottie-react Bibliothek durch native CSS 3D Transforms ersetzt - Hobbyhimmel Logo (Hammer & Wolke) als animiertes Loading-Icon - Wolke rotiert um Y-Achse (4s) - Hammer rotiert um Y-Achse UND eigene Diagonalachse (3s) - 15° X-Neigung für dynamischeren 3D-Effekt - Nested Transform-Hierarchie mit transform-box: fill-box - Upload-Erfolgsmeldung als grünes Banner unter Animation - Nutzer muss Upload-Bestätigung mit Button bestätigen - Loading-Animation bleibt während Erfolgsmeldung sichtbar
This commit is contained in:
parent
ddc7e787b3
commit
008adf3f27
63
frontend/public/hobbyhimmel_logo.svg
Normal file
63
frontend/public/hobbyhimmel_logo.svg
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="841.89px"
|
||||
height="595.28px"
|
||||
viewBox="0 0 841.89 595.28"
|
||||
enable-background="new 0 0 841.89 595.28"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="hobbyhimmel_logo.svg"
|
||||
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><defs
|
||||
id="defs182" /><sodipodi:namedview
|
||||
id="namedview180"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.92473429"
|
||||
inkscape:cx="340.09769"
|
||||
inkscape:cy="237.90618"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
|
||||
<g
|
||||
display="inline"
|
||||
id="g136"
|
||||
inkscape:label="Hammer">
|
||||
|
||||
<path
|
||||
display="inline"
|
||||
fill="#76b043"
|
||||
d="m 386.456,248.659 c -0.824,0.825 -2.157,0.825 -2.987,0 L 365.572,230.76 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z"
|
||||
id="path132" /><path
|
||||
display="inline"
|
||||
fill="#76b043"
|
||||
d="m 473.015,185.95 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.808,0.811 0.819,2.087 0.05,2.916"
|
||||
id="path134" />
|
||||
</g><g
|
||||
id="g561"
|
||||
inkscape:label="Wolke"
|
||||
style="display:inline"><path
|
||||
fill="#48484a"
|
||||
d="m 501.16,142.979 c -4.11,0 -8.124,0.403 -12.017,1.146 -14.397,-26.528 -42.494,-44.539 -74.798,-44.539 -41.217,0 -75.58,29.322 -83.381,68.243 -1.451,-0.123 -2.914,-0.2 -4.396,-0.2 -28.181,0 -51.027,22.845 -51.027,51.026 0,28.18 22.847,51.026 51.027,51.026 14.838,0 159.491,-10e-4 174.591,-10e-4 35.229,0 63.787,-27.689 63.787,-62.916 10e-4,-35.225 -28.557,-63.785 -63.786,-63.785 M 386.432,248.707 c -0.824,0.825 -2.157,0.825 -2.987,0 l -17.897,-17.899 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z m 86.558,-62.709 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.809,0.811 0.82,2.087 0.05,2.916"
|
||||
id="path130"
|
||||
style="display:inline" /></g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
|
@ -1,17 +1,41 @@
|
|||
import '../../../App.css'
|
||||
|
||||
import Lottie from 'lottie-react';
|
||||
import animationData from './animation.json';
|
||||
import React from "react";
|
||||
import './LoadingLogo.css';
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="loading">
|
||||
<Lottie
|
||||
animationData={animationData}
|
||||
loop={true}
|
||||
autoplay={true}
|
||||
style={{ width: 400, height: 400 }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
const Loading = () => {
|
||||
|
||||
return (
|
||||
<div className="loading-logo-container">
|
||||
<div className="rotor">
|
||||
<svg
|
||||
className="loading-logo"
|
||||
version="1.1"
|
||||
viewBox="0 0 841.89 595.28"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g id="g136" display="inline">
|
||||
<path
|
||||
display="inline"
|
||||
fill="#76b043"
|
||||
d="m 386.456,248.659 c -0.824,0.825 -2.157,0.825 -2.987,0 L 365.572,230.76 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z"
|
||||
/>
|
||||
<path
|
||||
display="inline"
|
||||
fill="#76b043"
|
||||
d="m 473.015,185.95 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.808,0.811 0.819,2.087 0.05,2.916"
|
||||
/>
|
||||
</g>
|
||||
<g id="g561" display="inline">
|
||||
<path
|
||||
fill="#48484a"
|
||||
d="m 501.16,142.979 c -4.11,0 -8.124,0.403 -12.017,1.146 -14.397,-26.528 -42.494,-44.539 -74.798,-44.539 -41.217,0 -75.58,29.322 -83.381,68.243 -1.451,-0.123 -2.914,-0.2 -4.396,-0.2 -28.181,0 -51.027,22.845 -51.027,51.026 0,28.18 22.847,51.026 51.027,51.026 14.838,0 159.491,-10e-4 174.591,-10e-4 35.229,0 63.787,-27.689 63.787,-62.916 10e-4,-35.225 -28.557,-63.785 -63.786,-63.785 M 386.432,248.707 c -0.824,0.825 -2.157,0.825 -2.987,0 l -17.897,-17.899 c -0.818,-0.816 -0.818,-2.136 -0.005,-2.962 0.005,-0.008 0.005,-0.011 0.011,-0.019 0.006,-0.002 0.01,-0.002 0.017,-0.01 l 52.177,-52.177 20.877,20.876 z m 86.558,-62.709 c -0.021,0.018 -0.025,0.045 -0.043,0.063 -0.02,0.02 -0.045,0.022 -0.064,0.041 l -17.811,17.813 c -0.018,0.019 -0.023,0.046 -0.041,0.061 -0.02,0.02 -0.045,0.026 -0.064,0.045 -0.815,0.758 -2.064,0.754 -2.877,-0.012 -0.012,-0.014 -0.035,-0.018 -0.047,-0.033 -0.012,-0.012 -0.019,-0.033 -0.032,-0.046 l -49.265,-49.265 c -0.014,-0.016 -0.035,-0.02 -0.048,-0.034 -0.013,-0.011 -0.019,-0.034 -0.032,-0.049 -0.783,-0.826 -0.779,-2.121 0.032,-2.929 0.31,-0.312 0.698,-0.465 1.093,-0.543 l 0.004,-0.039 30.859,-5.149 0.035,0.034 c 0.607,-0.061 1.232,0.107 1.704,0.578 l 36.547,36.548 c 0.809,0.811 0.82,2.087 0.05,2.916"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Loading;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
.loading-logo-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
position: relative;
|
||||
perspective: 1000px;
|
||||
}
|
||||
|
||||
/* Äußerer Container: Y-Achsen-Rotation für Wolke UND Hammer zusammen */
|
||||
.rotor {
|
||||
display: inline-block;
|
||||
transform-origin: center;
|
||||
transform-style: preserve-3d;
|
||||
will-change: transform;
|
||||
animation: rotateY 4s linear infinite;
|
||||
}
|
||||
|
||||
.loading-logo {
|
||||
display: block;
|
||||
width: 400px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Hammer: zusätzliche Rotation um eigene Längsachse */
|
||||
.loading-logo #g136 {
|
||||
transform-box: fill-box; /* Bezieht sich auf eigene Bounding Box */
|
||||
transform-origin: center; /* Mittelpunkt der eigenen BBox */
|
||||
will-change: transform;
|
||||
animation: rotateHammerAxis 3s linear infinite;
|
||||
}
|
||||
|
||||
/* Y-Achsen-Rotation mit leichter X-Neigung (vermeidet Totpunkt bei 90°) */
|
||||
@keyframes rotateY {
|
||||
from {
|
||||
transform: rotateY(0deg) rotateX(15deg);
|
||||
}
|
||||
to {
|
||||
transform: rotateY(360deg) rotateX(15deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Hammer-Rotation um eigene Längsachse (diagonal) */
|
||||
@keyframes rotateHammerAxis {
|
||||
from {
|
||||
transform: rotate3d(1, -1, 0, 0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate3d(1, -1, 0, 360deg);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,8 @@ function MultiUploadPage() {
|
|||
});
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
const [uploadComplete, setUploadComplete] = useState(false);
|
||||
const [uploadResult, setUploadResult] = useState(null);
|
||||
const [isEditMode, setIsEditMode] = useState(false);
|
||||
const [imageDescriptions, setImageDescriptions] = useState({});
|
||||
|
||||
|
|
@ -165,23 +167,10 @@ function MultiUploadPage() {
|
|||
clearInterval(progressInterval);
|
||||
setUploadProgress(100);
|
||||
|
||||
// Kurze Verzögerung für UX
|
||||
// Kurze Verzögerung für UX, dann Erfolgsmeldung anzeigen
|
||||
setTimeout(() => {
|
||||
setUploading(false);
|
||||
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Upload erfolgreich!',
|
||||
text: `${result.imageCount} Bild${result.imageCount !== 1 ? 'er' : ''} wurden hochgeladen.`,
|
||||
confirmButtonColor: '#4CAF50',
|
||||
timer: 2000,
|
||||
showConfirmButton: false
|
||||
});
|
||||
|
||||
// Seite neu laden für nächsten Upload
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 2000);
|
||||
setUploadComplete(true);
|
||||
setUploadResult(result);
|
||||
}, 500);
|
||||
|
||||
} catch (error) {
|
||||
|
|
@ -305,6 +294,56 @@ function MultiUploadPage() {
|
|||
totalFiles={selectedImages.length}
|
||||
isUploading={uploading}
|
||||
/>
|
||||
|
||||
{uploadComplete && uploadResult && (
|
||||
<Box sx={{
|
||||
mt: 4,
|
||||
p: 3,
|
||||
borderRadius: '12px',
|
||||
background: 'linear-gradient(135deg, #4CAF50 0%, #45a049 100%)',
|
||||
color: 'white',
|
||||
boxShadow: '0 4px 20px rgba(76, 175, 80, 0.4)',
|
||||
animation: 'slideIn 0.5s ease-out',
|
||||
'@keyframes slideIn': {
|
||||
from: {
|
||||
opacity: 0,
|
||||
transform: 'translateY(-20px)'
|
||||
},
|
||||
to: {
|
||||
opacity: 1,
|
||||
transform: 'translateY(0)'
|
||||
}
|
||||
}
|
||||
}}>
|
||||
<Typography sx={{ fontSize: '28px', fontWeight: 'bold', mb: 1 }}>
|
||||
✅ Upload erfolgreich!
|
||||
</Typography>
|
||||
<Typography sx={{ fontSize: '18px', mb: 3 }}>
|
||||
{uploadResult.imageCount} Bild{uploadResult.imageCount !== 1 ? 'er' : ''} wurden hochgeladen.
|
||||
</Typography>
|
||||
<Button
|
||||
sx={{
|
||||
background: 'white',
|
||||
color: '#4CAF50',
|
||||
fontWeight: 'bold',
|
||||
fontSize: '16px',
|
||||
px: 4,
|
||||
py: 1.5,
|
||||
borderRadius: '25px',
|
||||
textTransform: 'none',
|
||||
'&:hover': {
|
||||
background: '#f0f0f0',
|
||||
transform: 'scale(1.05)',
|
||||
boxShadow: '0 4px 12px rgba(0,0,0,0.2)'
|
||||
},
|
||||
transition: 'all 0.3s ease'
|
||||
}}
|
||||
onClick={() => window.location.reload()}
|
||||
>
|
||||
👍 Alles klar!
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user