From f9c1e24abe5108ebb42a29642a0f268d117e17d0 Mon Sep 17 00:00:00 2001 From: sasha-astiadi Date: Thu, 11 Sep 2025 13:55:36 +0200 Subject: [PATCH] ok --- css/animations.css | 193 +++++++++++++++++++++++++++++++++ static/js/custom.js | 159 +++++++++++++++++++++++++++ templates/partials/footer.html | 7 +- templates/partials/head.html | 1 + templates/partials/header.html | 5 - templates/partials/hero.html | 10 +- templates/shortcodes/row.html | 2 +- 7 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 css/animations.css diff --git a/css/animations.css b/css/animations.css new file mode 100644 index 0000000..96efa82 --- /dev/null +++ b/css/animations.css @@ -0,0 +1,193 @@ +/* Animation Styles for Homepage Components */ + +/* Base animation classes */ +.animate-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; +} + +.animate-fade-in.animate-visible { + opacity: 1; + transform: translateY(0); +} + +/* Slide in from left */ +.animate-slide-left { + opacity: 0; + transform: translateX(-50px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; +} + +.animate-slide-left.animate-visible { + opacity: 1; + transform: translateX(0); +} + +/* Slide in from right */ +.animate-slide-right { + opacity: 0; + transform: translateX(50px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; +} + +.animate-slide-right.animate-visible { + opacity: 1; + transform: translateX(0); +} + +/* Scale up animation */ +.animate-scale-up { + opacity: 0; + transform: scale(0.9); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; +} + +.animate-scale-up.animate-visible { + opacity: 1; + transform: scale(1); +} + +/* Staggered animations for multiple elements */ +.animate-stagger-1 { + transition-delay: 0.1s; +} + +.animate-stagger-2 { + transition-delay: 0.2s; +} + +.animate-stagger-3 { + transition-delay: 0.3s; +} + +.animate-stagger-4 { + transition-delay: 0.4s; +} + +.animate-stagger-5 { + transition-delay: 0.5s; +} + +/* Hero section specific animations */ +.hero-title { + opacity: 0; + transform: translateY(40px); + transition: opacity 1s ease-out, transform 1s ease-out; +} + +.hero-title.animate-visible { + opacity: 1; + transform: translateY(0); +} + +.hero-subtitle { + opacity: 0; + transform: translateY(30px); + transition: opacity 1s ease-out 0.3s, transform 1s ease-out 0.3s; +} + +.hero-subtitle.animate-visible { + opacity: 1; + transform: translateY(0); +} + +.hero-button { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.8s ease-out 0.6s, transform 0.8s ease-out 0.6s; +} + +.hero-button.animate-visible { + opacity: 1; + transform: translateY(0); +} + +/* Image animations */ +.animate-image { + opacity: 0; + transform: scale(1.1); + transition: opacity 1s ease-out, transform 1s ease-out; +} + +.animate-image.animate-visible { + opacity: 1; + transform: scale(1); +} + +/* Text content animations */ +.animate-text-content h1, +.animate-text-content h2, +.animate-text-content h3, +.animate-text-content h4 { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; +} + +.animate-text-content.animate-visible h1, +.animate-text-content.animate-visible h2, +.animate-text-content.animate-visible h3, +.animate-text-content.animate-visible h4 { + opacity: 1; + transform: translateY(0); +} + +.animate-text-content p { + opacity: 0; + transform: translateY(15px); + transition: opacity 0.8s ease-out 0.2s, transform 0.8s ease-out 0.2s; +} + +.animate-text-content.animate-visible p { + opacity: 1; + transform: translateY(0); +} + +.animate-text-content button, +.animate-text-content a[href] { + opacity: 0; + transform: translateY(10px); + transition: opacity 0.8s ease-out 0.4s, transform 0.8s ease-out 0.4s; +} + +.animate-text-content.animate-visible button, +.animate-text-content.animate-visible a[href] { + opacity: 1; + transform: translateY(0); +} + +/* Reduced motion for accessibility */ +@media (prefers-reduced-motion: reduce) { + .animate-fade-in, + .animate-slide-left, + .animate-slide-right, + .animate-scale-up, + .hero-title, + .hero-subtitle, + .hero-button, + .animate-image, + .animate-text-content h1, + .animate-text-content h2, + .animate-text-content h3, + .animate-text-content h4, + .animate-text-content p, + .animate-text-content button, + .animate-text-content a[href] { + transition: none; + opacity: 1; + transform: none; + } +} + +/* Loading animation for initial page load */ +.page-loading .animate-on-load { + opacity: 0; + transform: translateY(20px); +} + +.page-loaded .animate-on-load { + opacity: 1; + transform: translateY(0); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; +} diff --git a/static/js/custom.js b/static/js/custom.js index aa87508..33b2446 100644 --- a/static/js/custom.js +++ b/static/js/custom.js @@ -144,6 +144,8 @@ window.onload = function () { 'www.ourworld.tf', 'ourworld.tf', 'www2.ourworld.tf', + 'www2.freezone.ourworld.tf', + 'freezone.ourworld.tf', 'localhost', '127.0.0.1' ] @@ -169,3 +171,160 @@ window.onload = function () { function openInNewTab(url) { window.open(url, '_blank').focus() } + +// Animation System for Homepage Components +class AnimationController { + constructor() { + this.observer = null; + this.isPageLoaded = false; + this.init(); + } + + init() { + // Set up intersection observer for scroll animations + this.setupIntersectionObserver(); + + // Handle initial page load animations + this.handlePageLoad(); + + // Initialize animations when DOM is ready + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => this.initializeAnimations()); + } else { + this.initializeAnimations(); + } + } + + setupIntersectionObserver() { + const options = { + root: null, + rootMargin: '0px 0px -10% 0px', // Trigger when element is 10% visible + threshold: 0.1 + }; + + this.observer = new IntersectionObserver((entries) => { + entries.forEach(entry => { + if (entry.isIntersecting) { + this.animateElement(entry.target); + } + }); + }, options); + } + + animateElement(element) { + // Add visible class to trigger CSS animations + element.classList.add('animate-visible'); + + // Animate child elements with stagger effect + const children = element.querySelectorAll('.animate-stagger-1, .animate-stagger-2, .animate-stagger-3, .animate-stagger-4, .animate-stagger-5'); + children.forEach((child, index) => { + setTimeout(() => { + child.classList.add('animate-visible'); + }, index * 100); + }); + + // Stop observing this element once animated + this.observer.unobserve(element); + } + + handlePageLoad() { + // Add loading class initially + document.body.classList.add('page-loading'); + + window.addEventListener('load', () => { + this.isPageLoaded = true; + document.body.classList.remove('page-loading'); + document.body.classList.add('page-loaded'); + + // Animate hero section immediately on load + this.animateHeroSection(); + }); + } + + animateHeroSection() { + const heroElements = document.querySelectorAll('.hero-title, .hero-subtitle, .hero-button'); + heroElements.forEach(element => { + element.classList.add('animate-visible'); + }); + } + + initializeAnimations() { + // Find all elements that should be animated + const animatedElements = document.querySelectorAll( + '.animate-fade-in, .animate-slide-left, .animate-slide-right, .animate-scale-up, .animate-text-content, .animate-image' + ); + + // Start observing each element + animatedElements.forEach(element => { + this.observer.observe(element); + }); + + // Add animation classes to row containers + this.addAnimationClassesToRows(); + } + + addAnimationClassesToRows() { + // Get all row containers from the homepage + const rows = document.querySelectorAll('[id*="row"], .relative.justify-center.flex.overflow-hidden'); + + rows.forEach((row, index) => { + // Add different animation types based on position + const animationType = this.getAnimationTypeForRow(index); + row.classList.add(animationType); + + // Add text content animation to text columns + const textColumns = row.querySelectorAll('div[class*="flex-1"]'); + textColumns.forEach(column => { + if (this.hasTextContent(column)) { + column.classList.add('animate-text-content'); + } + + // Add image animation to image containers + const images = column.querySelectorAll('img'); + images.forEach(img => { + img.parentElement.classList.add('animate-image'); + }); + }); + }); + } + + getAnimationTypeForRow(index) { + const animations = ['animate-fade-in', 'animate-slide-left', 'animate-slide-right', 'animate-scale-up']; + return animations[index % animations.length]; + } + + hasTextContent(element) { + const textElements = element.querySelectorAll('h1, h2, h3, h4, p, button, a'); + return textElements.length > 0; + } + + // Method to trigger animations on scroll direction change + handleScrollDirection() { + let lastScrollTop = 0; + + window.addEventListener('scroll', () => { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const scrollDirection = scrollTop > lastScrollTop ? 'down' : 'up'; + + // You can add specific animations based on scroll direction here + document.body.setAttribute('data-scroll-direction', scrollDirection); + + lastScrollTop = scrollTop <= 0 ? 0 : scrollTop; + }, false); + } +} + +// Initialize animation system +let animationController; + +// Enhanced window.onload to include animations +const originalWindowOnload = window.onload; +window.onload = function() { + // Call original onload function + if (originalWindowOnload) { + originalWindowOnload(); + } + + // Initialize animation controller + animationController = new AnimationController(); +} diff --git a/templates/partials/footer.html b/templates/partials/footer.html index 1a6c993..1ccd734 100644 --- a/templates/partials/footer.html +++ b/templates/partials/footer.html @@ -5,13 +5,8 @@