background
Simple drag files and pictures to the local system, drag message body text to send (similar to functions in wechat and QQ)
Implement Drag to local system, regardless of the mouse implementation, use Electron startDrag with Browser’s Drag and Drop
startdrag
The Electron API (startDrag) provides the ability to drag and drop files locally to the desktop system
The use case is relatively simple, the main process listens for the event and calls startDrag
// main-process
ipcMain.on('drag-start'.(event) = > {
event.sender.startdrag({
file: 'drag-start.md'.// string | string[]
icon:'icon.png'
})
return true
})
Copy the code
Sub-process IPC Communication main process,
// render.js
await ipcRenderer.invoke('drag-start')
// dragend processing logic
Copy the code
Some questions about StartDrag:
-
Because startDrag is the ability to use V8 provide directly, so it will cover it draggable events, such as event. DataTransfer. SetData () sets of data will be overwritten
-
If you want to listen for a dragend event, you need to notify the child process after event.sender. startDrag to indicate that the drag operation has finished
-
Icon customization is rudimentary and doesn’t use DOM to render translucent images by default like html5 Draggable
-
Startdrag can drag only one file at a time on the Window system
-
The mouse cursor gestures is a plus icon, equivalent to the event. DataTransfer. EffectAllowed = ‘move’
-
The ICONS in Windows and MAC are on the left and right, respectively
HTML5 Drag and Drop
If there is a local file path, use startDrag. Otherwise, html5 draggable is performed by default
// render.js
const filePath = getFilePathSync()
if(filePath) {
// Block the default action
event.preventDefault()
/ / send the IPC
await ipcRenderer.invoke('drag-start')
/* Here you can handle the dragend event logic */
return
} else {
// html5 draggable processing
}
Copy the code
Draggable is introduced
Htm5 draggable event triggers are divided into drag and drop
Drag and drop the target | Events trigger |
---|---|
drag | When a dragable item is being dragged, it fires until the drag ends |
dragstart | Start dragging items firstdrag The trigger |
dragend | The drag operation is complete |
Release the target | Events trigger |
---|---|
dragenter | This event is emitted when an element is dragged into a releasable area |
dragleave | This event is emitted when an element is dragged out of a free area |
dragover | Drag elements into a region that continuously fires this event (once over 100 milliseconds) |
drop | Triggers this event by releasing the drag operation on the release region |
Drag and drop zones
Trigger order: dragstart > drag(continuous trigger) > dragend
Bind the Dragstart event listener to the element
const el = document.querySelector('#target')
el.addEventListener('dragstart'.(e:DragEvent) = > {})
Copy the code
Custom drag and drop images
// Generate a drag image
function applyDragImage(event: DragEvent,class:string, label:string | null) :void {
const dragImage = document.createElement('div')
dragImage.className = class;
dragImage.textContent = label;
if(event.dataTransfer) {
document.body.appendChild(dragImage);
event.dataTransfer.setDragImage(dragImage, -10, -10);
setTimeout(() = > document.body.removeChild(dragImage), 0); }}Copy the code
Whole drag && local text selection drag
On the parent element of the target element, setsdraggable=true
, and listens for the target elementmouseenter/mouseleave
Event that cancels the parent element when entering the current element areadraggable=false
, leaves the target element area and restores the parent elementdraggable=true
// Find the parent element
const parent = document.querySelector('#targetParent');
parent.draggable=true
const el = document.querySelector('#target')
// Enter the target element area
el.addEventListener('mouseenter'.(e:DragEvent) = > {
parent.removeAttribute('draggable')
parent.ondragstart = null
},true)
// Leave the target element area
el.addEventListener('mouseleave'.(e:DragEvent) = > {
parent.draggable = true
})
Copy the code
Drag and drop images onto the system
const TYPE = 'image/png'
const NAME = 'name.png'
const URL = 'https://example.com/img/1.png'
// Non-standard properties supported by Chrome
event.dataTransfer.setData('DownloadURL'.`${TYPE}:${NAME}:${URL}`)
Copy the code
Release area
The target element listens as a free region binding event
<template>
<div @dragenter="handleDragEnterFn @dragleave="handleDragLeaveFn"@dragover.prevent @drop="handleDropFn">/* Subcomponent */</div>
</template>
<script lang="ts">
data() {
return {
dropStack: new Set()}}handleDragEnterFn(e:DragEvent) {
this.dropStack.add(e.target)
}
handleDragLeaveFn(e:DragEvent) {
this.dropStack.delete(e.target)
// The stack is empty, really leaving the current region
if(!this.dropStack.size) {
}
}
handleDropFn(e:DragEvent){}</script>
Copy the code
Matters needing attention:
- Trigger sequence:
dragenter
->dragover
(Lasts, recalculates the trigger every 100 + ms) ->dragleave
->drop
- There are usually some state changes going into the release region and leaving the release region that you can put in
dragenter
和dragleave
In the processing;dragenter
anddragleave
Will contain child child element trigger response, need to determine true for the corresponding regiondragleave
Events can be considered to increasedropStack
The corresponding area of stack storage is in and out. If it is empty, it indicates that it has left the current area. - Drag and drop actions by default can trigger the automatic up and down mouse scrolling behavior (in get
focus()
In the case ofdocument.querySelector('#dropTarget').focus()
summary
For the Electron drag operation, most of it can be realized by Web. A local file (with a local path) that can be dragged to the local system using StartDrag
reference
- Fixing drag and drop in Electron | Fileside
- ‘DownloadURL’ for drag and drop – Web Platform News
- Native File Drag & Drop | Electron (electronjs.org)