diff --git a/src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip b/src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip
new file mode 100644
index 0000000..bc401ae
Binary files /dev/null and b/src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip differ
diff --git a/src/pages/components/animation.jsx b/src/pages/components/animation.jsx
index ff3f5e6..b2c4fc4 100644
--- a/src/pages/components/animation.jsx
+++ b/src/pages/components/animation.jsx
@@ -1,79 +1,403 @@
-import React, { useEffect, useState } from 'react';
-import JSZip from 'jszip';
+//version 1
+ // import React, { useEffect, useState } from 'react';
+ // import JSZip from 'jszip';
-const Animation = ({src="src/assets/mainCharacters/M_Porsche_cross_arm.zip" ,animationWidth="500px"}) => {
- const [images, setImages] = useState([]);
- const [currentFrame, setCurrentFrame] = useState(0);
- const [loading, setLoading] = useState(true);
- const frameRate = 1000/24;
+ // const Animation = ({src="src/assets/mainCharacters/M_Porsche_cross_arm.zip" ,animationWidth="500px"}) => {
+ // const [images, setImages] = useState([]);
+ // const [currentFrame, setCurrentFrame] = useState(0);
+ // const [loading, setLoading] = useState(true);
+ // const frameRate = 1000/24;
- useEffect(() => {
- const loadImages = async () => {
- const zip = new JSZip();
- try {
- const response = await fetch(src);
- if (!response.ok) {
- throw new Error('Network response was not ok');
- }
- const data = await response.arrayBuffer();
- const zipContent = await zip.loadAsync(data);
+ // useEffect(() => {
+ // const loadImages = async () => {
+ // const zip = new JSZip();
+ // try {
+ // const response = await fetch(src);
+ // 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('base64').then(base64 => {
- return `data:image/webp;base64,${base64}`;
- })
- );
+ // const imgPromises = [];
+ // zipContent.forEach((relativePath, file) => {
+ // if (file.name.endsWith('.webp')) {
+ // imgPromises.push(
+ // file.async('base64').then(base64 => {
+ // return `data:image/webp;base64,${base64}`;
+ // })
+ // );
+ // }
+ // });
+
+ // const imgUrls = await Promise.all(imgPromises);
+
+ // if (imgUrls.length === 0) {
+ // console.error('No images found in the ZIP file.');
+ // }
+
+ // setImages(imgUrls);
+ // } catch (error) {
+ // console.error('Error loading images:', error);
+ // } finally {
+ // setLoading(false);
+ // }
+ // };
+
+ // loadImages();
+
+ // }, []);
+
+ // useEffect(() => {
+ // if (images.length > 0) {
+ // const interval = setInterval(() => {
+ // setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
+ // }, frameRate);
+
+ // return () => clearInterval(interval);
+ // }
+ // }, [images]);
+
+ // if (loading) {
+ // return
Loading...
;
+ // } else {
+ // return (
+ //
+ // {images.length > 0 ? (
+ //

+ // ) : (
+ //
No images to display.
+ // )}
+ //
+ // );
+ // }
+ // };
+
+ // export default Animation;
+
+//version 2
+ // import React, { useEffect, useState, useRef } from 'react';
+ // import JSZip from 'jszip';
+
+ // const Animation = ({ src = "src/assets/mainCharacters/M_Porsche_cross_arm.zip", animationWidth = "500px" }) => {
+ // const [images, setImages] = useState([]);
+ // const [loading, setLoading] = useState(true);
+ // const frameRate = 1000 / 24; // Original frame rate (24 FPS)
+ // const canvasRef = useRef(null);
+ // const animationRef = useRef(null);
+ // const currentFrameRef = useRef(0);
+ // const imageElementsRef = useRef([]);
+
+ // useEffect(() => {
+ // const loadImages = async () => {
+ // const zip = new JSZip();
+ // try {
+ // const response = await fetch(src);
+ // 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('base64').then(base64 => {
+ // const img = new Image();
+ // img.src = `data:image/webp;base64,${base64}`;
+ // return img; // Return the Image object
+ // })
+ // );
+ // }
+ // });
+
+ // const imgElements = await Promise.all(imgPromises);
+
+ // if (imgElements.length === 0) {
+ // console.error('No images found in the ZIP file.');
+ // }
+
+ // imageElementsRef.current = imgElements; // Store preloaded images
+ // setImages(imgElements); // Set images state
+ // } catch (error) {
+ // console.error('Error loading images:', error);
+ // } finally {
+ // setLoading(false);
+ // }
+ // };
+
+ // loadImages();
+ // }, [src]);
+
+ // useEffect(() => {
+ // if (images.length > 0) {
+ // const canvas = canvasRef.current;
+ // const ctx = canvas.getContext('2d');
+ // let lastFrameTime = 0;
+
+ // const animate = (timestamp) => {
+ // if (lastFrameTime === 0) lastFrameTime = timestamp;
+
+ // const elapsed = timestamp - lastFrameTime;
+ // if (elapsed > frameRate) {
+ // currentFrameRef.current = (currentFrameRef.current + 1) % images.length;
+ // lastFrameTime = timestamp;
+ // }
+
+ // // Clear the canvas
+ // ctx.clearRect(0, 0, canvas.width, canvas.height);
+ // // Draw the current frame
+ // ctx.drawImage(imageElementsRef.current[currentFrameRef.current], 0, 0, canvas.width, canvas.height);
+
+ // animationRef.current = requestAnimationFrame(animate);
+ // };
+
+ // animationRef.current = requestAnimationFrame(animate);
+
+ // return () => {
+ // if (animationRef.current) {
+ // cancelAnimationFrame(animationRef.current);
+ // }
+ // };
+ // }
+ // }, [images]);
+
+ // if (loading) {
+ // return Loading...
;
+ // } else {
+ // return (
+ //
+ //
+ //
+ // );
+ // }
+ // };
+
+ // export default Animation;
+
+ import React, { useEffect, useState, useRef } from 'react';
+ import JSZip from 'jszip';
+
+ const Animation = ({ src = "src/assets/mainCharacters_pow2/M_porsche_cross_arm_power2.zip", animationWidth = "500px" }) => {
+ const [images, setImages] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const frameRate = 1000 / 24; // Original frame rate (24 FPS)
+ const canvasRef = useRef(null);
+ const animationRef = useRef(null);
+ const currentFrameRef = useRef(0);
+ const imageElementsRef = useRef([]);
+
+ // Load images from the ZIP file
+ useEffect(() => {
+ const loadImages = async () => {
+ const zip = new JSZip();
+ try {
+ const response = await fetch(src);
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
}
- });
-
- const imgUrls = await Promise.all(imgPromises);
-
- if (imgUrls.length === 0) {
- console.error('No images found in the ZIP file.');
+ 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('base64').then(base64 => {
+ const img = new Image();
+ img.src = `data:image/webp;base64,${base64}`;
+ return new Promise((resolve, reject) => {
+ img.onload = () => resolve(img);
+ img.onerror = reject;
+ });
+ })
+ );
+ }
+ });
+
+ const imgElements = await Promise.all(imgPromises);
+
+ if (imgElements.length === 0) {
+ console.error('No images found in the ZIP file.');
+ }
+
+ imageElementsRef.current = imgElements; // Store preloaded images
+ setImages(imgElements); // Set images state
+ } catch (error) {
+ console.error('Error loading images:', error);
+ } finally {
+ setLoading(false);
}
+ };
+
+ loadImages();
+ }, [src]);
+
+ // WebGL setup and animation loop
+ useEffect(() => {
+ if (images.length > 0) {
+ const canvas = canvasRef.current;
+ const gl = canvas.getContext('webgl');
+ if (!gl) {
+ console.error("WebGL is not supported.");
+ return;
+ }
+
+ // Set up WebGL context (basic)
+ gl.clearColor(0.0, 0.0, 0.0, 0.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.viewport(0, 0, canvas.width, canvas.height);
- setImages(imgUrls);
- } catch (error) {
- console.error('Error loading images:', error);
- } finally {
- setLoading(false);
+ // Enable blending
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+ // gl.blendFunc(gl.SRC_COLOR, gl.DST_COLOR);
+
+ // Shader program
+ const vertexShaderSource = `
+ attribute vec2 a_position;
+ attribute vec2 a_texCoord;
+ varying vec2 v_texCoord;
+ void main() {
+ gl_Position = vec4(a_position, 0.0, 1.0);
+ v_texCoord = a_texCoord;
+ }
+ `;
+ const fragmentShaderSource = `
+ precision mediump float;
+ uniform sampler2D u_texture;
+ varying vec2 v_texCoord;
+ void main() {
+ gl_FragColor = texture2D(u_texture, v_texCoord);
+ }
+ `;
+
+ const createShader = (source, type) => {
+ const shader = gl.createShader(type);
+ gl.shaderSource(shader, source);
+ gl.compileShader(shader);
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+ console.error('ERROR compiling shader', gl.getShaderInfoLog(shader));
+ }
+ return shader;
+ };
+
+ const vertexShader = createShader(vertexShaderSource, gl.VERTEX_SHADER);
+ const fragmentShader = createShader(fragmentShaderSource, gl.FRAGMENT_SHADER);
+
+ const shaderProgram = gl.createProgram();
+ gl.attachShader(shaderProgram, vertexShader);
+ gl.attachShader(shaderProgram, fragmentShader);
+ gl.linkProgram(shaderProgram);
+ if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
+ console.error('ERROR linking program', gl.getProgramInfoLog(shaderProgram));
+ }
+ gl.useProgram(shaderProgram);
+
+ // Create buffer and set up attributes
+ const positionBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ const vertices = new Float32Array([
+ -1.0, -1.0, // Bottom-left
+ 1.0, -1.0, // Bottom-right
+ -1.0, 1.0, // Top-left
+ 1.0, 1.0 // Top-right
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+ const positionLocation = gl.getAttribLocation(shaderProgram, "a_position");
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(positionLocation);
+
+ // Create texture and load image
+ const texture = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+
+ const loadTexture = (image) => {
+ gl.bindTexture(gl.TEXTURE_2D, texture);
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+
+ gl.generateMipmap(gl.TEXTURE_2D);
+ };
+
+ loadTexture(imageElementsRef.current[0]); // Initially load the first image
+
+ // Texture coordinates
+ const texCoordBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
+ const texCoords = new Float32Array([
+ 0.0, 1.0, // Bottom-left (now corresponds to top-left of the image)
+ 1.0, 1.0, // Bottom-right (now corresponds to top-right of the image)
+ 0.0, 0.0, // Top-left (now corresponds to bottom-left of the image)
+ 1.0, 0.0 // Top-right (now corresponds to bottom-right of the image)
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, texCoords, gl.STATIC_DRAW);
+
+ const texCoordLocation = gl.getAttribLocation(shaderProgram, "a_texCoord");
+ gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
+ gl.enableVertexAttribArray(texCoordLocation);
+
+ const uTextureLocation = gl.getUniformLocation(shaderProgram, "u_texture");
+
+ let lastFrameTime = 0;
+ const animate = (timestamp) => {
+ if (lastFrameTime === 0) lastFrameTime = timestamp;
+
+ const elapsed = timestamp - lastFrameTime;
+ if (elapsed > frameRate) {
+ currentFrameRef.current = (currentFrameRef.current + 1) % images.length;
+ loadTexture(imageElementsRef.current[currentFrameRef.current]);
+ lastFrameTime = timestamp;
+ }
+
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+
+ animationRef.current = requestAnimationFrame(animate);
+ };
+
+ animationRef.current = requestAnimationFrame(animate);
+
+ return () => {
+ if (animationRef.current) {
+ cancelAnimationFrame(animationRef.current);
+ }
+ };
}
- };
-
- loadImages();
-
- }, []);
-
- useEffect(() => {
- if (images.length > 0) {
- const interval = setInterval(() => {
- setCurrentFrame((prevFrame) => (prevFrame + 1) % images.length);
- }, frameRate);
-
- return () => clearInterval(interval);
- }
- }, [images]);
-
- if (loading) {
- return Loading...
;
- } else {
- return (
-
- {images.length > 0 ? (
-

Loading...
;
+ } else {
+ return (
+
+
- ) : (
-
No images to display.
- )}
-
- );
- }
-};
-
-export default Animation;
+
+ );
+ }
+ };
+
+ export default Animation;
+
+
\ No newline at end of file