js 拖动表格框线调整列宽

本文介绍了一种使用原生JavaScript实现鼠标拖拽调整HTML表格列宽的方法。通过监听鼠标事件,动态调整<colgroup>标签内列的宽度比例,支持列的插入和删除操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:获取鼠标在框线位置,调整表格的“<colgroup>”标签里的列宽

(HTML <colgroup> 标签参看:HTML <colgroup> 标签 | 菜鸟教程 (runoob.com)

let aflag = false
let mouseStyleFlag = true
let collsNum = 0  // 列数
let colWidth = 0  // 宽度
let pixelOne = 0  // 单个像素
let width1 = 0   // 要调整的列1
let width2 = 0   // 要调整的列2
let coord = 0   // 初始坐标
let colls = null // 列宽

// tableNode : 表示表格节点
tableNode.addEventListener('mousedown', (e) => {
        
    if (e.button == 0) {
        // 获取表格中的单元格的id分布
        let list = downTable(e.target)
        // 行转列
        let newArray = list[0].map(function (col, i) {
            return list.map(function (row) {
                return row[i]
            })
        })
        // 获取单元格所在的列
        collsNum = getCellsTrain(e.target, newArray)

        colWidth = e.target.offsetWidth

        let table =  getTable(e.target)
        colls = table.getElementsByTagName('colgroup')[0].getElementsByTagName('col')  // 列
        coord = e.screenX

        // 框线左侧的列宽
        width1 = parseInt(colls[collsNum-1].getAttribute('width'))/100
        // 框线右侧的列宽
        width2 = parseInt(colls[collsNum].getAttribute('width'))/100  
            
        pixelOne = width2 / colWidth

        aflag = true
        }

    }, false)

    tableNode.addEventListener('mousemove', (e) => {
        shiftIn = true

        if (e.offsetX<2) {
            // 光标在框线上修改光标的形状
            e.target.style.cursor= "e-resize"

        }else if (!aflag) {
           
            e.target.style.cursor= "default"

        }
        // 鼠标按下
        if (aflag) {
            // 鼠标所在的坐标
            let x = e.screenX
            let px = (Math.abs(coord - x)) * pixelOne
            // 框线左侧的列宽
            let width12 = parseInt(colls[collsNum-1].getAttribute('width'))/100
            // 框线右侧的列宽
            let width22 = parseInt(colls[collsNum].getAttribute('width'))/100  
            
            if (x > coord && width22 > 0.05) {

                colls[collsNum-1].setAttribute('width', `${(width1 + px)*100}%`)
                colls[collsNum].setAttribute('width', `${(width2 - px)*100}%`)
                
            }else if (x < coord && width12 > 0.05){

                colls[collsNum-1].setAttribute('width', `${(width1 - px)*100}%`)
                colls[collsNum].setAttribute('width', `${(width2 + px)*100}%`)
            }
            
        }

    }, false)


 tableNode.addEventListener('mouseup', () => {
        console.log("鼠标松开");
        
        aflag = false
        collsNum = 0  // 列数
        colWidth = 0  // 宽度
        pixelOne = 0  // 单个像素
        width1 = 0   // 要调整的列1
        width2 = 0   // 要调整的列2
        coord = 0   // 初始坐标
        colls = null // 列宽
        mouseStyleFlag = true
       
    }, false)

downTable() : 方法

/**
 * 获取表格的id数组分布
 * @param {鼠标所在节点} node 
 * @returns 
 */
export const downTable = (node) => {

    if (!node) {
        return 
    }
    // 获取表格
    let table =  getTable(node)
    
    return getTbList(table)
}


/**
 * 获取光标所在的表格
 * @param {光标所在的节点} node 
 */
export const getTable = (node) => {
    if (!node) {
        return null
    }
    if (node.nodeName.toLowerCase() == 'table') {
        return node
    }
    return getTable(node.parentNode)
}



/**
 * 获取单元格id
 * @param {表格节点} curTable 
 */
export const getTbList = (curTable) => {
    if (!curTable) {
        return
    }
    const rowLength = curTable.rows.length 
    const colLength = getCellLength(curTable)
    // let arr = new Array(colLength).fill('undefined');
    // list = new Array(rowLength).fill(arr);
    let list = new Array()
    for (let i = 0; i < rowLength; i++) {
        let arr = []
        for (let j = 0; j < colLength; j++) {
            arr.push('undefined')
        }
        list.push(arr)
    }

    for (let i = 0; i < rowLength; i++) {
        for (let j = 0; j < colLength; j++) {
            // 获取单元格
            let tdNode = curTable.rows[i].cells[j]
            if (!tdNode) {
                continue
            }
            for (let k = j; k < colLength; k++) {
                
                if (list[i][k] != 'undefined' ) {
                    continue
                }
                list[i][k] = tdNode.getAttribute('id')
                break
            }
            
            let rowspan = tdNode.rowSpan
            let colspan = tdNode.colSpan

            if (rowspan>1 && colspan>1) {
                for (let k = 0; k < rowspan; k++) {
                    for (let z = 0; z < colspan; z++) {
                        list[i+k][j+z] = tdNode.getAttribute('id')
                    }
                    
                }
            }else if(rowspan>1 || colspan>1){
                for (let k = 1; k < rowspan; k++) {
                    list[i+k][j] = tdNode.getAttribute('id')
                }
                for (let k = 1; k < colspan; k++) {
                    list[i][j+k] = tdNode.getAttribute('id')
                }
            }
        }
        
    }
    console.log("list: ");
    console.log(list);
    return list
}



/**
 * 获取表格的列数
 * @param {表格节点} curTable 
 * @returns 
 */
 export const getCellLength = (curTable) => {
    let rowNode = curTable.rows[0]
    let tdNodeList = rowNode.getElementsByTagName('td')
    if (tdNodeList.length == 0) {
        tdNodeList = rowNode.getElementsByTagName('th')
    }
    let length = 0
    for (let i = 0; i < tdNodeList.length; i++) {
        let rowspan = tdNodeList[i].getAttribute('colspan')
        if (rowspan) {
            length += Number(rowspan)
        } else {
            length++
        }
    }
    return length
}

插入列时,<colgroup> 中各列所占的比例修改


/**
 * 插入列,要插入的列的列宽和光标所在的列宽要一致
 * @param {光标所在的单元格} colls 
 * @param {表格节点} curTable
 * @param {true:向左插入, false:向右插入} isLeft 
 * @returns 
 */
export const addCell = (colls, curTable, isLeft) => {

    let colgroup = curTable.getElementsByTagName('colgroup')[0]
    let colgroupCol = colgroup.getElementsByTagName('col')  // 列
    // col 列数
    let proportion = parseInt(colgroupCol[col].getAttribute('width'))
    let temp = 100/(100+proportion)
    for (let i = 0; i < colgroupCol.length; i++) {
        let width = (parseInt(colgroupCol[i].getAttribute('width')))
        colgroupCol[i].setAttribute('width', `${temp * width}%`)
    }
    let colNode = document.createElement('col')
    colNode.setAttribute('width', `${temp * proportion}%`)
    if (isLeft) {
        colgroup.insertBefore(colNode, colgroupCol[col])
    }else{
        colgroup.insertBefore(colNode, colgroupCol[col].nextSibling)
    }
}

删除列时,<colgroup> 中各列所占的比例修改

// 删除列
export const delCell = (colls, curTable) => {

    let colgroup = curTable.getElementsByTagName('colgroup')[0]
    let colgroupCol = colgroup.getElementsByTagName('col')  // 列

    let proportion = parseInt(colgroupCol[col].getAttribute('width'))

    colgroup.removeChild(colgroupCol[col])

    let temp = 100/(100-proportion)

    for (let i = 0; i < colgroupCol.length; i++) {
        let width = (parseInt(colgroupCol[i].getAttribute('width')))
        colgroupCol[i].setAttribute('width', `${temp * width}%`)
    }
    
}

还可以参考:原生JS鼠标拖动修改表格的列宽_ling…的博客-CSDN博客_js设置表格列宽

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值