美文网首页
univer实现字段拖拽

univer实现字段拖拽

作者: 超人s | 来源:发表于2024-03-27 17:19 被阅读0次

好久不写文章了,这篇是写给 Univer 群里的友友们看的。

1_1711617301 -big-original.gif

1. 获取canvas滚动偏移量

https://univer.work/zh-cn/guides/facade/general/#监听命令

通过监听命令api 可以知道canvas内滚动 会触发 命令sheet.operation.set-scroll

单独输出 命令sheet.operation.set-scroll 的params 可以获取到数据

代码:

      this.univerAPI.onBeforeCommandExecute((command) => {
        const { id, type, params } = command
          if (id === 'sheet.operation.set-scroll') {
            console.log('params', params)
            const { offsetX, offsetY, sheetId, sheetViewStartColumn, sheetViewStartRow, unitId } =
              params
            this.$emit('setScroll', {
              offsetX,
              offsetY,
              sheetId,
              sheetViewStartColumn,
              sheetViewStartRow,
              unitId
            })
          }
      })

image.png

{ offsetX, offsetY, sheetId, sheetViewStartColumn, sheetViewStartRow, unitId }

通过多次滚动,对数据的分析可以得出

这些数据为滚动后,左上角第一个格子的相关参数。

sheetViewStartColumn:左上角可视行的行数

sheetViewStartRow:左上角可视列的列数

offsetX:左上角可视第一个格被滚动的距离X

offsetY:左上角可视第一个格被滚动的距离Y

image.png

例如上图滚动后,则上面数据都是相对于B3格子。sheetViewStartColumn为B3的行,sheetViewStartRow为B3的列,offsetX为B3的x被遮住的部分,offsetY为B3的y被遮住的部分

同时,知道了sheetViewStartColumn,和sheetViewStartRow,就可以知道前面还有多少行多少列。就可以计算出前面所有行和列的距离。

2.获取鼠标位置

image.png

        <button @dragend="inserDataWithDrag" draggable="true">
          客户名称(可拖拽)
        </button>

下面就是全部核心代码 写满注释了。

前面几个常数在我的demo页面内,是上面图片的这样一个关系,可以根据自己的调整

/**
 * @description 拖拽字段到单元格内
 * @param {*} event
 */
const inserDataWithDrag = (event) => {
  const canvasLeft = 45 // 行数字宽度
  const pageLeft = 250 // 左侧字段区域宽带
  const canvasTop = 20 // 列字母高度
  const canvasTool = 32 // 工具条高度
  const canvasInput = 28 // 输入框高度
  const canvasCellLeft = canvasLeft + pageLeft
  const canvasCellTop = canvasTop + canvasTool + canvasInput
  const mouseX = event.clientX - canvasCellLeft // 鼠标在Excel表格内的相对位置
  const mouseY = event.clientY - canvasCellTop // 鼠标在Excel表格内的相对位置
  if (mouseX < 0 || mouseY < 0) return

  const allData = univerRef.value.getData() // 获取所有的sheet表 -
  const nowSheet = allData.sheets['sheet-01'] // 我暂时手动直接拿第一个表的内容了,需要的自己手动更换
  // Object.entries(allSheets).forEach(([key, value])
  const defaultColumnWidth = nowSheet.defaultColumnWidth // 默认行宽度
  const defaultRowHeight = nowSheet.defaultRowHeight // 默认列高度
  const rowData = nowSheet.rowData // 手动设置过列宽度的行数据
  const columnData = nowSheet.columnData // 手动设置过行高度的列数据
  let canvasScrollXHide = offsetX.value // 操作区间滚动后的偏移量x 滚动后 但滚动距离不超过1列 
  let canvasScrollYHide = offsetY.value // 操作区间滚动后的偏移量y 滚动后 但滚动距离不超过1行
  if (sheetViewStartColumn.value) { // 当页面滚动超过一行 
    const columnLen = new Array(sheetViewStartColumn.value).fill(null)
    const canvasScrollX = columnLen.reduce((acc, currentValue, currentIndex) => {
      if (columnData[currentIndex] && columnData[currentIndex].w) {
        // 如果手动设置过列宽
        return acc + columnData[currentIndex].w
      } else {
        return acc + defaultColumnWidth
      }
    }, 0)
    canvasScrollXHide += canvasScrollX // 拿到最终操作区间滚动后的全部偏移量x
  }
  if (sheetViewStartRow.value) { // 当页面滚动超过一列
    const rowLen = new Array(sheetViewStartRow.value).fill(null)
    const canvasScrollY = rowLen.reduce((acc, currentValue, currentIndex) => {
      if (rowData[currentIndex] && rowData[currentIndex].h) {
        // 如果手动设置过行高
        return acc + rowData[currentIndex].h
      } else {
        return acc + defaultRowHeight
      }
    }, 0)
    canvasScrollYHide += canvasScrollY // 拿到最终操作区间滚动后的全部偏移量y
  }

  // 拿到偏移量 就可以知道当前鼠标对于canvas的起点,0,0的位置
  const moseInCanvasX = canvasScrollXHide + mouseX // 得到鼠标相对于0,0位置的偏移量
  const moseInCanvasY = canvasScrollYHide + mouseY // 得到鼠标相对于0,0位置的偏移量

  console.log('鼠标位置:', mouseX, mouseY)
  console.log('鼠标在canvas内相对于起始0,0的位置:', moseInCanvasX, moseInCanvasY)

  // 计算鼠标在canvas内相对于起始0,0的位置在哪个单元格 获取行
  const getDragColumn = (moseInCanvasX, defaultColumnWidth) => {
    let count = 0
    let currentValue = 0

    while (currentValue <= moseInCanvasX) {
      if (columnData[count] && columnData[count].w) {
        // 如果下一列有设置过宽度 需要加上设置过的宽度
        currentValue += columnData[count].w
      } else {
        currentValue += defaultColumnWidth
      }
      count++
    }
    return count - 1 // 减去最后一次操作
  }

  // 计算鼠标在canvas内相对于起始0,0的位置在哪个单元格 获取列
  const getDragRow = (moseInCanvasY, defaultRowHeight) => {
    let count = 0
    let currentValue = 0

    while (currentValue <= moseInCanvasY) {
      if (rowData[count] && rowData[count].h) {
        // 如果下一行有设置过高度 需要加上设置过的高度
        currentValue += rowData[count].h
      } else {
        currentValue += defaultRowHeight
      }
      count++
    }
    return count - 1 // 减去最后一次操作
  }

  const column = getDragColumn(+moseInCanvasX, +defaultColumnWidth)
  const row = getDragRow(+moseInCanvasY, +defaultRowHeight)
  console.log('鼠标所在的位置列:', column)
  console.log('鼠标所在的位置行:', row)
}

已得到鼠标所在行列,赋值即可

在上面代码最后添加如下代码

  ...
  ...
  ...
  ...
  const column = getDragColumn(+moseInCanvasX, +defaultColumnWidth)
  const row = getDragRow(+moseInCanvasY, +defaultRowHeight)
  console.log('鼠标所在的位置列:', column)
  console.log('鼠标所在的位置行:', row)

  univerRef.value.setData({
    pos: [row, column, 1, 1],
    value: '{客户名称}' // 根据自身业务去赋值即可
  })

https://univer.work/zh-cn/guides/facade/sheet/#设置范围数据

上面univerRef.value.setData 是我封装过的赋值方法,本体也是官方api提供的

    setData({ pos, value }) {
      const [col, row, colNum, rowNum] = pos

      const activeSheet = this.univerAPI.getActiveWorkbook().getActiveSheet()

      const range = activeSheet.getRange(col, row, colNum, rowNum)
      range?.setValue(value)
    }

彩蛋:

最后如果想设置拖拽数据后单元格显示高亮:

image.png

https://univer.work/zh-cn/guides/facade/general/#监听命令

同样,通过监听命令api 可以知道canvas内被点击,会触发 命令sheet.operation.set-selections

参照最开的的调试输出params,最终结果是可以通过调用该命令高亮格子

      this.univerAPI.executeCommand('sheet.operation.set-selections', {
        selections: [{ range: { startRow: row, startColumn: column, endRow: row, endColumn: column } }]
      })

相关文章

  • HTML5拖拽drag

    通过拖拽实现页面元素的位置改变 实现拖拽效果 源元素 - 要拖拽的文件 目标元素 - 要拖拽到哪里去 目前实现拖拽...

  • 拖拽API

    实现拖拽效果 目前实现拖拽效果 HTML5拖拽 源元素事件例子 目标元素事件 从本地拖放图片到页面中 实现拖拽

  • HTML5实现拖拽

    实现拖拽效果源元素 - 要拖拽的文件目标元素 - 要拖拽到哪里去 目前实现拖拽效果使用原生DOM就能实现 - 最麻...

  • 原生拖拽,拖放事件(drag and drop)

    拖拽,拖放事件可以通过拖拽实现数据传递,达到良好的交互效果,如:从操作系统拖拽文件实现文件选择,拖拽实现元素布局的...

  • vue,iview遇到的问题(1)

    1 vue draggable 火狐拖拽搜索问题使用vue-draggable做字段拖拽排序,在谷歌浏览器上是没有...

  • 原生js实现拖拽(碰撞检测)

    js实现拖拽

  • html5实现拖拽效果

    在此之前,实现拖拽操作都是开发人员自定义逻辑实现的,但是HTML5提供了拖拽API ,使得拖拽操作的实现变得简单。...

  • HTML5 拖拽事件

    HTML5 拖拽事件图片自带拖拽功能其他元素也通过设置 draggable=true属性 实现拖拽功能 垃圾(拖拽...

  • js实现拖拽

    ①鼠标按下+鼠标移动 → 拖拽②鼠标松开 → 无拖拽③鼠标偏移 → 拖拽距离 js实现 ① onmousedown...

  • vdesjs实现原理

    拖拽功能实现 vdesjs的拖拽功能使用到了vuedraggble,vuedragable的实现是基于sortab...

网友评论

      本文标题:univer实现字段拖拽

      本文链接:https://www.haomeiwen.com/subject/ihuytjtx.html