test sprite animate , series file , zip

This commit is contained in:
NekoVari 2024-12-17 00:04:55 +07:00
parent 5391b2606c
commit cad7c8f84e
9 changed files with 269 additions and 2 deletions

107
package-lock.json generated
View file

@ -8,6 +8,8 @@
"name": "fifty-shades-of-bully",
"version": "0.0.0",
"dependencies": {
"animejs": "^3.2.2",
"jszip": "^3.10.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.2"
@ -1373,6 +1375,12 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/animejs": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.2.tgz",
"integrity": "sha512-Ao95qWLpDPXXM+WrmwcKbl6uNlC5tjnowlaRYtuVDHHoygjtIPfDUoK9NthrlZsQSKjZXlmji2TrBUAVbiH0LQ==",
"license": "MIT"
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -1711,6 +1719,12 @@
"node": ">=18"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -2645,6 +2659,12 @@
"node": ">= 4"
}
},
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
"license": "MIT"
},
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -2672,6 +2692,12 @@
"node": ">=0.8.19"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/internal-slot": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
@ -3155,6 +3181,18 @@
"node": ">=4.0"
}
},
"node_modules/jszip": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
"license": "(MIT OR GPL-3.0-or-later)",
"dependencies": {
"lie": "~3.3.0",
"pako": "~1.0.2",
"readable-stream": "~2.3.6",
"setimmediate": "^1.0.5"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@ -3179,6 +3217,15 @@
"node": ">= 0.8.0"
}
},
"node_modules/lie": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"license": "MIT",
"dependencies": {
"immediate": "~3.0.5"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@ -3431,6 +3478,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
"license": "(MIT AND Zlib)"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -3527,6 +3580,12 @@
"node": ">= 0.8.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@ -3631,6 +3690,27 @@
"react-dom": ">=18"
}
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/readable-stream/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"license": "MIT"
},
"node_modules/reflect.getprototypeof": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz",
@ -3757,6 +3837,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"license": "MIT"
},
"node_modules/safe-regex-test": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
@ -3834,6 +3920,12 @@
"node": ">= 0.4"
}
},
"node_modules/setimmediate": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
"license": "MIT"
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -3886,6 +3978,15 @@
"node": ">=0.10.0"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/string.prototype.matchall": {
"version": "4.0.11",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz",
@ -4168,6 +4269,12 @@
"punycode": "^2.1.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
},
"node_modules/vite": {
"version": "5.4.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",

View file

@ -4,12 +4,14 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"animejs": "^3.2.2",
"jszip": "^3.10.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.2"

View file

@ -8,12 +8,13 @@
}
html * {
background-color: rgb(var(--black));
/* background-color: rgb(var(--black)); */
color: rgb(var(--white));
}
body {
margin: 0;
background-color: rgb(var(--black));
}
.title {

View file

@ -0,0 +1,21 @@
.character {
width: 624px; /* Width of a single frame */
height: 814px; /* Height of a single frame */
background-color: wheat;
/* overflow: hidden; */
/* Ensure only one frame is visible */
}
.spriteAnimation {
width: 9984px;
animation: moveSprite 1s steps(16) infinite; /* 240 total frames */
}
@keyframes moveSprite {
form{
transform: translate3d(0,0,0)
}
to{
transform: translate3d(-100%,0,0);
}
}

View file

@ -6,6 +6,7 @@ import './css/global.css'
import HomePage from './pages/homePage.jsx'
import WarningPage from './pages/warningPage.jsx';
import NamePage from './pages/namePage.jsx';
import Animation from './pages/components/testAnimation_onefile.jsx';
createRoot(document.getElementById('root')).render(
<StrictMode>
@ -14,6 +15,7 @@ createRoot(document.getElementById('root')).render(
<Route path="/" element={<HomePage />} />
<Route path="/warn" element={<WarningPage />} />
<Route path="/name" element={<NamePage />}/>
<Route path="/sprite" element={<Animation />}/>
</Routes>
</BrowserRouter>
</StrictMode>,

View file

@ -0,0 +1,49 @@
import React, { useEffect, useRef, useState } from 'react';
import anime from 'animejs';
const startNumber = 1000; // Starting number
const endNumber = 1239; // Ending number
const imageCount = endNumber - startNumber + 1; // Total number of images
const images = [];
// Loop through the range from startNumber to endNumber
for (let i = startNumber; i <= endNumber; i++) {
// Format the number to be 5 digits with leading zeros
const formattedNumber = String(i).padStart(5, '0');
images.push(import(`../../assets/characters/F_porche_akimbo_AME/Porsche${formattedNumber}.png`));
}
const CharacterAnimation = () => {
const totalFrames = imageCount; // Total number of frames
const frameDuration = 20; // Duration for each frame in milliseconds
const [currentFrame, setCurrentFrame] = useState(0);
const [loadedImages, setLoadedImages] = useState([]); // State to hold loaded images
const characterRef = useRef(null);
useEffect(() => {
// Load all images
Promise.all(images).then((resolvedImages) => {
setLoadedImages(resolvedImages.map(image => image.default)); // Set the loaded images
});
}, []);
useEffect(() => {
const interval = setInterval(() => {
setCurrentFrame((prevFrame) => (prevFrame + 1) % totalFrames);
console.log(loadedImages)
}, frameDuration);
return () => clearInterval(interval); // Cleanup on unmount
}, []);
return (
<img
ref={characterRef}
src={loadedImages[currentFrame]} // Use the loaded images
alt="Character Animation"
style={{ width: '200px', height: 'auto' }} // Adjust size as needed
/>
);
};
export default CharacterAnimation;

View file

@ -0,0 +1,77 @@
import React, { useEffect, useState } from 'react';
import JSZip from 'jszip';
const Animation = () => {
const [images, setImages] = useState([]);
const [currentFrame, setCurrentFrame] = useState(0);
const [loading, setLoading] = useState(true);
const frameRate = 100; // Frame rate in milliseconds
useEffect(() => {
const loadImages = async () => {
const zip = new JSZip();
try {
const response = await fetch('src/assets/characters/sprite.zip'); // Adjust the path to your ZIP file
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.arrayBuffer();
const zipContent = await zip.loadAsync(data);
const imgPromises = [];
zipContent.forEach((relativePath, file) => {
if (file.name.endsWith('.webp')) {
imgPromises.push(file.async('blob')); // Convert file to Blob
}
});
const imgBlobs = 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
setImages(imgUrls);
} catch (error) {
console.error('Error loading images:', error);
} finally {
setLoading(false); // Set loading to false after images are loaded
}
};
loadImages();
}, []);
useEffect(() => {
const interval = setInterval(() => {
setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
}, frameRate);
return () => clearInterval(interval);
}, [images]);
useEffect(() => {
// Cleanup object URLs when the component unmounts
return () => {
images.forEach(url => URL.revokeObjectURL(url)); // Clean up object URLs
};
}, [images]);
if (loading) {
return <div>Loading...</div>; // Show loading indicator
} else {
return (
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
{images.length > 0 && (
<img
src={images[currentFrame]}
alt="Animation frame"
style={{ maxWidth: '100%', height: 'auto' }} // Responsive image
/>
)}
</div>
);
}
};
export default Animation;

View file

@ -1,6 +1,8 @@
import { useState } from 'react'
import '../css/global.css'
import BlackButton from './components/customButton'
import SpriteAnimation from './components/testAnimation_onefile'
import CharacterAnimation from './components/testAnimation_manyfiles'
function HomePage() {
@ -17,6 +19,11 @@ function HomePage() {
<div style={{ height: '8vh' }}/>
<CharacterAnimation/>
{/* <SpriteAnimation/> */}
<div style={{ height: '8vh' }}/>
<BlackButton text="Start" to='/warn'/>
</div>
)

View file

@ -4,4 +4,5 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
assetsInclude: ['**/*.zip'],
})