suryajs-animfx
Version:
SuryaJS - A powerful JavaScript animation library with 20+ image, text, and advanced 3D effects
576 lines (456 loc) • 18.3 kB
JavaScript
class AdvancedEffects {
constructor() {
this.mouseFollowers = new Map();
this.mouseMagnets = new Map();
this.isMouseTracking = false;
this.mousePosition = { x: 0, y: 0 };
this.init();
}
init() {
// Initialize mouse tracking
this.initMouseTracking();
}
initMouseTracking() {
if (!this.isMouseTracking) {
document.addEventListener('mousemove', (e) => {
this.mousePosition.x = e.clientX;
this.mousePosition.y = e.clientY;
this.updateMouseFollowers();
this.updateMouseMagnets();
});
this.isMouseTracking = true;
}
}
// Effect 6: Mouse Follower
mouseFollower(elements, options = {}) {
const speed = options.speed || 0.1;
const distance = options.distance || 50;
const scale = options.scale || 1.2;
elements.forEach((element, index) => {
if (!element) return;
// Create follower element
const follower = document.createElement('div');
follower.style.position = 'fixed';
follower.style.width = '20px';
follower.style.height = '20px';
follower.style.background = options.color || '#667eea';
follower.style.borderRadius = '50%';
follower.style.pointerEvents = 'none';
follower.style.zIndex = '9999';
follower.style.transition = 'all 0.1s ease';
follower.style.opacity = '0.8';
follower.style.boxShadow = '0 0 20px rgba(102, 126, 234, 0.5)';
document.body.appendChild(follower);
// Store follower reference
this.mouseFollowers.set(element, {
follower: follower,
speed: speed,
distance: distance + (index * 10),
targetX: 0,
targetY: 0,
currentX: 0,
currentY: 0
});
// Add hover effects to original element
element.addEventListener('mouseenter', () => {
element.style.transform = `scale(${scale})`;
element.style.transition = 'transform 0.3s ease';
follower.style.transform = 'scale(1.5)';
follower.style.background = options.hoverColor || '#e17055';
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'scale(1)';
follower.style.transform = 'scale(1)';
follower.style.background = options.color || '#667eea';
});
});
}
// Effect 7: Mouse Magnet
mouseMagnet(elements, options = {}) {
const strength = options.strength || 0.3;
const distance = options.distance || 100;
elements.forEach((element, index) => {
if (!element) return;
element.style.transition = 'transform 0.3s ease';
this.mouseMagnets.set(element, {
strength: strength,
distance: distance,
originalX: 0,
originalY: 0
});
// Store original position
const rect = element.getBoundingClientRect();
const magnetData = this.mouseMagnets.get(element);
magnetData.originalX = rect.left + rect.width / 2;
magnetData.originalY = rect.top + rect.height / 2;
});
}
// Effect 8: 3D Tilt
tilt3D(elements, options = {}) {
const maxTilt = options.maxTilt || 15;
const perspective = options.perspective || 1000;
const scale = options.scale || 1.05;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.transition = 'transform 0.3s ease';
element.addEventListener('mouseenter', () => {
element.style.transform = `perspective(${perspective}px) scale(${scale})`;
});
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = (e.clientX - centerX) / (rect.width / 2);
const deltaY = (e.clientY - centerY) / (rect.height / 2);
const rotateX = deltaY * maxTilt;
const rotateY = deltaX * maxTilt;
element.style.transform = `perspective(${perspective}px) scale(${scale}) rotateX(${-rotateX}deg) rotateY(${rotateY}deg)`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'perspective(1000px) scale(1) rotateX(0deg) rotateY(0deg)';
});
});
}
// Effect 9: Parallax 3D
parallax3D(elements, options = {}) {
const depth = options.depth || 0.5;
const speed = options.speed || 0.1;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.transition = 'transform 0.1s ease';
const layerDepth = depth * (index + 1);
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = (e.clientX - centerX) * speed * layerDepth;
const deltaY = (e.clientY - centerY) * speed * layerDepth;
element.style.transform = `translate3d(${deltaX}px, ${deltaY}px, ${layerDepth * 10}px)`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'translate3d(0px, 0px, 0px)';
});
});
}
// Effect 10: Magnetic Pull
magneticPull(elements, options = {}) {
const pullStrength = options.pullStrength || 0.4;
const pullDistance = options.pullDistance || 80;
elements.forEach((element, index) => {
if (!element) return;
element.style.transition = 'transform 0.2s ease';
document.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const distance = Math.sqrt(
Math.pow(e.clientX - centerX, 2) + Math.pow(e.clientY - centerY, 2)
);
if (distance < pullDistance) {
const force = (pullDistance - distance) / pullDistance;
const deltaX = (e.clientX - centerX) * force * pullStrength;
const deltaY = (e.clientY - centerY) * force * pullStrength;
element.style.transform = `translate(${deltaX}px, ${deltaY}px) scale(${1 + force * 0.1})`;
} else {
element.style.transform = 'translate(0px, 0px) scale(1)';
}
});
});
}
// Update mouse followers
updateMouseFollowers() {
this.mouseFollowers.forEach((data, element) => {
const { follower, speed, distance } = data;
data.targetX = this.mousePosition.x - distance;
data.targetY = this.mousePosition.y - distance;
data.currentX += (data.targetX - data.currentX) * speed;
data.currentY += (data.targetY - data.currentY) * speed;
follower.style.left = data.currentX + 'px';
follower.style.top = data.currentY + 'px';
});
}
// Update mouse magnets
updateMouseMagnets() {
this.mouseMagnets.forEach((data, element) => {
const { strength, distance } = data;
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = this.mousePosition.x - centerX;
const deltaY = this.mousePosition.y - centerY;
const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (dist < distance) {
const force = (distance - dist) / distance;
const moveX = deltaX * force * strength;
const moveY = deltaY * force * strength;
element.style.transform = `translate(${moveX}px, ${moveY}px) scale(${1 + force * 0.1})`;
} else {
element.style.transform = 'translate(0px, 0px) scale(1)';
}
});
}
// Effect 11: Liquid Distortion
liquidDistortion(elements, options = {}) {
const intensity = options.intensity || 20;
const speed = options.speed || 0.02;
elements.forEach((element, index) => {
if (!element) return;
let animationId;
let startTime = Date.now();
const animate = () => {
const elapsed = Date.now() - startTime;
const wave1 = Math.sin(elapsed * speed) * intensity;
const wave2 = Math.cos(elapsed * speed * 1.5) * intensity * 0.5;
element.style.transform = `skew(${wave1 * 0.1}deg, ${wave2 * 0.1}deg) scale(${1 + Math.sin(elapsed * speed * 0.5) * 0.05})`;
element.style.filter = `hue-rotate(${wave1 * 2}deg)`;
animationId = requestAnimationFrame(animate);
};
element.addEventListener('mouseenter', () => {
animate();
});
element.addEventListener('mouseleave', () => {
if (animationId) {
cancelAnimationFrame(animationId);
}
element.style.transform = 'none';
element.style.filter = 'none';
});
});
}
// Effect 12: Floating Animation
floatingAnimation(elements, options = {}) {
const amplitude = options.amplitude || 10;
const speed = options.speed || 0.02;
elements.forEach((element, index) => {
if (!element) return;
const startTime = Date.now() + (index * 1000); // Stagger start times
const animate = () => {
const elapsed = Date.now() - startTime;
const y = Math.sin(elapsed * speed) * amplitude;
const rotation = Math.sin(elapsed * speed * 0.5) * 2;
element.style.transform = `translateY(${y}px) rotate(${rotation}deg)`;
requestAnimationFrame(animate);
};
animate();
});
}
// Effect 13: Morphing Shape
morphingShape(elements, options = {}) {
const morphSteps = options.morphSteps || [
'border-radius: 50%',
'border-radius: 0% 50% 50% 50%',
'border-radius: 50% 0% 50% 50%',
'border-radius: 50% 50% 0% 50%',
'border-radius: 50% 50% 50% 0%',
'border-radius: 0%'
];
const duration = options.duration || 3000;
elements.forEach((element, index) => {
if (!element) return;
let currentStep = 0;
const morph = () => {
element.style.cssText += morphSteps[currentStep];
element.style.transition = 'all 0.5s ease';
currentStep = (currentStep + 1) % morphSteps.length;
setTimeout(morph, duration / morphSteps.length);
};
setTimeout(() => {
morph();
}, index * 500);
});
}
// Effect 14: 3D Card Flip
card3DFlip(elements, options = {}) {
const perspective = options.perspective || 1000;
const duration = options.duration || 800;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.perspective = perspective + 'px';
element.style.cursor = 'pointer';
element.addEventListener('click', () => {
const isFlipped = element.classList.contains('flipped-3d');
if (!isFlipped) {
element.style.transition = `transform ${duration}ms ease`;
element.style.transform = 'rotateY(180deg)';
element.classList.add('flipped-3d');
} else {
element.style.transform = 'rotateY(0deg)';
element.classList.remove('flipped-3d');
}
});
});
}
// Effect 15: 3D Cube Rotation
cube3DRotation(elements, options = {}) {
const speed = options.speed || 0.02;
const amplitude = options.amplitude || 15;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.perspective = '1000px';
let animationId;
let startTime = Date.now() + (index * 1000);
const animate = () => {
const elapsed = Date.now() - startTime;
const rotateX = Math.sin(elapsed * speed) * amplitude;
const rotateY = Math.cos(elapsed * speed * 0.7) * amplitude;
const rotateZ = Math.sin(elapsed * speed * 0.5) * (amplitude * 0.5);
element.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`;
animationId = requestAnimationFrame(animate);
};
element.addEventListener('mouseenter', () => {
animate();
});
element.addEventListener('mouseleave', () => {
if (animationId) {
cancelAnimationFrame(animationId);
}
element.style.transform = 'perspective(1000px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)';
});
});
}
// Effect 16: 3D Depth Layers
depth3DLayers(elements, options = {}) {
const maxDepth = options.maxDepth || 100;
const sensitivity = options.sensitivity || 0.1;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.transition = 'transform 0.2s ease';
const depth = (index + 1) * 20;
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = (e.clientX - centerX) * sensitivity;
const deltaY = (e.clientY - centerY) * sensitivity;
element.style.transform = `
perspective(1000px)
translate3d(${deltaX}px, ${deltaY}px, ${depth}px)
rotateX(${-deltaY * 0.1}deg)
rotateY(${deltaX * 0.1}deg)
`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = `perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg)`;
});
});
}
// Effect 17: 3D Hover Lift
hover3DLift(elements, options = {}) {
const liftHeight = options.liftHeight || 50;
const tiltAngle = options.tiltAngle || 10;
const scale = options.scale || 1.05;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.transition = 'all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
element.style.cursor = 'pointer';
element.addEventListener('mouseenter', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const deltaX = (e.clientX - centerX) / (rect.width / 2);
const deltaY = (e.clientY - centerY) / (rect.height / 2);
const rotateX = deltaY * tiltAngle;
const rotateY = deltaX * tiltAngle;
element.style.transform = `
perspective(1000px)
translate3d(0px, -${liftHeight}px, 0px)
rotateX(${-rotateX}deg)
rotateY(${rotateY}deg)
scale3d(${scale}, ${scale}, ${scale})
`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = 'perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg) rotateY(0deg) scale3d(1, 1, 1)';
});
});
}
// Effect 18: 3D Perspective Shift
perspective3DShift(elements, options = {}) {
const maxRotation = options.maxRotation || 25;
const perspective = options.perspective || 1000;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.perspective = perspective + 'px';
element.style.transition = 'transform 0.3s ease';
element.addEventListener('mousemove', (e) => {
const rect = element.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
const rotateY = ((e.clientX - centerX) / (rect.width / 2)) * maxRotation;
const rotateX = ((e.clientY - centerY) / (rect.height / 2)) * -maxRotation;
element.style.transform = `perspective(${perspective}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
element.addEventListener('mouseleave', () => {
element.style.transform = `perspective(${perspective}px) rotateX(0deg) rotateY(0deg)`;
});
});
}
// Effect 19: 3D Ripple Wave
ripple3DWave(elements, options = {}) {
const waveHeight = options.waveHeight || 30;
const waveSpeed = options.waveSpeed || 0.05;
elements.forEach((element, index) => {
if (!element) return;
element.style.transformStyle = 'preserve-3d';
element.style.perspective = '1000px';
let animationId;
let startTime = Date.now() + (index * 200);
const animate = () => {
const elapsed = Date.now() - startTime;
const wave1 = Math.sin(elapsed * waveSpeed) * waveHeight;
const wave2 = Math.cos(elapsed * waveSpeed * 1.5) * (waveHeight * 0.5);
const wave3 = Math.sin(elapsed * waveSpeed * 0.8) * (waveHeight * 0.3);
element.style.transform = `
perspective(1000px)
translate3d(0px, ${wave1}px, ${wave2}px)
rotateX(${wave3}deg)
`;
animationId = requestAnimationFrame(animate);
};
element.addEventListener('mouseenter', () => {
animate();
});
element.addEventListener('mouseleave', () => {
if (animationId) {
cancelAnimationFrame(animationId);
}
element.style.transform = 'perspective(1000px) translate3d(0px, 0px, 0px) rotateX(0deg)';
});
});
}
// Cleanup methods
removeMouseFollower(element) {
const data = this.mouseFollowers.get(element);
if (data && data.follower) {
data.follower.remove();
this.mouseFollowers.delete(element);
}
}
removeMouseMagnet(element) {
this.mouseMagnets.delete(element);
element.style.transform = 'none';
}
// Cleanup all effects
cleanup() {
// Remove all mouse followers
this.mouseFollowers.forEach((data, element) => {
if (data.follower) {
data.follower.remove();
}
});
this.mouseFollowers.clear();
// Reset all magnets
this.mouseMagnets.forEach((data, element) => {
element.style.transform = 'none';
});
this.mouseMagnets.clear();
}
}
export default AdvancedEffects;