Tauri V2中如何获取拖拽事件下鼠标指向的元素?
问题描述
希望实现从系统文件资源管理器拖拽文件到页面元素并设置其值的功能。目前在Tauri V2中,采用的方式是获取作为“放置目标”的元素的DOMRect,再判断Tauri的onDragDropEvent是否发生在该矩形范围内,极简示例代码如下:
<script lang="ts"> import { onMount } from "svelte"; let container: HTMLElement; let rects: DOMRect[] = []; let highlighted: number[] = []; let x = 0; let y = 0; function getInputRects(): DOMRect[] { if (!container) return []; const inputs = container.querySelectorAll('input'); return Array.from(inputs).map(input => input.getBoundingClientRect()); } function isPointInRect(x: number, y: number, rect: DOMRect): boolean { return ( x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom ); } function handleDragOver(event: DragEvent) { event.preventDefault(); // Necessary to allow drop rects = getInputRects(); x = event.clientX; y = event.clientY; highlighted = []; rects.forEach((rect, i) => { if (isPointInRect(x, y, rect)) { highlighted.push(i); } }); } function handleDrop(event: DragEvent) { event.preventDefault(); highlighted = []; } onMount(() => { rects = getInputRects(); }); </script> <div bind:this={container} on:dragover={handleDragOver} on:drop={handleDrop} class="drop-area" > {#each Array(5) as _, i} <div class="row"> <input class:highlighted={highlighted.includes(i)} placeholder="Drop something over me" /> </div> {/each} </div> <p>X: {x}, Y: {y}</p> <p>Over Inputs: {JSON.stringify(highlighted)}</p> <style> .drop-area { padding: 20px; border: 2px dashed gray; } .row { margin: 10px 0; } input { width: 300px; padding: 5px; font-size: 14px; } .highlighted { border: 2px solid green; background: #eaffea; } </style>
现咨询:是否存在更符合规范的方式获取拖拽事件中鼠标指向的元素,或是Tauri是否有内置方法实现此类操作?
解决方案
1. 用原生DOM API替代手动矩形判断
不需要手动计算DOMRect并判断点是否在矩形内,原生DOM提供了document.elementFromPoint(x, y)方法,可以直接获取指定坐标位置最顶层的元素,这是更符合规范的实现方式。
优化后的核心逻辑示例:
function handleDragOver(event: DragEvent) { event.preventDefault(); x = event.clientX; y = event.clientY; // 清除之前的高亮 highlighted = []; // 获取当前鼠标位置的元素 const targetElement = document.elementFromPoint(x, y); if (targetElement instanceof HTMLInputElement && container.contains(targetElement)) { // 找到该input在列表中的索引 const inputs = Array.from(container.querySelectorAll('input')); const index = inputs.indexOf(targetElement); if (index !== -1) { highlighted.push(index); } } }
这个方法不需要维护rects数组,逻辑更简洁,也避免了元素位置变化(如滚动、布局更新)导致Rect失效的问题。
2. Tauri V2的拖拽事件配合原生方法
Tauri V2本身没有专门提供“直接获取拖拽目标元素”的内置API,但可以结合Tauri的onDragDrop事件和原生DOM方法实现完整功能:
- 首先确保在
tauri.conf.json中开启拖拽权限:
{ "tauri": { "allowlist": { "window": { "dragDrop": true } } } }
- 监听Tauri的拖拽事件来获取文件信息,同时用原生方法定位目标元素:
import { window } from '@tauri-apps/api'; onMount(() => { window.onDragDropEvent((event) => { if (event.type === 'drop') { const { x, y } = event.position; const targetElement = document.elementFromPoint(x, y); if (targetElement instanceof HTMLInputElement) { // 设置文件路径到input targetElement.value = event.files[0].path; } } }); });
这种方式可以直接拿到系统拖拽的文件路径,同时精准定位到目标输入框,完成赋值操作。
内容的提问来源于stack exchange,提问作者ANimator120
相关产品推荐
相关产品推荐

