zyzo / react-dnd-mouse-backend

Mouse Backend for react-dnd library
http://zyzo.github.io/react-dnd-mouse-backend/
MIT License
85 stars 30 forks source link

Drag Preview not working - how hard to fix? #1

Closed decodeman closed 8 years ago

decodeman commented 8 years ago

Hi, I realize this package may not be official at all, and am here because I'm looking for react-dnd... but for svg elements. I have react-dnd working for HTML elements, but my understanding is now that HTML5 backend doesn't work for svg.

This mouse backend package does the basic job it seems (at least for my simple thus far) - thanks! But, no drag preview displays unfortunately (not for html nor svg elements). My question is how hard do you think it would be for one of us to fix this up to support drag preview?

I'm ignorant of the mousemove details it would take to hook this mouse backend lib to react-dnd standards, but could look into it if needed. For now, I assume it wouldn't be too difficult to eventually get that working in this backend - do you agree?

Thanks!

Here is my basic render code, which does not produce a drag preview (same code with Html5 backend and Html elements works fine). Note react-dnd collecting function, etc. are omitted.

return connectDragPreview(connectDragSource(<g id='Piece'> <circle className={'piece piece-'+pawn.owner} cx={originX-50+idx%5*25} cy={originY+Math.floor(idx/5)*25}/> <text className={'pieceName pieceName-'+pawn.owner} x={originX-75+idx%5*25} y={originY+Math.floor(idx/5)*25}>{ant.id}</text> </g>));

Note: When adding connectDragPreview(...), I had to firstly get around errors by changing misspelling in lib\MouseBackend.js 'sourcePreviewNodeOptions' to 'sourcePreviewNodesOptions'.

So just no drag preview of anything shows up (even though drag and drop work fine). No errors in console. Looking at lib\MouseBackend.js, I don't see where sourcePreviewNodes is really being utilized, and am not sure what to do with it. I assume this is lightweight/pending/unofficial and thus not complete, but wanted to check the author's thoughts on feasibility of one of us adding drag preview support. Thanks again.

zyzo commented 8 years ago

Hi @decodeman sorry for the late reply.

Unlike HTML5 drag and drop which provides drag preview out of the box, there is no such thing with this mouse backend. You need to implement a DragLayer yourself. That's what I did with my project:

import React from 'react'
import { DragLayer } from 'react-dnd'

const defaultStyle = (item, currentOffset) => (
  {
    left: item.left + currentOffset.x,
    top: item.top + currentOffset.y,
    position: 'fixed'
  }
)

const DragPreview = React.createClass({
  render() {
    const {
      isDragging,
      currentOffset,
      item
    } = this.props
    return !isDragging || !currentOffset ?
      null
    :
      <div style={defaultStyle(item, currentOffset)}>Dragging</div>

  }
})

const collect = (monitor) => (
  {
    item: monitor.getItem(),
    itemType: monitor.getItemType(),
    currentOffset: monitor.getSourceClientOffset(),
    isDragging: monitor.isDragging()
  }
)

export default DragLayer(collect)(DragPreview)

Internal drag preview support seems like a nice addition to this library. I just don't know if it's possible to do. So feel free to send a pr :).

anatoliyarkhipov commented 8 years ago

Hi, @zyzo! Could you tell me please, at what step do you add the left and top properties into the item?

zyzo commented 8 years ago

@anatoliyarkhipov it is done with the defaultStyle function:

const defaultStyle = (item, currentOffset) => (
  {
    left: item.left + currentOffset.x,
    top: item.top + currentOffset.y,
    position: 'fixed'
  }
)
anatoliyarkhipov commented 8 years ago

Thanks for the answer, @zyzo! But I asked where did you get item.left and item.top used in this function?

zyzo commented 8 years ago

Oic, silly me XD. The value of monitor.getItem() is given by the drag source as the return value of beginDrag:

const source = {
  const beginDrag = (props, monitor, component) => {
    const domNode = ReactDOM.findDOMNode(component)
    return {
      left: domNode.left,
      top: domNode.top
    }
  }
}

[...]

const DraggableObject = DragSource(itemType, source, collect)(Object)

This is only necessary when you need to compute future values based on initial position. In most of the cases, monitor.getSourceClientOffset() should be more than enough.

anatoliyarkhipov commented 8 years ago

Oh, now I got it, I didn't know that the library passes the source component as third arguments. Thanks for the example!

bflannery commented 6 years ago

@zyzo would it possible to share a link to your project which uses the drag preview?

zyzo commented 6 years ago

Yes ofc. Added it here https://github.com/zyzo/react-dnd-mouse-backend/tree/master/example/src/WithDragPreview

zyzo commented 6 years ago

To run the example locally https://github.com/zyzo/react-dnd-mouse-backend#playground