使用 HTML + JavaScript 实现可拖拽的任务看板系统

本文将介绍如何使用 HTML、CSS 和 JavaScript 创建一个交互式任务看板系统。该系统支持拖拽任务、添加新任务以及动态创建列,适用于任务管理和团队协作场景。

效果演示

image-20250530222903130

image-20250530222932759

image-20250530223009693

页面结构

HTML 部分主要包含三个默认的任务列(待办、进行中、已完成)和一个用于添加新列的按钮。

<div class="board" id="board">
    <div class="column" id="todo-column">
        <div class="column-title">待办</div>
        <div class="task-list" id="todo-list">
            <div class="task" draggable="true">设计登录页面UI</div>
            <div class="task" draggable="true">编写API接口文档</div>
            <div class="task" draggable="true">项目需求评审会议</div>
        </div>
        <div class="add-task" onclick="showAddTaskForm('todo-list')">添加任务</div>
    </div>
     <!-- 其他两个列 -->
    <div class="add-column" onclick="addNewColumn()">
        <div class="add-column-icon">+</div>
        <div>添加新列</div>
    </div>
</div>

核心功能实现

拖拽功能实现

完整的拖拽逻辑包括拖拽开始、结束、移动和放置操作。

首先,获取拖拽容器的元素用来绑定拖拽时间,定义一个变量用于保存当前正在被拖动的任务项

const board = document.getElementById('board');
let draggedTask = null;

拖拽开始

board.addEventListener('dragstart', function(e) {
   
    if (e.target.classList.contains('task')) {
   
        draggedTask = e.target;
        setTimeout(() => {
   
            e.target.classList.add('dragging');
        }, 0);
    }
});

拖拽过程

board.addEventListener('dragover', function(e) {
   
    e.preventDefault();
    const afterElement = getDragAfterElement(e.target.closest('.task-list'), e.clientY);
    const draggingTask = document.querySelector('.dragging');

    if (draggingTask && e.target.closest('.task-list')) {
   
        const list = e.target.closest('.task-list');
        if (afterElement) {
   
            list.insertBefore(draggingTask, afterElement);
        } else {
   
            list.appendChild(draggingTask);
        }
    }
});

拖拽结束

board.addEventListener('dragend', function(e) {
   
    if (e.target.classList.contains('task')) {
   
        e.target.classList.remove('dragging');
    }
});

获取拖拽后应该放置的位置

function getDragAfterElement(container, y) {
   
    const draggableElements = [...container.querySelectorAll('.task:not(.dragging)')];

    return draggableElements.reduce((closest, child) => {
   
        const box = child.getBoundingClientRect();
        const offset = y - box.top - box.height / 2;

        if (offset < 0 && offset > closest.offset) {
   
            return {
    offset: offset, element: child };
        } else {
   
            return closest;
        }
    }, {
    offset: Number.NEGATIVE_INFINITY }).element;
}
添加任务功能

当用户点击“添加任务”按钮时,会动态创建一个任务输入表单,替换原来的按钮,供用户输入新任务内容。

function showAddTaskForm(listId) {
   
    const list = document.getElementById(listId);
    const addButton = list.nextElementSibling;

    // 检查是否已存在表单
    if (list.querySelector('.task-form')) return;

    // 创建表单
    const form = document.createElement('div');
    form.className = 'task-form';
    form.innerHTML = `<input type="text" class="task-input" placeholder="输入任务内容..." autofocus>
        <div class="btn-group">
        <button class="btn btn-primary" onclick="addTask('${
     listId}')">
        <span>添加任务</span>
        </button>
        <button class="btn btn-outline" onclick="cancelAddTask('${
     listId}')"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值