create animation with zip of frame
This commit is contained in:
parent
cad7c8f84e
commit
71e597158d
4 changed files with 45 additions and 51 deletions
17
src/main.jsx
17
src/main.jsx
|
@ -1,9 +1,9 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StrictMode } from 'react'
|
import { StrictMode } from 'react';
|
||||||
import { createRoot } from 'react-dom/client'
|
import { createRoot } from 'react-dom/client';
|
||||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
|
||||||
import './css/global.css'
|
import './css/global.css';
|
||||||
import HomePage from './pages/homePage.jsx'
|
import HomePage from './pages/homePage.jsx';
|
||||||
import WarningPage from './pages/warningPage.jsx';
|
import WarningPage from './pages/warningPage.jsx';
|
||||||
import NamePage from './pages/namePage.jsx';
|
import NamePage from './pages/namePage.jsx';
|
||||||
import Animation from './pages/components/testAnimation_onefile.jsx';
|
import Animation from './pages/components/testAnimation_onefile.jsx';
|
||||||
|
@ -14,9 +14,10 @@ createRoot(document.getElementById('root')).render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<HomePage />} />
|
<Route path="/" element={<HomePage />} />
|
||||||
<Route path="/warn" element={<WarningPage />} />
|
<Route path="/warn" element={<WarningPage />} />
|
||||||
<Route path="/name" element={<NamePage />}/>
|
<Route path="/name" element={<NamePage />} />
|
||||||
<Route path="/sprite" element={<Animation />}/>
|
<Route path="/sprite" element={<Animation />} />
|
||||||
|
<Route path="*" element={<Navigate to="/" replace />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</StrictMode>,
|
</StrictMode>,
|
||||||
)
|
);
|
||||||
|
|
|
@ -1,47 +1,43 @@
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import anime from 'animejs';
|
import anime from 'animejs';
|
||||||
|
|
||||||
const startNumber = 1000; // Starting number
|
const startNumber = 1000;
|
||||||
const endNumber = 1239; // Ending number
|
const endNumber = 1239;
|
||||||
const imageCount = endNumber - startNumber + 1; // Total number of images
|
const imageCount = endNumber - startNumber + 1;
|
||||||
const images = [];
|
const images = [];
|
||||||
|
|
||||||
// Loop through the range from startNumber to endNumber
|
|
||||||
for (let i = startNumber; i <= endNumber; i++) {
|
for (let i = startNumber; i <= endNumber; i++) {
|
||||||
// Format the number to be 5 digits with leading zeros
|
|
||||||
const formattedNumber = String(i).padStart(5, '0');
|
const formattedNumber = String(i).padStart(5, '0');
|
||||||
images.push(import(`../../assets/characters/F_porche_akimbo_AME/Porsche${formattedNumber}.png`));
|
images.push(import(`../../assets/characters/F_porche_akimbo_AME/Porsche${formattedNumber}.png`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const CharacterAnimation = () => {
|
const CharacterAnimation = () => {
|
||||||
const totalFrames = imageCount; // Total number of frames
|
const totalFrames = imageCount;
|
||||||
const frameDuration = 20; // Duration for each frame in milliseconds
|
const frameDuration = 20;
|
||||||
const [currentFrame, setCurrentFrame] = useState(0);
|
const [currentFrame, setCurrentFrame] = useState(0);
|
||||||
const [loadedImages, setLoadedImages] = useState([]); // State to hold loaded images
|
const [loadedImages, setLoadedImages] = useState([]);
|
||||||
const characterRef = useRef(null);
|
const characterRef = useRef(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Load all images
|
|
||||||
Promise.all(images).then((resolvedImages) => {
|
Promise.all(images).then((resolvedImages) => {
|
||||||
setLoadedImages(resolvedImages.map(image => image.default)); // Set the loaded images
|
setLoadedImages(resolvedImages.map(image => image.default));
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
setCurrentFrame((prevFrame) => (prevFrame + 1) % totalFrames);
|
setCurrentFrame((prevFrame) => (prevFrame + 1) % totalFrames);
|
||||||
console.log(loadedImages)
|
|
||||||
}, frameDuration);
|
}, frameDuration);
|
||||||
|
|
||||||
return () => clearInterval(interval); // Cleanup on unmount
|
return () => clearInterval(interval);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
ref={characterRef}
|
ref={characterRef}
|
||||||
src={loadedImages[currentFrame]} // Use the loaded images
|
src={loadedImages[currentFrame]}
|
||||||
alt="Character Animation"
|
alt="Character Animation"
|
||||||
style={{ width: '200px', height: 'auto' }} // Adjust size as needed
|
style={{ width: '200px', height: 'auto' }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,13 +5,13 @@ const Animation = () => {
|
||||||
const [images, setImages] = useState([]);
|
const [images, setImages] = useState([]);
|
||||||
const [currentFrame, setCurrentFrame] = useState(0);
|
const [currentFrame, setCurrentFrame] = useState(0);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const frameRate = 100; // Frame rate in milliseconds
|
const frameRate = 60;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadImages = async () => {
|
const loadImages = async () => {
|
||||||
const zip = new JSZip();
|
const zip = new JSZip();
|
||||||
try {
|
try {
|
||||||
const response = await fetch('src/assets/characters/sprite.zip'); // Adjust the path to your ZIP file
|
const response = await fetch('src/assets/characters/M_Porsche_cross_arm.zip');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Network response was not ok');
|
throw new Error('Network response was not ok');
|
||||||
}
|
}
|
||||||
|
@ -21,20 +21,27 @@ const Animation = () => {
|
||||||
const imgPromises = [];
|
const imgPromises = [];
|
||||||
zipContent.forEach((relativePath, file) => {
|
zipContent.forEach((relativePath, file) => {
|
||||||
if (file.name.endsWith('.webp')) {
|
if (file.name.endsWith('.webp')) {
|
||||||
imgPromises.push(file.async('blob')); // Convert file to Blob
|
imgPromises.push(
|
||||||
|
file.async('base64').then(base64 => {
|
||||||
|
return `data:image/webp;base64,${base64}`;
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const imgBlobs = await Promise.all(imgPromises);
|
const imgUrls = await Promise.all(imgPromises);
|
||||||
const imgUrls = imgBlobs.map(blob => URL.createObjectURL(blob)); // Create object URLs
|
|
||||||
|
|
||||||
console.log('Loaded images:', imgUrls); // Log the loaded image URLs
|
// console.log('Loaded images:', imgUrls);
|
||||||
|
|
||||||
|
if (imgUrls.length === 0) {
|
||||||
|
console.error('No images found in the ZIP file.');
|
||||||
|
}
|
||||||
|
|
||||||
setImages(imgUrls);
|
setImages(imgUrls);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading images:', error);
|
console.error('Error loading images:', error);
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false); // Set loading to false after images are loaded
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,31 +50,28 @@ const Animation = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
if (images.length > 0) {
|
||||||
setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
|
const interval = setInterval(() => {
|
||||||
}, frameRate);
|
setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
|
||||||
|
}, frameRate);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, [images]);
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Cleanup object URLs when the component unmounts
|
|
||||||
return () => {
|
|
||||||
images.forEach(url => URL.revokeObjectURL(url)); // Clean up object URLs
|
|
||||||
};
|
|
||||||
}, [images]);
|
}, [images]);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <div>Loading...</div>; // Show loading indicator
|
return <div>Loading...</div>;
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
{images.length > 0 && (
|
{images.length > 0 ? (
|
||||||
<img
|
<img
|
||||||
src={images[currentFrame]}
|
src={images[currentFrame]}
|
||||||
alt="Animation frame"
|
alt={`Animation frame ${currentFrame + 1}`}
|
||||||
style={{ maxWidth: '100%', height: 'auto' }} // Responsive image
|
style={{ maxWidth: '500px', height: 'auto' }}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
<div>No images to display.</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import '../css/global.css'
|
import '../css/global.css'
|
||||||
import BlackButton from './components/customButton'
|
import BlackButton from './components/customButton'
|
||||||
import SpriteAnimation from './components/testAnimation_onefile'
|
|
||||||
import CharacterAnimation from './components/testAnimation_manyfiles'
|
|
||||||
|
|
||||||
function HomePage() {
|
function HomePage() {
|
||||||
|
|
||||||
|
@ -19,11 +17,6 @@ function HomePage() {
|
||||||
|
|
||||||
<div style={{ height: '8vh' }}/>
|
<div style={{ height: '8vh' }}/>
|
||||||
|
|
||||||
<CharacterAnimation/>
|
|
||||||
{/* <SpriteAnimation/> */}
|
|
||||||
|
|
||||||
<div style={{ height: '8vh' }}/>
|
|
||||||
|
|
||||||
<BlackButton text="Start" to='/warn'/>
|
<BlackButton text="Start" to='/warn'/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue