banner updated

This commit is contained in:
Alaguraj0361 2025-10-02 17:25:45 +05:30
parent 0124c57991
commit c8f24b2b12
5 changed files with 276 additions and 440 deletions

View File

@ -23,8 +23,8 @@ export default function Blog() {
<div key={i} className="col-lg-4 col-md-6 col-sm-12 news-block">
<div
className="news-block-one wow fadeInUp animated"
data-wow-delay={`${i * 300}ms`}
data-wow-duration="1500ms"
data-wow-delay={`${i * 20}ms`}
data-wow-duration="300ms"
>
<div className="inner-box">
<figure className="image-box">

View File

@ -1,237 +1,161 @@
'use client'
import React, { useState } from 'react';
import Link from "next/link";
import { Autoplay, Navigation, Pagination } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
import { motion, AnimatePresence } from "framer-motion";
"use client"
import React, { useState } from "react"
import Link from "next/link"
import { useKeenSlider } from "keen-slider/react"
import "keen-slider/keen-slider.min.css"
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
const swiperOptions = {
modules: [Autoplay, Pagination, Navigation],
slidesPerView: 1,
spaceBetween: 0,
autoplay: {
delay: 2000,
disableOnInteraction: false,
pauseOnMouseEnter: true, // stops on hover for smooth UX
},
speed: 1500, // increase speed for smoother sliding
loop: true,
navigation: {
nextEl: '.h1n',
prevEl: '.h1p',
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
effect: "slide", // ensures smooth slide effect
};
const variants = {
topToBottom: {
initial: { y: '-100vh', opacity: 0 },
animate: { y: 0, opacity: 1 },
exit: { y: '100vh', opacity: 0 }
},
bottomToTop: {
initial: { y: '100vh', opacity: 0 },
animate: { y: 0, opacity: 1 },
exit: { y: '-100vh', opacity: 0 }
},
leftToRight: {
initial: { x: '-100vw', opacity: 0 },
animate: { x: 0, opacity: 1 },
exit: { x: '100vw', opacity: 0 }
},
rightToLeft: {
initial: { x: '100vw', opacity: 0 },
animate: {
x: 0,
opacity: 1,
transition: {
duration: 0.8, // adjust speed
ease: "easeInOut" // try "easeOut", "easeIn", or custom [0.4, 0, 0.2, 1]
}
},
exit: {
x: "-100vw",
opacity: 0,
transition: {
duration: 0.6,
ease: "easeInOut"
}
}
},
};
const revealVariants = {
hidden: {
scaleX: 0,
opacity: 0,
originX: 0, // same as transform-origin: 0% 50%
},
visible: {
scaleX: 1,
opacity: 1,
originX: 0,
transition: {
duration: 0.6,
ease: "easeInOut"
}
},
exit: {
scaleX: 0,
opacity: 0,
originX: 0,
transition: {
duration: 0.6,
ease: "easeInOut"
}
// Autoplay plugin
function AutoplaySlider(slider) {
let timeout
let mouseOver = false
function clearNextTimeout() {
clearTimeout(timeout)
}
};
const transition = {
type: "tween",
ease: [0.4, 0.0, 0.2, 1],
duration: 1.2
};
function nextTimeout() {
clearTimeout(timeout)
if (mouseOver) return
timeout = setTimeout(() => {
slider.next()
}, 4000)
}
slider.on("created", () => {
slider.container.addEventListener("mouseover", () => {
mouseOver = true
clearNextTimeout()
})
slider.container.addEventListener("mouseout", () => {
mouseOver = false
nextTimeout()
})
nextTimeout()
})
slider.on("dragStarted", clearNextTimeout)
slider.on("animationEnded", nextTimeout)
slider.on("updated", nextTimeout)
}
export default function Banner() {
const [activeIndex, setActiveIndex] = useState(0);
const [isAnimating, setIsAnimating] = useState(false);
const [sliderLoaded, setSliderLoaded] = useState(false)
const handleSlideChange = (swiper) => {
setIsAnimating(true);
setActiveIndex(swiper.realIndex || 0);
setTimeout(() => setIsAnimating(false), 1200);
};
const [sliderRef] = useKeenSlider(
{
loop: true,
renderMode: "performance",
slides: { perView: 1, spacing: 0 },
duration: 1000, // increase for smoother transition
easing: (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2, // smooth cubic easing
created() {
setSliderLoaded(true)
},
},
[AutoplaySlider]
)
const slides = [
{
id: 0,
bg: "/assets/images/banner/desktopBanner/banner-4.png",
upper: "Begin your",
title: "Recovery",
desc: "• Rehab • Strength Training • Personalized Care",
btn: { text: "Visit Our Location", link: "/contact" },
align: "start",
},
{
id: 1,
bg: "/assets/images/banner/desktopBanner/banner-1.png",
upper: "Build Your Strength &",
title: "Endurance",
desc: "• Physiotherapy • Sports Therapy • Injury Prevention",
btn: { text: "Book Your Appointment", link: "tel:+647-722-3434" },
align: "center",
},
{
id: 2,
bg: "/assets/images/banner/desktopBanner/banner-3.webp",
upper: "Regain Your Strength",
title: "Heal",
desc: "• Pain Relief • Mobility • Wellness",
btn: { text: "Schedule a Massage", link: "/contact" },
align: "start",
},
{
id: 3,
bg: "/assets/images/banner/desktopBanner/banner-2.png",
upper: "Build your Core",
title: "Performance",
desc: "• Pain Relief • Active Care • Long-Term Result",
btn: { text: "Explore Our Service", link: "/etobicoke-treatment-service" },
align: "space-evenly",
},
]
return (
<section className="banner-style-two p_relative">
<Swiper {...swiperOptions}
className="banner-carousel owl-theme owl-carousel owl-nav-none owl-dots-none"
onSwiper={(swiper) => setActiveIndex(swiper.realIndex || 0)}
onSlideChange={handleSlideChange}
<div
ref={sliderRef}
className="keen-slider"
style={{ opacity: sliderLoaded ? 1 : 0, transition: "opacity 0.5s ease" }}
>
<SwiperSlide>
<AnimatePresence mode="wait">
{activeIndex === 0 && (
<motion.div key="slide-3"
className="slide-item banner-slide"
variants={revealVariants}
initial="initial" animate="animate" exit="exit" transition={transition}>
<div className="bg-layer"
style={{ backgroundImage: 'url(/assets/images/banner/desktopBanner/banner-4.png)' }}>
</div>
<div className="auto-container" style={{ height: "600px", display: "flex", alignItems: "end", justifyContent: "start", textAlign: "start" }}>
<div className="content-box custom-content-box">
<span className="upper-text mb-2">Begin your</span>
<h2 style={{ color: "#bc0000" }}>Recovery</h2>
<p className='text-white'> Rehab Strength Training Personalized Care </p>
<div className="btn-box mt-3">
<Link href="/contact" className="theme-btn btn-one">
<span>Vist Our Location</span>
</Link>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</SwiperSlide>
<SwiperSlide>
<AnimatePresence mode="wait">
{activeIndex === 1 && (
<motion.div key="slide-0"
className="slide-item banner-slide"
//variants={variants.rightToLeft}
variants={revealVariants}
initial="initial" animate="animate" exit="exit" transition={transition}>
<div className="bg-layer bg-slide-0"
style={{ backgroundImage: 'url(/assets/images/banner/desktopBanner/banner-1.png)' }}>
</div>
<div className="auto-container" style={{ height: "600px", display: "flex", alignItems: "end", justifyContent: "end", textAlign: "center" }}>
<div className="content-box custom-content-box">
<span className="upper-text mb-2 ">Build Your Strength & </span>
<h2 style={{ color: "#bc0000" }}>Endurance</h2>
<p className=' text-white'> Physiotherapy Sports Therapy Injury Prevention</p>
<div className="btn-box mt-3">
<Link href="tel:+647-722-3434" className="theme-btn btn-one">
<span>Book Your Appointment</span>
</Link>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</SwiperSlide>
{/* ✅ existing 3rd slide remains as 3rd */}
<SwiperSlide>
<AnimatePresence mode="wait">
{activeIndex === 2 && (
<motion.div key="slide-2"
className="slide-item banner-slide"
//variants={variants.rightToLeft}
variants={revealVariants}
initial="initial" animate="animate" exit="exit" transition={transition}>
<div className="bg-layer"
style={{ backgroundImage: 'url(/assets/images/banner/desktopBanner/banner-3.webp)' }}>
</div>
<div className="auto-container" style={{ height: "600px", display: "flex", alignItems: "end", justifyContent: "start", textAlign: "start" }}>
<div className="content-box custom-content-box">
<span className="upper-text mb-2">Regain Your Strength</span>
<h2 style={{ color: "#bc0000" }}> Heal </h2>
<p className=' text-white'> Pain Relief mobility Wellness </p>
<div className="btn-box mt-3">
<Link href="/contact" className="theme-btn btn-one">
<span>Schedule a Massage</span>
</Link>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</SwiperSlide>
<SwiperSlide>
<AnimatePresence mode="wait">
{activeIndex === 3 && (
<motion.div key="slide-1"
className="slide-item banner-slide"
//variants={variants.rightToLeft}
variants={revealVariants}
initial="initial" animate="animate" exit="exit" transition={transition}>
<div className="bg-layer"
style={{ backgroundImage: 'url(/assets/images/banner/desktopBanner/banner-2.png)' }}>
</div>
<div className="auto-container" style={{ height: "600px", display: "flex", alignItems: "end", justifyContent: "center", textAlign: "center" }}>
<div className="content-box custom-content-box">
<span className="upper-text mb-3">Build your Core </span>
<h2 style={{ color: "#bc0000" }}>Performance</h2>
<p className=' text-white'> Pain Relief Active Care Long-Term Result</p>
<div className="btn-box mt-3">
<Link href="/etobicoke-treatment-service" className="theme-btn btn-one">
<span>Explore Our Service</span>
</Link>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</SwiperSlide>
</Swiper>
{slides.map((s) => (
<div
key={s.id}
className="keen-slider__slide"
style={{
minHeight: "600px",
width: "100%",
backgroundImage: `url(${s.bg})`,
backgroundSize: "cover",
backgroundPosition: "center",
display: "flex",
alignItems: "end",
justifyContent:
s.align === "start"
? "flex-start"
: s.align === "end"
? "flex-end"
: s.align === "center"
? "center"
: s.align === "space-between"
? "space-between"
: s.align === "space-evenly"
? "space-evenly"
: "center",
padding: "0 150px 40px",
}}
>
<div
className="content-box custom-content-box"
style={{
color: "#bc0000",
textAlign:
s.align === "space-between" || s.align === "space-evenly"
? "center"
: s.align,
padding: "450px 0px 220px 0px",
}}
>
<span className="upper-text mb-2" style={{ fontSize: "22px" }}>{s.upper}</span>
<h1
style={{
color: "#bc0000",
fontWeight: "bold",
fontSize: "64px",
}}
>
{s.title}
</h1>
<p style={{ color: "#fff" }}>{s.desc}</p>
<div className="btn-box mt-3">
<Link href={s.btn.link} className="theme-btn btn-one">
<span>{s.btn.text}</span>
</Link>
</div>
</div>
</div>
))}
</div>
</section>
);
}
)
}

View File

@ -1,220 +1,124 @@
'use client'
import React, { useState, useEffect } from 'react';
"use client";
import React, { useState } from "react";
import Link from "next/link";
import { Autoplay, Navigation, Pagination } from "swiper/modules";
import { Swiper, SwiperSlide } from "swiper/react";
import { motion, AnimatePresence } from "framer-motion";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
const swiperOptions = {
modules: [Autoplay, Pagination, Navigation],
slidesPerView: 1,
spaceBetween: 0,
autoplay: {
delay: 10000,
disableOnInteraction: false,
},
loop: true,
navigation: {
nextEl: '.h1n',
prevEl: '.h1p',
},
pagination: {
el: '.swiper-pagination',
clickable: true,
},
};
const variants = {
topToBottom: { initial: { y: '-100vh', opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: '100vh', opacity: 0 } },
bottomToTop: { initial: { y: '100vh', opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: '-100vh', opacity: 0 } },
leftToRight: { initial: { x: '-100vw', opacity: 0 }, animate: { x: 0, opacity: 1 }, exit: { x: '100vw', opacity: 0 } },
rightToLeft: { initial: { x: '100vw', opacity: 0 }, animate: { x: 0, opacity: 1 }, exit: { x: '-100vw', opacity: 0 } },
};
const transition = { type: "tween", ease: [0.4, 0.0, 0.2, 1], duration: 1.2 };
const revealVariants = {
hidden: {
scaleX: 0,
opacity: 0,
originX: 0, // same as transform-origin: 0% 50%
},
visible: {
scaleX: 1,
opacity: 1,
originX: 0,
transition: {
duration: 0.8,
ease: "easeInOut"
}
},
exit: {
scaleX: 0,
opacity: 0,
originX: 0,
transition: {
duration: 0.6,
ease: "easeInOut"
}
}
};
import { useKeenSlider } from "keen-slider/react";
import "keen-slider/keen-slider.min.css";
export default function MobileBanner() {
const [activeIndex, setActiveIndex] = useState(0);
const [isMobile, setIsMobile] = useState(false);
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
React.useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
handleResize();
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
const slides = [
{
id: 0,
variant: 'revealVariants',
bgImage: '/assets/images/banner/mobile-banner/4.webp',
upperText: 'Begin your ',
title: ' Recovery',
// titleSpan: 'Wellness',
// titleEnd: 'Care',
// subtitle: 'Waterfront Physio and Rehab Services.',
description: 'Discover holistic physiotherapy and rehab services designed to restore balance, ease pain, and support long-term recovery.',
buttonText: 'Book Your Appointment',
buttonLink: '/contact',
// contentStyle: 'with-background'
},
{
id: 1,
variant: 'revealVariants',
bgImage: '/assets/images/banner/mobile-banner/1.webp',
upperText: 'Build Your Strength & ',
title: 'Endurance',
// titleSpan: 'health',
// titleEnd: 'Forever',
subtitle: 'Expert Physiotherapy in Mississauga for You.',
description: 'Our expert physiotherapists help you restore movement, reduce pain, and live healthier with personalized care in Mississauga.',
buttonText: 'Book Your Appointment',
buttonLink: 'tel:+647-722-3434',
contentStyle: 'mobile-style'
},
const [sliderRef] = useKeenSlider({
loop: true,
autoplay: {
delay: 4000,
pauseOnMouseEnter: true,
stopOnInteraction: false,
},
slides: { perView: 1, spacing: 0 },
});
{
id: 2,
variant: 'revealVariants',
bgImage: '/assets/images/banner/mobile-banner/3.webp',
upperText: 'Regain your Flexiblity & ',
title: 'Balance',
// titleSpan: 'Physio',
// titleEnd: 'Experts',
// subtitle: 'Physiotherapy Etobicoke & Rehab Care.',
description: 'Comprehensive physiotherapy and rehab services designed to restore your strength, mobility and long-term wellness.',
buttonText: 'Explore Our Service',
buttonLink: '/etobicoke-treatment-service',
// contentStyle: 'with-background'
},
{
id: 3,
variant: 'revealVariants',
bgImage: '/assets/images/banner/mobile-banner/2.webp',
upperText: 'Build your Core ',
title: 'Performance',
// titleSpan: 'Massage',
// titleEnd: 'Therapy',
// subtitle: 'Expert Hand Massage Techniques for Relief',
description: 'Experience soothing massage techniques that release tension, promote circulation, and support your overall wellness.',
buttonText: 'Schedule a Massage',
buttonLink: '/contact',
// contentStyle: 'with-background'
},
const slides = [
{
id: 0,
bgImage: "/assets/images/banner/mobile-banner/4.webp",
upperText: "Begin your ",
title: "Recovery",
description:
"Discover holistic physiotherapy and rehab services designed to restore balance, ease pain, and support long-term recovery.",
buttonText: "Book Your Appointment",
buttonLink: "/contact",
},
{
id: 1,
bgImage: "/assets/images/banner/mobile-banner/1.webp",
upperText: "Build Your Strength & ",
title: "Endurance",
subtitle: "Expert Physiotherapy in Mississauga for You.",
description:
"Our expert physiotherapists help you restore movement, reduce pain, and live healthier with personalized care in Mississauga.",
buttonText: "Book Your Appointment",
buttonLink: "tel:+647-722-3434",
},
{
id: 2,
bgImage: "/assets/images/banner/mobile-banner/3.webp",
upperText: "Regain your Flexibility & ",
title: "Balance",
description:
"Comprehensive physiotherapy and rehab services designed to restore your strength, mobility and long-term wellness.",
buttonText: "Explore Our Service",
buttonLink: "/etobicoke-treatment-service",
},
{
id: 3,
bgImage: "/assets/images/banner/mobile-banner/2.webp",
upperText: "Build your Core ",
title: "Performance",
description:
"Experience soothing massage techniques that release tension, promote circulation, and support your overall wellness.",
buttonText: "Schedule a Massage",
buttonLink: "/contact",
},
];
];
if (!isMobile) return null;
if (!isMobile) return null;
return (
<section
className="banner-style-two p_relative"
style={{ minHeight: '100vh', position: 'relative' }}
>
<Swiper
{...swiperOptions}
className="banner-carousel"
onSwiper={(swiper) => setActiveIndex(swiper.realIndex || 0)}
onSlideChange={(swiper) => setActiveIndex(swiper.realIndex || 0)}
return (
<section
className="banner-style-two"
style={{ minHeight: "100vh", position: "relative" }}
>
<div ref={sliderRef} className="keen-slider">
{slides.map((slide) => (
<div
key={slide.id}
className="keen-slider__slide"
style={{
minHeight: "100vh",
position: "relative",
backgroundImage: `url(${slide.bgImage})`,
backgroundSize: "cover",
backgroundPosition: "center",
}}
>
<div
className="auto-container"
style={{
position: "relative",
zIndex: 1,
minHeight: "100vh",
display: "flex",
justifyContent: "center",
alignItems: "center",
paddingTop: "200px",
color: "#fff",
textAlign: "center",
}}
>
{slides.map((slide, index) => (
<SwiperSlide key={slide.id}>
<AnimatePresence mode="wait">
{activeIndex === index && (
<motion.div
key={`slide-${index}`}
className="slide-item"
style={{ minHeight: '100vh', position: 'relative' }}
variants={variants[slide.variant]}
initial="initial"
animate="animate"
exit="exit"
transition={transition}
>
{/* full-height background */}
<div
className="bg-layer"
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundImage: `url(${slide.bgImage})`,
backgroundSize: 'cover',
backgroundPosition: 'center'
}}
/>
{/* centered content */}
<div
className="auto-container"
style={{
position: 'relative',
zIndex: 1,
minHeight: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'end',
paddingBottom: "20px"
}}
>
{!slide.hideContent && (
<div
className={`content-box custom-content-box ${slide.contentStyle || ''}`}
>
<span className="upper-text mb-2 ">{slide.upperText}</span>
<h2 style={{ fontSize: "32px !important", lineHeight: "42px" }}>
{slide.title} {slide.titleSpan} {slide.titleEnd}
</h2>
<p>{slide.subtitle}</p>
<p>{slide.description}</p>
<div className="btn-box mt-3">
<Link href={slide.buttonLink} className="theme-btn btn-one-new">
<span>{slide.buttonText}</span>
</Link>
</div>
</div>
)}
</div>
</motion.div>
)}
</AnimatePresence>
</SwiperSlide>
))}
</Swiper>
</section>
);
};
<div className="content-box custom-content-box">
<span className="upper-text mb-2">{slide.upperText}</span>
<h2 style={{ fontSize: "32px", lineHeight: "42px", color:"#bc0000", fontWeight:"bold" }}>
{slide.title}
</h2>
{/* {slide.subtitle && <p>{slide.subtitle}</p>} */}
{/* <p>{slide.description}</p> */}
<div className="btn-box mt-3">
<Link href={slide.buttonLink} className="theme-btn btn-one-new">
<span>{slide.buttonText}</span>
</Link>
</div>
</div>
</div>
</div>
))}
</div>
</section>
);
}

7
package-lock.json generated
View File

@ -17,6 +17,7 @@
"imagemin-optipng": "^8.0.0",
"imagemin-webp": "^8.0.0",
"isotope-layout": "^3.0.6",
"keen-slider": "^6.8.6",
"lightgallery": "^2.7.2",
"next": "^14.0.4-canary.36",
"react": "18.2.0",
@ -3704,6 +3705,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/keen-slider": {
"version": "6.8.6",
"resolved": "https://registry.npmjs.org/keen-slider/-/keen-slider-6.8.6.tgz",
"integrity": "sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w==",
"license": "MIT"
},
"node_modules/keyv": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",

View File

@ -22,6 +22,7 @@
"imagemin-optipng": "^8.0.0",
"imagemin-webp": "^8.0.0",
"isotope-layout": "^3.0.6",
"keen-slider": "^6.8.6",
"lightgallery": "^2.7.2",
"next": "^14.0.4-canary.36",
"react": "18.2.0",