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 '../../../App.css'
|
||||||
|
|
||||||
import Lottie from 'lottie-react';
|
import React from "react";
|
||||||
import animationData from './animation.json';
|
import './LoadingLogo.css';
|
||||||
|
|
||||||
export default function Loading() {
|
const Loading = () => {
|
||||||
return (
|
|
||||||
<div className="loading">
|
return (
|
||||||
<Lottie
|
<div className="loading-logo-container">
|
||||||
animationData={animationData}
|
<div className="rotor">
|
||||||
loop={true}
|
<svg
|
||||||
autoplay={true}
|
className="loading-logo"
|
||||||
style={{ width: 400, height: 400 }}
|
version="1.1"
|
||||||
/>
|
viewBox="0 0 841.89 595.28"
|
||||||
</div>
|
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 [uploading, setUploading] = useState(false);
|
||||||
const [uploadProgress, setUploadProgress] = useState(0);
|
const [uploadProgress, setUploadProgress] = useState(0);
|
||||||
|
const [uploadComplete, setUploadComplete] = useState(false);
|
||||||
|
const [uploadResult, setUploadResult] = useState(null);
|
||||||
const [isEditMode, setIsEditMode] = useState(false);
|
const [isEditMode, setIsEditMode] = useState(false);
|
||||||
const [imageDescriptions, setImageDescriptions] = useState({});
|
const [imageDescriptions, setImageDescriptions] = useState({});
|
||||||
|
|
||||||
|
|
@ -165,23 +167,10 @@ function MultiUploadPage() {
|
||||||
clearInterval(progressInterval);
|
clearInterval(progressInterval);
|
||||||
setUploadProgress(100);
|
setUploadProgress(100);
|
||||||
|
|
||||||
// Kurze Verzögerung für UX
|
// Kurze Verzögerung für UX, dann Erfolgsmeldung anzeigen
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setUploading(false);
|
setUploadComplete(true);
|
||||||
|
setUploadResult(result);
|
||||||
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);
|
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -305,6 +294,56 @@ function MultiUploadPage() {
|
||||||
totalFiles={selectedImages.length}
|
totalFiles={selectedImages.length}
|
||||||
isUploading={uploading}
|
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>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user