【前端特效】瀑布流

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>瀑布流</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            background: #f8f9fa;
            font-family: 'Segoe UI', sans-serif;
        }

        .container {
            position: relative;
            margin: 20px auto;
            max-width: 1200px;
        }

        .card {
            position: absolute;
            width: 280px;
            background: white;
            border-radius: 15px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.06);
            transition: transform 0.3s ease, opacity 0.3s ease;
            opacity: 0;
        }

        .card.visible {
            opacity: 1;
        }

        .card-content {
            padding: 25px;
        }

        h3 {
            color: rgba(0,0,0,0.8);
            margin-bottom: 12px;
            font-size: 1.3em;
        }

        p {
            color: rgba(0,0,0,0.6);
            line-height: 1.6;
            font-size: 0.95em;
        }

        .bg1 { background: #f0f8ff }
        .bg2 { background: #f5f0ff }
        .bg3 { background: #f0fff4 }
        .bg4 { background: #fff8f0 }
        .bg5 { background: #fff0f5 }
    </style>
</head>
<body>
    <div class="container" id="container"></div>

    <script>
        const cardsData = [
            { title: '晨曦微光', content: '黎明前的天空泛起鱼肚白,晨露在草叶上闪烁' },
            { title: '云海幻境', content: '群山之巅的云浪翻滚,如入蓬莱仙境。云层如轻纱般流动,朝阳为云海镶上金边' },
            { title: '林间小径', content: '斑驳树影下的碎石路通向未知的秘境,青苔悄悄爬上古老石阶' },
            { title: '琉璃湖畔', content: '风过无痕的水面倒映着天空的蔚蓝,几只白鹭掠过泛起涟漪' },
            { title: '青瓷记忆', content: '釉色流淌间凝固了千年的时光,冰裂纹中藏着岁月的密码' },
            { title: '花间絮语', content: '花瓣随风起舞诉说春日的私语,花香在暖阳中缓缓流淌' },
            { title: '茶韵悠长', content: '氤氲香气中品味时光的沉淀,茶汤在杯中画出金色漩涡' },
            { title: '纸上流年', content: '墨迹晕染开泛黄的书卷记忆,毛笔尖悬停着未尽的思绪' },
            { title: '雨巷琴声', content: '潮湿石板路上飘散的音符回响,油纸伞划过雨幕的弧度' },
            { title: '远山含黛', content: '水墨画般的轮廓在天际若隐若现,雾霭为群山蒙上薄纱' }
        ];

        class Waterfall {
            constructor(container, colWidth = 280, gap = 20) {
                this.container = container;
                this.colWidth = colWidth;
                this.gap = gap;
                this.cols = [];
                this.init();
                window.addEventListener('resize', () => this.debouncedLayout());
            }

            init() {
                this.createCols();
                this.debouncedLayout = this.debounce(() => this.layout());
            }

            createCols() {
                const containerWidth = this.container.offsetWidth;
                const colCount = Math.floor((containerWidth + this.gap) / (this.colWidth + this.gap));
                this.cols = Array(colCount).fill(0);
            }

            layout() {
                this.createCols();
                const cards = Array.from(this.container.children);
                const positions = [];

                cards.forEach(card => {
                    const minHeight = Math.min(...this.cols);
                    const colIndex = this.cols.indexOf(minHeight);
                    
                    const x = colIndex * (this.colWidth + this.gap);
                    const y = minHeight + (minHeight > 0 ? this.gap : 0);
                    
                    positions.push({x, y, height: card.offsetHeight});
                    this.cols[colIndex] = y + card.offsetHeight;
                });

                cards.forEach((card, i) => {
                    card.style.transform = `translate(${positions[i].x}px, ${positions[i].y}px)`;
                    card.classList.add('visible');
                });

                this.container.style.height = Math.max(...this.cols) + 'px';
            }

            debounce(fn, delay = 100) {
                let timer;
                return () => {
                    clearTimeout(timer);
                    timer = setTimeout(fn, delay);
                };
            }
        }

        const container = document.getElementById('container');
        const waterfall = new Waterfall(container);

        cardsData.forEach((item, index) => {
            const card = document.createElement('div');
            card.className = `card bg${Math.floor(Math.random() * 5) + 1}`;

            const randomHeight = 150 + Math.random() * 150;
            card.style.height = `${randomHeight}px`;
            
            const content = `
                <div class="card-content">
                    <h3>${item.title}</h3>
                    <p>${item.content}</p>
                </div>
            `;
            
            card.innerHTML = content;
            container.appendChild(card);
        });

        setTimeout(() => waterfall.layout(), 50);

        window.addEventListener('scroll', () => {
            if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 100) {
                setTimeout(() => waterfall.layout(), 50);
            }
        });
    </script>
</body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值