唯品会主页上下二级运动效果 React + Ts实现

import React, { useRef, useState } from 'react'
import "./index.less"
export default function Pinduoduo() {
    const tit = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    const [selectIndex, setselectIndex] = useState<number>(0);
    const tranleft = useRef<HTMLDivElement>(null);
    const tranright = useRef<HTMLDivElement>(null);
    let disx = 0
    let x = 0
    const handelstart = (index: number) => {
        setselectIndex(index)
        tranleft.current!.scrollLeft = index > 2 ? (index - 2) * 51 : 0;
        tranright.current!.style.transition = ".3s all";
    }
    const Fnstart = (ev: React.TouchEvent) => {
        disx = ev.changedTouches[0].pageX - x;
        x = 0
        tranright.current!.style.transition = "none";
    }
    const fnmove = (ev: React.TouchEvent) => {
        x = ev.changedTouches[0].pageX - disx;
        tranright.current!.style.left = selectIndex * -100 + (x / 10) + 'vw';
    }
    const Fnend = () => {
        tranright.current!.style.transition = ".3s all";
        if (x > 150 && x > 0) setselectIndex(selectIndex - 1);
        if (x < -150 && x !== tit.length) setselectIndex(selectIndex + 1);
        tranleft.current!.scrollLeft = selectIndex > 2 ? (selectIndex - 2) * 51 : 0;
    }
    return (
        <div className='pinduoduo-box'>
            <div className="pinduoduo-header" ref={tranleft}>
                <div className="header-body">
                    {tit.map((item, index) => <div onTouchStart={() => handelstart(index)} key={item} className={selectIndex === index ? 'header-body-item actions' : 'header-body-item'}>
                        {item}
                    </div>)}
                    <div className="xian" style={{ left: selectIndex * (100 / 7) + "vw" }}>
                        <div></div>
                    </div>
                </div>
            </div>
            <div className="pinduoduo-content" onTouchMove={fnmove} onTouchEnd={Fnend} onTouchStart={Fnstart}>
                <div className="content-body" ref={tranright} style={{ left: -(selectIndex * 100) + 'vw' }}>
                    {tit.map((item, index) => <div key={item} className='content-item'>
                        {item}
                    </div>)}
                </div>
            </div>
        </div>
    )
}

index.less

.pinduoduo-box {
    width: 100vw;
    height: 100vh;
    overflow: hidden;

    .pinduoduo-header::-webkit-scrollbar {
        display: none;
    }

    .pinduoduo-header {
        width: 100vw;
        height: 100px;
        background-color: skyblue;
        overflow-x: scroll;
        scroll-behavior: smooth;

        .header-body {
            height: 100px;
            display: flex;
            width: calc((100vw / 7) * 12);
            position: relative;

            .header-body-item {
                width: calc(100vw / 7);
                height: 100px;
                line-height: 100px;
                font-size: 22px;
                text-align: center;
            }

            .xian {
                position: absolute;
                width: calc(100vw / 7);
                height: 2px;
                left: 0;
                bottom: 3px;
                padding-left: 15px;
                padding-right: 15px;
                box-sizing: border-box;
                transition: .3s all;

                >div {
                    width: 100%;
                    height: 2px;
                    background-color: darkmagenta;
                }
            }
        }
    }

    .pinduoduo-content {
        width: 100vw;
        height: 100vh;
        position: relative;

        .content-body {
            height: 100vh;
            display: flex;
            width: 1200vw;
            position: absolute;

            .content-item {
                width: 100vw;
                height: 100vh;
                font-size: 50px;
                text-align: center;
                line-height: 100vh;
                background-color: orange;

                &:nth-child(2n) {
                    background-color: pink;
                }
            }
        }

    }
}

.header-body-item.actions {
    color: red;
}

此功能仅适合单一展示在项目会有问题  ,如需在项目中实现,需要解决首尾能滑出问题 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值