public pages content
This commit is contained in:
138
templates/components/animated_numbers.html
Normal file
138
templates/components/animated_numbers.html
Normal file
@@ -0,0 +1,138 @@
|
||||
<!-- Animated Numbers Component -->
|
||||
<div class="stats-section">
|
||||
<div class="container">
|
||||
<div class="row text-center">
|
||||
{% for stat in stats %}
|
||||
<div class="col-md-{{ 12 // stats|length }}">
|
||||
<div class="stat-item">
|
||||
<span class="stat-number" data-value="{{ stat.value }}" data-suffix="{{ stat.suffix }}">{{ stat.display }}</span>
|
||||
<div class="stat-label">{{ stat.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.stats-section {
|
||||
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
|
||||
color: white;
|
||||
padding: 80px 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stats-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="1" fill="white" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 1.1rem;
|
||||
opacity: 0.9;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
// Function to animate number counting
|
||||
function animateNumber(element, endValue, suffix = '', duration = 2000) {
|
||||
const start = performance.now();
|
||||
const startValue = 0;
|
||||
const difference = endValue - startValue;
|
||||
|
||||
function updateNumber(currentTime) {
|
||||
const elapsed = currentTime - start;
|
||||
const progress = Math.min(elapsed / duration, 1);
|
||||
|
||||
// Easing function for smooth animation
|
||||
const easeOutQuart = 1 - Math.pow(1 - progress, 4);
|
||||
const currentValue = startValue + (difference * easeOutQuart);
|
||||
|
||||
// Format the number based on the suffix
|
||||
let displayValue;
|
||||
if (suffix === '%') {
|
||||
displayValue = currentValue.toFixed(1) + suffix;
|
||||
} else if (suffix === '-bit') {
|
||||
displayValue = Math.round(currentValue) + suffix;
|
||||
} else if (suffix === '/7') {
|
||||
displayValue = Math.round(currentValue) + suffix;
|
||||
} else if (suffix === '+') {
|
||||
displayValue = Math.round(currentValue) + suffix;
|
||||
} else if (suffix === 'K+') {
|
||||
displayValue = Math.round(currentValue) + suffix;
|
||||
} else {
|
||||
displayValue = Math.round(currentValue) + (suffix || '');
|
||||
}
|
||||
|
||||
element.textContent = displayValue;
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(updateNumber);
|
||||
} else {
|
||||
// Ensure the final value is correct
|
||||
element.textContent = element.getAttribute('data-value') + (suffix || '');
|
||||
}
|
||||
}
|
||||
|
||||
requestAnimationFrame(updateNumber);
|
||||
}
|
||||
|
||||
// Initialize animated numbers when component is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const statsObserver = new IntersectionObserver(function(entries) {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const statNumbers = entry.target.querySelectorAll('.stat-number');
|
||||
statNumbers.forEach((stat, index) => {
|
||||
setTimeout(() => {
|
||||
const value = parseFloat(stat.getAttribute('data-value'));
|
||||
const suffix = stat.getAttribute('data-suffix') || '';
|
||||
|
||||
if (!isNaN(value)) {
|
||||
animateNumber(stat, value, suffix, 2000);
|
||||
}
|
||||
}, index * 300); // Stagger the animations
|
||||
});
|
||||
|
||||
// Only trigger once
|
||||
statsObserver.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.5 });
|
||||
|
||||
// Observe the stats section
|
||||
const statsSection = document.querySelector('.stats-section');
|
||||
if (statsSection) {
|
||||
statsObserver.observe(statsSection);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -17,7 +17,6 @@
|
||||
<h6 class="mb-3" style="color: var(--white);">Company</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">About</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Blog</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Careers</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Press</a></li>
|
||||
</ul>
|
||||
@@ -27,7 +26,6 @@
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Help Center</a></li>
|
||||
<li><a href="#contact" style="color: var(--border-light); text-decoration: none;">Contact</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Status</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Security</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -36,8 +34,7 @@
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Privacy</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Terms</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">GDPR</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Compliance</a></li>
|
||||
<li><a href="#" style="color: var(--border-light); text-decoration: none;">Cookies</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
</a>
|
||||
<ul class="dropdown-menu" style="background-color: var(--white); border: 1px solid var(--border-color); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);">
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.about') }}" style="color: var(--text-dark);">About</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.blog') }}" style="color: var(--text-dark);">Blog</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.careers') }}" style="color: var(--text-dark);">Careers</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.press') }}" style="color: var(--text-dark);">Press</a></li>
|
||||
</ul>
|
||||
@@ -36,7 +35,6 @@
|
||||
<ul class="dropdown-menu" style="background-color: var(--white); border: 1px solid var(--border-color); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);">
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.help_center') }}" style="color: var(--text-dark);">Help Center</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.contact') }}" style="color: var(--text-dark);">Contact</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.status') }}" style="color: var(--text-dark);">Status</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.security') }}" style="color: var(--text-dark);">Security</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -47,8 +45,7 @@
|
||||
<ul class="dropdown-menu" style="background-color: var(--white); border: 1px solid var(--border-color); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);">
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.privacy') }}" style="color: var(--text-dark);">Privacy</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.terms') }}" style="color: var(--text-dark);">Terms</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.gdpr') }}" style="color: var(--text-dark);">GDPR</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.compliance') }}" style="color: var(--text-dark);">Compliance</a></li>
|
||||
<li><a class="dropdown-item" href="{{ url_for('public.cookies') }}" style="color: var(--text-dark);">Cookies</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user