Add rotating hero image gallery for desktop breakpoint

- Add 5 new hero images to assets/images/hero-gallery/
- Create hero-section.js with image rotation (6s interval)
- Only preload/animate at >= 1450px to save mobile bandwidth
- Fade transition with slight grow effect
- Add overflow:hidden to prevent scrollbar during transition
- Images use 30% right crop via transform system

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hanson.xyz Dev
2025-11-30 22:38:34 -06:00
parent 1a4d41def6
commit 4be4edb4ad
20 changed files with 203 additions and 657 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 642 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 MiB

File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+20
View File
@@ -64,6 +64,25 @@ $featured_commercial = new WP_Query(array(
$fallback_image = get_template_directory_uri() . '/assets/images/hero.webp';
$logo_cropped = get_template_directory_uri() . '/assets/images/logo-cropped.webp';
// Build gallery images array for desktop hero rotation
// Include the original hero plus the 5 additional gallery images
$gallery_source_images = array(
'assets/images/hero-original.png',
'assets/images/hero-gallery/hero-2.png',
'assets/images/hero-gallery/hero-3.png',
'assets/images/hero-gallery/hero-4.jpg',
'assets/images/hero-gallery/hero-5.png',
'assets/images/hero-gallery/hero-6.png',
);
$gallery_images = array();
foreach ($gallery_source_images as $source) {
$transformed = homeproz_get_transformed_theme_image($source, 30, 2560, 90);
if ($transformed) {
$gallery_images[] = $transformed;
}
}
// Design 2: Two-column split (shown >= 1450px)
?>
<div class="hero-desktop-only">
@@ -78,6 +97,7 @@ $featured_commercial = new WP_Query(array(
'secondary_cta_text' => 'Contact Us',
'secondary_cta_url' => home_url('/contact/'),
'background_image' => $hero_image_split ?: $fallback_image,
'gallery_images' => $gallery_images,
'size' => 'large',
));
?>
+1
View File
@@ -8,6 +8,7 @@ import './main.scss';
// Import component JS
import '../template-parts/header/navigation.js';
import '../template-parts/components/hero-section.js';
import '../template-parts/property/property-filters.js';
import '../template-parts/property/property-gallery.js';
@@ -0,0 +1,168 @@
/**
* Hero Section Gallery - Image Rotation
*
* Rotates hero background images with fade transition.
* Only active at >= 1450px breakpoint. Pauses/resumes on resize.
* Only preloads images when at desktop breakpoint to save mobile bandwidth.
*
* @package HomeProz
*/
(function($) {
'use strict';
// Configuration
var ROTATION_INTERVAL = 6000; // milliseconds between image swaps
var BREAKPOINT = 1450; // minimum width for gallery to be active
var FADE_DURATION = 1000; // milliseconds for fade transition
// State
var galleryImages = [];
var currentIndex = 0;
var rotationTimer = null;
var isActive = false;
var imagesPreloaded = false;
var $heroImageElement = null;
/**
* Initialize the hero gallery
*/
function init() {
// Only run on homepage with split hero
if (!$('.Home_Page').length) return;
$heroImageElement = $('.hero-split-image');
if (!$heroImageElement.length) return;
// Get gallery images from data attribute
var imagesData = $heroImageElement.data('gallery-images');
if (!imagesData || !imagesData.length) return;
galleryImages = imagesData;
// Check initial viewport width
checkBreakpoint();
// Listen for resize events
$(window).on('resize', debounce(checkBreakpoint, 150));
}
/**
* Check if we're at the desktop breakpoint and start/stop accordingly
*/
function checkBreakpoint() {
var windowWidth = $(window).width();
if (windowWidth >= BREAKPOINT) {
if (!isActive) {
startGallery();
}
} else {
if (isActive) {
stopGallery();
}
}
}
/**
* Start the gallery rotation
*/
function startGallery() {
isActive = true;
// Preload images only when entering desktop mode (saves mobile bandwidth)
if (!imagesPreloaded) {
preloadImages();
imagesPreloaded = true;
}
// Start rotation timer
rotationTimer = setInterval(rotateImage, ROTATION_INTERVAL);
}
/**
* Stop the gallery rotation
*/
function stopGallery() {
isActive = false;
if (rotationTimer) {
clearInterval(rotationTimer);
rotationTimer = null;
}
}
/**
* Preload all gallery images using detached img elements
*/
function preloadImages() {
$.each(galleryImages, function(index, imageUrl) {
var img = new Image();
img.src = imageUrl;
});
}
/**
* Rotate to the next image with fade transition
*/
function rotateImage() {
// Move to next image
currentIndex = (currentIndex + 1) % galleryImages.length;
var nextImage = galleryImages[currentIndex];
// Create overlay element for crossfade
var $overlay = $('<div class="hero-split-image-overlay"></div>');
$overlay.css({
'position': 'absolute',
'top': 0,
'left': 0,
'right': 0,
'bottom': 0,
'background-image': 'url(' + nextImage + ')',
'background-size': 'cover',
'background-position': 'center center',
'background-repeat': 'no-repeat',
'opacity': 0,
'transform': 'scale(1.02)',
'transition': 'opacity ' + FADE_DURATION + 'ms ease-in-out, transform ' + FADE_DURATION + 'ms ease-in-out',
'z-index': 1
});
// Ensure hero image container has relative positioning
$heroImageElement.css('position', 'relative');
// Append overlay
$heroImageElement.append($overlay);
// Trigger reflow then animate
$overlay[0].offsetHeight; // Force reflow
$overlay.css({
'opacity': 1,
'transform': 'scale(1)'
});
// After transition, update background and remove overlay
setTimeout(function() {
$heroImageElement.css('background-image', 'url(' + nextImage + ')');
$overlay.remove();
}, FADE_DURATION);
}
/**
* Simple debounce function
*/
function debounce(func, wait) {
var timeout;
return function() {
var context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
};
}
// Initialize when DOM is ready
$(document).ready(init);
})(jQuery);
@@ -13,6 +13,7 @@
* - secondary_cta_text (string): Secondary button text
* - secondary_cta_url (string): Secondary button URL
* - background_image (string): Background image URL
* - gallery_images (array): Array of image URLs for rotation gallery
* - size (string): 'large' or 'small' (default: 'large')
* - show_location_search (bool): Show location search dropdown (default: false)
*/
@@ -31,11 +32,15 @@ $primary_cta_url = isset($args['primary_cta_url']) ? $args['primary_cta_url'] :
$secondary_cta_text = isset($args['secondary_cta_text']) ? $args['secondary_cta_text'] : '';
$secondary_cta_url = isset($args['secondary_cta_url']) ? $args['secondary_cta_url'] : '';
$background_image = isset($args['background_image']) ? $args['background_image'] : '';
$gallery_images = isset($args['gallery_images']) ? $args['gallery_images'] : array();
$size = isset($args['size']) ? $args['size'] : 'large';
$show_location_search = isset($args['show_location_search']) ? $args['show_location_search'] : false;
$size_class = $size === 'small' ? 'hero-section--small' : 'hero-section--large';
// Prepare gallery data attribute for JS
$gallery_data = !empty($gallery_images) ? esc_attr(wp_json_encode($gallery_images)) : '';
// Get locations for dropdown if needed
$locations = array();
if ($show_location_search) {
@@ -103,5 +108,8 @@ if ($show_location_search) {
<?php endif; ?>
</div>
</div>
<div class="hero-split-image" <?php echo $background_image ? 'style="background-image: url(' . esc_url($background_image) . ');"' : ''; ?>></div>
<div class="hero-split-image"
<?php echo $background_image ? 'style="background-image: url(' . esc_url($background_image) . ');"' : ''; ?>
<?php echo $gallery_data ? 'data-gallery-images="' . $gallery_data . '"' : ''; ?>
></div>
</section>
@@ -66,6 +66,8 @@
background-size: cover;
background-position: center center;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
@media (max-width: 768px) {
width: 100%;