最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue3+TypeScript實現(xiàn)鼠標(biāo)框選功能

 更新時間:2024年07月05日 08:42:39   作者:廣島原子  
這篇文章主要介紹了基于Vue3+TypeScript實現(xiàn)鼠標(biāo)框選功能,文中通過代碼示例給大家講解的非常纖細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下

實現(xiàn)功能:

  • 選擇、取消選擇單個元素、同時選擇多個元素。
  • 鼠標(biāo)懸浮變色。
  • 框選、滾動框選區(qū)域。
  • 同時選擇多個區(qū)域。

最終實現(xiàn)效果

1. HTML代碼

 <div class="right-bottom">
    <<img src="div" alt="" width="70%" />
      class="page"
      ref="pageRef"
      @scroll="handleScroll"
      @mouseup="handleMouseUp"
    >
      <table class="table" @mousemove="handleMouseMove">
        <tr v-for="(row, rowIndex) in tableData" :key="rowIndex">
          <td
            id="td"
            v-for="(col, colIndex) in row"
            :key="colIndex"
            :class="{
              'table-item-active': selectedCells.has(rowIndex + '-' + colIndex),
            }"
            :style="{
              backgroundColor: selectedCells.has(rowIndex + '-' + colIndex)
                ? 'skyblue'
                : col.color,
            }"
            @mousedown.prevent="startSelect(rowIndex, colIndex)"
          >
            <div
              class="table-item"
              :class="{
                'item-hover': hoverPosition == `${rowIndex}-${colIndex}`,
              }"
              @click="handleItemClick(rowIndex, colIndex)"
              @mouseenter="handleMouseEnter(rowIndex, colIndex)"
              @mouseleave="handleMouseLeave(rowIndex, colIndex)"
            >
              {{ col.hole }}
            </div>
          </td>
        </tr>
      </table>
    </div>
  </div>

2. 定義全局變量

// 已選擇的單元格。因為可能出現(xiàn)重復(fù)框選單元格的情況,所以這里最好使用Set類型。
const selectedCells = reactive(new Set([]));
// 矩陣起始坐標(biāo)位置??蜻x矩陣在頁面上的位置,使用時請根據(jù)實際情況計算
let tableStartX = 0;
let tableStartY = 0;
// 單元格寬高
let cellWidth = 63;
let cellHeight = 63;
// 是否按住ctrl
let isClickCtrl = false;
// 當(dāng)前懸浮單元格坐標(biāo)
let hoverPosition = ref('');

3. 實現(xiàn)單個元素選擇、取消選擇、按ctrl同時選擇多個元素

/**
 * @description: 點擊單元格事件
 * @param row 當(dāng)前單元格X坐標(biāo)
 * @param column 當(dāng)前單元格Y坐標(biāo)
 */
const handleItemClick = (row: number, column: number) => {
  // 按下ctrl
  document.onkeydown = (e: KeyboardEvent) => {
    if (e.key === 'Control') isClickCtrl = true;
  };
  // 松開ctrl
  document.onkeyup = (e: KeyboardEvent) => {
    if (e.key === 'Control') isClickCtrl = false;
  };
  // 如果按住ctrl鍵
  if (isClickCtrl) {
    // 點擊了已經(jīng)選中的元素,取消選中; 否則選中
    if (selectedCells.has(`${row}-${column}`)) {
      selectedCells.delete(`${row}-${column}`);
    }else {
     selectedCells.add(`${row}-${column}`);
    }
  }
  // 如果沒有點擊ctrl鍵,則先清空所有選中的元素,然后選中當(dāng)前元素
  else {
    selectedCells.clear();
    selectedCells.add(`${row}-${column}`);
  }
};

4. 鼠標(biāo)懸浮變色

/**
 * @description: 鼠標(biāo)懸浮單元格變色
 * @param row 當(dāng)前單元格X坐標(biāo)
 * @param column 當(dāng)前單元格Y坐標(biāo)
 */
// 鼠標(biāo)進入單元格,使用防抖降低代碼重復(fù)執(zhí)行次數(shù),提高性能
const handleMouseEnter = _.debounce((row: number, column: number) => {
  hoverPosition = `${row}-${column}`;
}, 100);
// 鼠標(biāo)離開單元格
const handleMouseLeave = _.debounce(() => {
  hoverPosition = '';
}, 50);

5. 框選、滾動框選元素功能實現(xiàn)

5.1 獲取框選區(qū)域內(nèi)的所有元素

實現(xiàn)步驟:

  • 拿到起始單元格坐標(biāo)以及結(jié)束單元格坐標(biāo)。
  • 根據(jù)起始結(jié)束坐標(biāo)計算出框選區(qū)域內(nèi)的所有單元格。

實現(xiàn)原理:例1. 如起始坐標(biāo)為 startCell = [0, 0],結(jié)束坐標(biāo) endCell = [2, 2]
則當(dāng)前區(qū)域的元素包括:

0,00,10,2
1,01,11,2
2,02,12,2

例2. 如起始坐標(biāo)為 startCell = [3, 4],結(jié)束坐標(biāo) endCell = [1, 2]
則當(dāng)前區(qū)域的元素包括:

1,21,31,4
2,22,32,4
3,23,33,4

以此類推。。。

結(jié)論: 根據(jù)以上實例可得,我們只需要拿到起止位置X坐標(biāo)和Y坐標(biāo),然后用雙重for循環(huán)即可得到當(dāng)前框選區(qū)域內(nèi)的所有元素

獲取框選區(qū)域內(nèi)的所有元素方法:

/**
 * @description: 根據(jù)起始坐標(biāo)和結(jié)束坐標(biāo),設(shè)置選中區(qū)域
 * @param startX 起始坐標(biāo)x
 * @param startY 起始坐標(biāo)y
 * @param endX 結(jié)束坐標(biāo)x
 * @param endY 結(jié)束坐標(biāo)y
 */
const selectRange = (
  startX: number,
  startY: number,
  endX: number,
  endY: number
) => {
  for (
    let rowIndex = Math.min(startX, endX);
    rowIndex <= Math.max(startX, endX);
    rowIndex++
  ) {
    for (
      let cellIndex = Math.min(startY, endY);
      cellIndex <= Math.max(startY, endY);
      cellIndex++
    ) {
      selectedCells.add(`${rowIndex}-${cellIndex}`);
    }
  }
};

5.2 計算框選結(jié)束坐標(biāo)

實現(xiàn)原理:首先分別計算出鼠標(biāo)距離矩陣原點left距離和top距離,然后再用這個距離除單個單元格的寬高就能得到結(jié)束坐標(biāo)。

如果矩陣框選有滾動操作,只要再加上滾動距離即可。

5.3 鼠標(biāo)移動事件

// 起始單元格坐標(biāo)
let startCell: [number, number] | null = null;
// 鼠標(biāo)點擊事件,設(shè)置起始坐標(biāo)
function startSelect(rowIndex: number, cellIndex: number) {
  startCell = [rowIndex, cellIndex];
}
// 鼠標(biāo)抬起事件,將起始坐標(biāo)設(shè)置為null
const handleMouseUp = () => {
  startCell = null;
};
// 鼠標(biāo)移動事件
const handleMouseMove = (e: MouseEvent) => {
  debounceFun1(e);
};
const debounceFun1 = _.debounce((e: MouseEvent) => {
  // 如果沒有起始坐標(biāo),則不執(zhí)行
  if (!startCell) return;
  // 按下ctrl鍵
  document.onkeydown = (e: KeyboardEvent) => {
    if (e.key === 'Control') isClickCtrl = true;
  };
  // 松開ctrl鍵
  document.onkeyup = (e: KeyboardEvent) => {
    if (e.key === 'Control') isClickCtrl = false;
  };
  endXY.x = e.clientX;
  endXY.y = e.clientY;
  
  // 獲取鼠標(biāo)移動的當(dāng)前單元格坐標(biāo),并設(shè)置為框選結(jié)束坐標(biāo)
  let endCell: [number, number] | null = null;
  endCell = [
    Math.floor((e.clientY  + scrollXY.y - tableStartY) / cellHeight),
    Math.floor((e.clientX  + scrollXY.x - tableStartX) / cellWidth),
  ];
  // 如果鼠標(biāo)位置發(fā)生變化,則清空已選擇的單元格,并重新設(shè)置選中區(qū)域
  if (!isClickCtrl) {
    selectedCells.clear()
  }
  // 根據(jù)起始坐標(biāo)和結(jié)束坐標(biāo),設(shè)置選中區(qū)域
  selectRange(...startCell, ...endCell);
}, 50);

5.4 滾輪滾動事件

const scrollXY = reactive({ x: 0, y: 0 });
const handleScroll = (e: any) => {
  scrollXY.x = e.target.scrollLeft;
  scrollXY.y = e.target.scrollTop;
  if (!startCell) return;
  const endCell: [number, number] = [
    Math.floor((endXY.y + e.target.scrollTop - tableStartY) / cellHeight),
    Math.floor((endXY.x + e.target.scrollLeft - tableStartX) / cellWidth),
  ];
  selectRange(...startCell, ...endCell);
};

6. 樣式相關(guān)代碼

.item-hover {
  background-color: #bae0ff !important;
}
th,
td {
  border: 1px solid black;
  border-collapse: collapse;
}
.right-bottom {
  margin-left: 200px;
  height: 800px;
  width: 800px;
  .page {
    width: 100%;
    height: 100%;
    overflow: scroll;
    margin: 0 auto;
    .table {
      overflow-x: auto;
      overflow-y: auto;
      .table-item {
        position: relative;
        font-size: 13px;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 60px;
        height: 60px;
        .coordinates {
          position: absolute;
          left: 0;
          top: 0;
          font-size: 10px;
        }
      }
      .table-item-active {
        background-color: skyblue;
      }
    }
  }
  .page ::selection {
    background-color: transparent;
  }
}

7. 總結(jié)

實際開發(fā)中,矩陣原點坐標(biāo)可能會因為各種情況發(fā)生改變(這里默認是[0,0]),需要根據(jù)實際情況計算,否則框選區(qū)域會出現(xiàn)錯位的情況。最后希望這個組件能幫助到有需要的人,歡迎大家提出建議!

以上就是基于Vue3+TypeScript實現(xiàn)鼠標(biāo)框選功能的詳細內(nèi)容,更多關(guān)于Vue3 TypeScript鼠標(biāo)框選的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文探索Vue中組件和插件使用細節(jié)與差異

    一文探索Vue中組件和插件使用細節(jié)與差異

    Vue組件和插件是Vue生態(tài)系統(tǒng)中的兩種重要概念,它們分別服務(wù)于不同的目的,但都極大地豐富了Vue的功能性和可擴展性,下面我們就來看看二者的用法以及區(qū)別吧
    2024-03-03
  • vue時間格式化實例代碼

    vue時間格式化實例代碼

    本篇文章主要介紹了vue時間格式化實例代碼,這里整理了詳細的代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Vue.js 十五分鐘入門圖文教程

    Vue.js 十五分鐘入門圖文教程

    不過 Vue 本身含有非常豐富的功能,要用 Vue 搭建完整的應(yīng)用,仍然需要了解大量 Vue 設(shè)計概念和操作技巧。這篇文章主要介紹了Vue.js 十五分鐘入門圖文教程,需要的朋友可以參考下
    2018-09-09
  • vue cli中env的使用指南

    vue cli中env的使用指南

    眾所周知,一個項目在開發(fā)、測試與生產(chǎn)環(huán)境的各種配置變量是不一樣的,但在vue cli 3中通過指令vue create xxx創(chuàng)建的項目取消了默認的 config 和 build 文件夾,這導(dǎo)致剛?cè)胧值男』锇椴恢涝谀膬号渲铆h(huán)境變量,不過官方也提供了相應(yīng)的配置方法,本文就來介紹一下
    2021-08-08
  • 使用element-ui設(shè)置table組件寬度(width)為百分比

    使用element-ui設(shè)置table組件寬度(width)為百分比

    這篇文章主要介紹了使用element-ui設(shè)置table組件寬度(width)為百分比方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼

    Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼

    在 Vue 中,如果需要將按鈕居中顯示,可以使用 CSS 中的 `text-align: center` 屬性來實現(xiàn),本文通過實例代碼給大家介紹Vue 按鈕居中、按鈕居左、按鈕居右的實現(xiàn)代碼,感興趣的朋友一起看看吧
    2023-10-10
  • Webpack和Vite的區(qū)別小結(jié)

    Webpack和Vite的區(qū)別小結(jié)

    本文主要介紹了Webpack和Vite的區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Vue3.0之引入Element-plus ui樣式的兩種方法

    Vue3.0之引入Element-plus ui樣式的兩種方法

    本文主要介紹了Vue3.0之引入Element-plus ui樣式的兩種方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • vue3+vite+vant項目下按需引入vant報錯Failed?to?resolve?import的原因及解決方案

    vue3+vite+vant項目下按需引入vant報錯Failed?to?resolve?import的原因及解決

    這篇文章主要給大家介紹了關(guān)于vue3+vite+vant項目下按需引入vant報錯Failed?to?resolve?import的原因及解決方案,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • 在Vue中實現(xiàn)圖表數(shù)據(jù)的動態(tài)展示的示例代碼

    在Vue中實現(xiàn)圖表數(shù)據(jù)的動態(tài)展示的示例代碼

    隨著數(shù)據(jù)可視化技術(shù)的發(fā)展,圖表在前端開發(fā)中扮演著越來越重要的角色,Vue.js 作為一個流行的前端框架,以其靈活性和易用性,成為了實現(xiàn)圖表動態(tài)展示的理想選擇,在這篇博客中,我們將學(xué)習(xí)如何在 Vue 3 中實現(xiàn)動態(tài)展示圖表數(shù)據(jù),需要的朋友可以參考下
    2024-11-11

最新評論

昆山市| 长海县| 塔河县| 都安| 六枝特区| 南漳县| 井研县| 调兵山市| 青海省| 岳阳市| 和田县| 九龙县| 乳山市| 剑川县| 湘阴县| 同江市| 姚安县| 上蔡县| 淄博市| 通许县| 平顶山市| 建瓯市| 三门县| 宜黄县| 措美县| 钦州市| 客服| 巴林左旗| 马尔康县| 肇庆市| 淮滨县| 友谊县| 石渠县| 赤水市| 天柱县| 汝州市| 江北区| 揭阳市| 中西区| 平原县| 灵山县|