chrvadala / react-svg-pan-zoom

:eyes: A React component that adds pan and zoom features to SVG
https://chrvadala.github.io/react-svg-pan-zoom/
MIT License
681 stars 127 forks source link

Add event for ReactSVGPanZoom #122

Open ustimenko-andrew opened 6 years ago

ustimenko-andrew commented 6 years ago

Hi @chrvadala Amazing library But I met a problem, how can I add my custom event/any event which is not exist in doc/ For example I need a ondrop event, how can I add it ?

I want to expand a basic functionality, add a drop event and get a point like we have for click, but for drop item.

nsharma1396 commented 6 years ago

I added the drop functionality initially in one of my applications by adding a 'mouseover' event listener to the window whenever a 'dragstart' event has started (which can be done by setting some prop like isDragging to true on dragstart).

In this way, the mouseover will only trigger when the item being dragged has been dropped so you can drop anything on the svg-area and can create any svg shape on the drop coordinates according to your need. To keep a track of all elements that have been dropped, just keep storing them in your state alongwith their coordinates and eventually you can map them on the pan-zoom svg area.

We can check the for the drop in the following way:

// method to handle drop events
    handleDrop = (ev) => {
    window.removeEventListener("mouseover", this.handleDrop);
    const div = this.panZoomRef.ViewerDOM.getBoundingClientRect();
    // Check if the drop is inside the pan-zoom container
    if(ev.offsetX>div.left
      &&
      ev.offsetX<div.width
      &&
      ev.offsetY>div.top
      &&
      ev.offsetY<div.height) {
        // Perform your drop operations here by storing the drop coordinates from the ev
    }
   // Change your isDragging prop back to false irrespective of whether a drop was successful or not
  }

Another approach I found for drag and drop is using a library like react-dnd where you won't have to deal with the event listeners and you can just get the drop coordinates (provided by react-dnd) when a drop is performed.

P.S: For adjusting your coordinates according to zoom level, you can use the following approach:

    const translationX = this.panZoomRef.getValue().e;
    const translationY = this.panZoomRef.getValue().f;
    const scaleFactor = this.panZoomRef.getValue().a;
    const adjustedCoords = {
        x: ( event.offsetX - translationX) / scaleFactor,
        y: ( event.offsetY - translationY) / scaleFactor,
    }

Hope it helps you.