draggable-vue-directive icon indicating copy to clipboard operation
draggable-vue-directive copied to clipboard

On scroll element also moves up and down?So can this feature not be used in a long page?

Open ashutosh1807 opened this issue 6 years ago • 14 comments

ashutosh1807 avatar Jun 29 '18 10:06 ashutosh1807

By element I mean draggable element

ashutosh1807 avatar Jun 29 '18 11:06 ashutosh1807

Please provide explanation, example and screenshot

IsraelZablianov avatar Jun 29 '18 11:06 IsraelZablianov

See my draggable component gets attached to screen and remains there only as I scroll through the page ...for eg if I have element at centre of screen then it remains there only ..it doesn't get attached to page

ashutosh1807 avatar Jun 29 '18 11:06 ashutosh1807

Currently you can't. We are working on it

IsraelZablianov avatar Jun 29 '18 12:06 IsraelZablianov

The problem is actual for me too Very sad...

@ashutosh1807 Are you fix this for you? Or what the alternative of yours solution?

lgXenos avatar Aug 22 '18 10:08 lgXenos

I was about to open this very issue, when I found that someone else ran into the same problem.


Source of this issue

The issue is with line 163 in draggable.ts, where the element’s position is set to fixed.

Recommendation

  • This line of code should probably replace fixed with absolute. I think most web developers assume this would be the default kind of positioning for draggable-type functionality.

  • Perhaps an arg parameter for the directive’s binding could allow client code to “opt-in” to the current behavior (via something like v-draggable:fixed) to declare a component should have the current “scroll-ignoring” positioning.

Zearin avatar Nov 16 '18 17:11 Zearin

FYI, onPositionChange event also can be a workaround before the code itself isn't changed.

I'm using the directive like v-draggable='draggables' and then the data and event parameter would become:

data() {
    return {
        draggables: {
            onPositionChange: this.onPosChanged
        }
    };
},
methods: {
    onPosChanged: function(positionDiff, absolutePosition, event) {
        if(event.target.closest("[draggable-state]")){
            event.target.closest("[draggable-state]").style.position = "absolute";            
        }
    }
},

tpaksu avatar Mar 28 '19 08:03 tpaksu

Or better;

[draggable-state]{
    position: absolute !important;
}

tpaksu avatar Mar 28 '19 10:03 tpaksu

Hi guys, first of all thanks for your ideas, they are always welcomed.

I already started to work about the solution, 'absolute' positioning is problematic with bounding-rectangle feature.

IsraelZablianov avatar Mar 29 '19 14:03 IsraelZablianov

When can solve this issues?

lita-jerry avatar Apr 24 '19 06:04 lita-jerry

it will take a while

IsraelZablianov avatar Apr 24 '19 19:04 IsraelZablianov

@IsraelZablianov I congratulate you on the pack you created. Please fix this function.

MalkSof avatar Oct 30 '19 21:10 MalkSof

I've ended with a solution without modifying the directive, assuming multiple boxes to drag, bounding to a container.

1) Set each box a class

.drag-box {
  position: absolute !important;
}
  1. Each box's initialPosition is set relative to container, e.g. { left: 0, top: 0 }

  2. in onDragStart, change the box's position to 'fixed' and make sure top & left are wrt to the viewport

    onDragStart: function(positionDiff, absolutePosition, event) {
      let box = event && event.target && event.target.closest('[draggable-state]')
      if (box) {
        // Get the model
        const id = box.id
        let found = this.boxes.find(b => b.id === id)

        if (found && !found.firstTouched) {
          // On the first touch, the directive's initialPosition, startDragPosition, currentDragPosition needs to be set wrt to the viewport
          const container = this.$refs.container.getBoundingClientRect()
          const top = absolutePosition.top + container.top
          const left = absolutePosition.left + container.left
          box.style.top = top + 'px'
          box.style.left = left + 'px'

          let draggableState = JSON.parse(box.getAttribute('draggable-state')) || {}
          draggableState.initialPosition = { left, top }
          draggableState.startDragPosition = { left, top }
          draggableState.currentDragPosition = { left, top }
          box.setAttribute('draggable-state', JSON.stringify(draggableState))

          // Record in model that the box has been touched
          found.firstTouched = true
        } else {
          box.style.top = absolutePosition.top + 'px'
          box.style.left = absolutePosition.left + 'px'
        }
        // Remove the class
        box.classList.remove('drag-box')
      }
    }
  1. in onDragEnd, change the box's position to 'absolute' and make sure top & left are wrt to the container
    onDragEnd: function(positionDiff, absolutePosition, event) {
      let box = event && event.target && event.target.closest('[draggable-state]')
      if (box) {
        const container = this.$refs.container.getBoundingClientRect()
        const top = absolutePosition.top - container.top
        const left = absolutePosition.left - container.left
        box.style.top = top + 'px'
        box.style.left = left + 'px'

        // Add the class again
        box.classList.add('drag-box')
      }
    }

Clan-Utility avatar Feb 18 '20 15:02 Clan-Utility

A remaining problem is if the page scrolled, the directive's initialPosition, startDragPosition, currentDragPosition are not updated and the first touch of the box will suddenly move the box to somewhere else. But after the first touch, everything is fine again.

Clan-Utility avatar Feb 18 '20 15:02 Clan-Utility