This commit is contained in:
Marks 2023-11-17 01:11:16 +03:00
parent 5ee997ae3c
commit f8e7549d4f
6 changed files with 132 additions and 27 deletions

View File

@ -6,25 +6,15 @@
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="Нужна помощь с оплатой билетов, гостиниц, арендой транспорта (яхта, частный самолет) или других сервисов по всему миру? SanxPay консьерж-сервис готов прийти на помощь!"
/>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Raleway&display=swap" rel="stylesheet">
<title>Lux Service</title>
<title>SanxPay · консьерж-сервис</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -1,9 +1,11 @@
import AboutSection from "./Components/AboutSection";
import NavMenu from "./Components/NavMenu";
function App() {
return (
<div className="h-[10000px] bg-black text-white font-main">
<NavMenu></NavMenu>
<div className="bg-black h-[2000px] text-white font-main">
<NavMenu />
<AboutSection />
</div>
);
}

View File

@ -0,0 +1,29 @@
import React, { useState } from 'react';
import {motion, useScroll, useMotionValueEvent, useAnimationControls} from "framer-motion"
import yachtImg from "../Images/yacht.jpg"
const AboutSection = () => {
return (
<>
<div className='absolute inset-0'>
<img src={yachtImg} alt="yacht" className='w-full h-full object-cover brightness-[0.2] contrast-[1.1]' />
</div>
<div className='absolute inset-0 flex justify-center'>
<div className='flex flex-col justify-end w-full h-full max-w-[1920px] gap-8 p-4 pb-[40%] md:gap-16 md:p-12 lg:gap-16 lg:p-12 2xl:gap-28 2xl:p-20'>
<div className='flex items-center md:h-[230px] lg:h-[280px]'>
<h1 className='text-4xl md:text-6xl lg:text-7xl xl:text-8xl 2xl:text-9xl font-bold'>
Консьерж-сервис для VIP клиентов
</h1>
</div>
<div className='flex text-right self-end justify-end items-center max-w-[300px] lg:max-w-[400px]'>
<p className='text-xl md:text-2xl lg:text-3xl'>
Добро пожаловать в мир непревзойденной роскоши и удобства.
</p>
</div>
</div>
</div>
</>
);
}
export default AboutSection;

View File

@ -1,42 +1,108 @@
import React, { useState } from 'react';
import {motion, useScroll, useMotionValueEvent, useTransform} from "framer-motion"
import {motion, useScroll, useMotionValueEvent, useAnimationControls} from "framer-motion"
const hamburger01Variants = {
open: { d: 'M3.06061 2.99999L21.0606 21' },
closed: { d: 'M0 9.5L24 9.5' },
};
const hamburger02Variants = {
open: { d: 'M3.00006 21.0607L21 3.06064' },
moving: { d: 'M0 14.5L24 14.5' },
closed: { d: 'M0 14.5L15 14.5' },
};
const hmenuVariants = {
open: { translateY: "0rem", opacity: 1},
closed: {translateY: "-4rem", opacity: 0.3},
};
const NavMenu = () => {
const { scrollYProgress } = useScroll();
const menu_offset = useTransform(scrollYProgress, [0,0.1], ['50%', '100%']);
const menu_offset_l = useTransform(scrollYProgress, [0,0.1], ['-50%', '-100%']);
// const menu_offset = useTransform(scrollYProgress, [0,0.1], ['50%', '100%']);
// const menu_offset_l = useTransform(scrollYProgress, [0,0.1], ['-50%', '-100%']);
const [scrollPosition, setScrollPosition] = useState(0.0);
const animControls = useAnimationControls();
useMotionValueEvent(scrollYProgress, "change", (latest) => {
setScrollPosition(latest);
if(latest > 0.001)
{
animControls.start({left: "100%", translateX: "-100%", transition: {duration: 0.1}});
}
else
{
animControls.stop();
animControls.start({left: "50%", translateX: "-50%", transition: {duration: 0.1}});
}
})
const [hmenustate, setHMenuState] = useState('closed');
const onClick = () => {
setHMenuState('moving');
setTimeout(() => {
setHMenuState(hmenustate === 'closed' ? 'open' : 'closed');
}, 200);
};
return (
<motion.div className={'sticky top-0 left-0 right-0 w-full px-12 h-24 transition-all duration-100 bg-transparent flex items-center text-xl select-none '
<>
<motion.div className={'hidden lg:flex sticky top-0 left-0 right-0 w-full px-12 h-24 transition-all duration-100 bg-transparent z-10 items-center text-xl select-none '
+ (scrollPosition > 0.0 ? "justify-end":"justify-center")}
// initial={{y:100, opacity: 0.1}}
// animate={{y: 0, opacity:1.0}}
// transition={{type: "tween", stiffness:300}}
>
<div className='absolute top-0 left-12'>
<p className='text-2xl font-bold translate-y-[100%]'>COMPANY NAME</p>
<div className='absolute top-[50%] left-12 translate-y-[-50%]'>
<p className='text-3xl font-bold '>SanxPay</p>
</div>
<div className='absolute top-0 left-12 right-12 bottom-0'>
<div className='relative w-full h-full'>
<motion.div className='absolute flex gap-8 justify-center items-center'
<motion.nav className='absolute flex gap-8 justify-center items-center'
transition={{type: "tween", duration: 0.5}}
initial={{left: "50%", translateX: "-50%", top: "50%", translateY: "-50%"}}
style={{left: menu_offset, translateX: menu_offset_l}}
animate={animControls}
>
<a href="##" className='hover:opacity-50 transition-all duration-100'>About</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Services</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Steps</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Contact</a>
</motion.div>
<a href="##" className='hover:opacity-50 transition-all duration-100 w-[55px]'>О нас</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Сервисы</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Шаги</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Контакты</a>
</motion.nav>
</div>
</div>
</motion.div>
<motion.div className={'flex lg:hidden bg-black bg-opacity-30 justify-between sticky top-0 left-0 right-0 w-full px-12 h-16 transition-all duration-100 z-10 items-center text-xl select-none'}>
<p className='text-3xl font-bold '>SanxPay</p>
<div id='menu-icon'>
<button onClick={onClick}>
<svg width='24' height='24' viewBox='0 0 24 24'>
<motion.path
stroke='#FFFFFF'
animate={hmenustate}
variants={hamburger01Variants}
/>
<motion.path
stroke='#FFFFFF'
animate={hmenustate}
variants={hamburger02Variants}
/>
</svg>
</button>
</div>
<div className='absolute left-0 right-0 w-full translate-y-full h-16 overflow-hidden'>
<motion.nav className='absolute bg-black bg-opacity-30 flex items-center justify-center gap-4 h-16 w-full'
animate={hmenustate}
variants={hmenuVariants}
transition={{type: "tween", duration: 0.3}}>
<a href="##" className='hover:opacity-50 transition-all duration-100 w-[55px]'>О нас</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Сервисы</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Шаги</a>
<a href="##" className='hover:opacity-50 transition-all duration-100'>Контакты</a>
</motion.nav>
</div>
</motion.div>
</>
);
}

BIN
src/Images/yacht.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

View File

@ -0,0 +1,18 @@
import React from "react";
function HamburgerSVG0() {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="none"
viewBox="0 0 24 24"
>
<path stroke="#FFF" d="M0 9.5L24 9.5"></path>
<path stroke="#FFF" d="M0 14.5L15 14.5"></path>
</svg>
);
}
export default Icon;