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 firstdragThe 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/mouseleaveEvent 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 indragenterdragleaveIn the processing;dragenteranddragleaveWill contain child child element trigger response, need to determine true for the corresponding regiondragleaveEvents can be considered to increasedropStackThe 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 getfocus()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)