You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为通知框添加左滑显示删除按钮的Swipe Effect

如何实现通知栏左滑显示删除按钮的交互效果

需求:为每条通知栏添加左滑交互,左滑后在通知末尾显示删除按钮,效果类似苹果短信的左滑删除功能,预期效果如下:

左滑删除预期效果

原HTML结构如下:

<div class="spacer">
    <p class="header-text">Notifications</p>
    <div class="grey-box">
        <p class="grey-box-text">Today</p>
    </div>

    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Notification Name</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit
                ut aliquam, purus sit amet luctus venenatis, lectus
                magna fringilla urna.</p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>

    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Link To Our Survey</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur: <br>
            <a href="www.survey-generator.com/293/39djd" class="notification-link">
            www.survey-generator.com/293/39djd</a></p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>

    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Notification Name</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit
                ut aliquam, purus sit amet luctus venenatis, lectus
                magna fringilla urna.</p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>

    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Claim Status Update</p>
            <p class="notification-content">Your claim #230291 has been moved to “Under Review”
            Status... to view more go to Claims Tab.</p>
            <p class="notification-time-label">3h ago</p>
        </div>
    </div>

    <div class="grey-box">
        <p class="grey-box-text">Previous</p>
    </div>
    
    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Notification Name</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit
                ut aliquam, purus sit amet luctus venenatis, lectus
                magna fringilla urna.</p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>
    
    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Link To Our Survey</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur: <br>
                <a href="www.survey-generator.com/293/39djd" class="notification-link">
                    www.survey-generator.com/293/39djd</a>
            </p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>
    
    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Notification Name</p>
            <p class="notification-content">Lorem ipsum dolor sit amet, consectetur adipiscing elit
                ut aliquam, purus sit amet luctus venenatis, lectus
                magna fringilla urna.</p>
            <p class="notification-time-label">2h ago</p>
        </div>
    </div>
    
    <div class="notification-box">
        <div class="notification-icon">
            <i class="far fa-calendar icon"></i>
        </div>
        <div class="notification-content-box">
            <p class="notification-title">Claim Status Update</p>
            <p class="notification-content">Your claim #230291 has been moved to “Under Review”
                Status... to view more go to Claims Tab.</p>
            <p class="notification-time-label">3h ago</p>
        </div>
    </div>
</div>

实现方案

1. 修改HTML结构

给每个notification-box包裹一层滑动容器,同时添加删除按钮:

<!-- 替换原单个notification-box为以下结构 -->
<div class="swipe-container">
    <div class="notification-box">
        <!-- 原通知内容保持不变 -->
    </div>
    <button class="delete-btn">删除</button>
</div>

2. 添加CSS样式

设置滑动容器布局、过渡动画及删除按钮样式:

.swipe-container {
    position: relative;
    display: flex;
    overflow: hidden;
    margin-bottom: 12px;
}

.notification-box {
    flex: 1;
    display: flex;
    align-items: flex-start;
    padding: 15px;
    background: #fff;
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    cursor: grab;
}

.delete-btn {
    width: 85px;
    background: #ff3b30;
    color: #fff;
    border: none;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    font-size: 14px;
}

.notification-box.dragging {
    cursor: grabbing;
}

3. 编写JavaScript交互逻辑

监听鼠标/触摸事件,实现滑动判断、位移控制及删除功能:

const swipeContainers = document.querySelectorAll('.swipe-container');

swipeContainers.forEach(container => {
    const notificationBox = container.querySelector('.notification-box');
    const deleteBtn = container.querySelector('.delete-btn');
    let startX = 0;
    let currentX = 0;
    let isDragging = false;
    const deleteBtnWidth = deleteBtn.offsetWidth;

    // 鼠标事件绑定
    notificationBox.addEventListener('mousedown', startDrag);
    document.addEventListener('mousemove', drag);
    document.addEventListener('mouseup', endDrag);

    // 触摸事件绑定
    notificationBox.addEventListener('touchstart', startDrag);
    document.addEventListener('touchmove', drag);
    document.addEventListener('touchend', endDrag);

    function startDrag(e) {
        isDragging = true;
        notificationBox.classList.add('dragging');
        // 兼容鼠标和触摸事件的起始位置获取
        startX = e.type === 'touchstart' ? e.touches[0].clientX : e.clientX;
    }

    function drag(e) {
        if (!isDragging) return;
        e.preventDefault();
        currentX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
        const diffX = startX - currentX;

        // 限制仅向左滑动,且位移不超过删除按钮宽度
        if (diffX > 0 && diffX <= deleteBtnWidth) {
            notificationBox.style.transform = `translateX(-${diffX}px)`;
        } else if (diffX > deleteBtnWidth) {
            notificationBox.style.transform = `translateX(-${deleteBtnWidth}px)`;
        }
    }

    function endDrag() {
        if (!isDragging) return;
        isDragging = false;
        notificationBox.classList.remove('dragging');
        const diffX = startX - currentX;

        // 滑动超过一半宽度时固定展开,否则回弹复位
        if (diffX > deleteBtnWidth / 2) {
            notificationBox.style.transform = `translateX(-${deleteBtnWidth}px)`;
        } else {
            notificationBox.style.transform = 'translateX(0)';
        }

        // 删除按钮点击事件
        deleteBtn.addEventListener('click', () => {
            container.style.opacity = '0';
            container.style.transform = 'translateX(-100%)';
            container.style.transition = 'all 0.3s ease';
            setTimeout(() => container.remove(), 300);
        });
    }
});

效果说明

  • 同时支持鼠标拖拽和触摸滑动两种操作方式
  • 左滑距离超过删除按钮一半宽度时,自动固定显示删除按钮;否则平滑回弹复位
  • 点击删除按钮后,通知条会向左滑出并移除DOM

内容的提问来源于stack exchange,提问作者hopetocodebetter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 14:21:31