RVandersteen
RVandersteen

Reputation: 2137

Ionic, draggable item inside ion-scroll

In my ionic project, I put some icons overlaying an image inside a ionic-scroll directive. Using x,y coordinates and putting the icons position to absolute (relative to the ionic scroll). Placing the icons works great.

Now I would like to be able to drag those icons around inside the ionic scroll.

I use on-touch and on-release to freeze the scroll and on-drag to get the drag event.

Now the problem I have is that the $event from the on-drag method only gives me x / y coordinates in relation to the window / document.

I can't seem to figure out a way to get the correct x,y coordinates relative to the parent (ionic-scroll):

The HTML looks like this:

<ion-scroll zooming="true" direction="xy">
    <img >
    <my-icon 
      on-touch="vm.stopIonicScroll()" 
      on-release="vm.startIonicScroll()" 
      on-drag="vm.dragging($event, vm.start)">
    </my-icont>
</ion-scroll>

And my controller

vm.stopIonicScroll = function() {
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingY = false;
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingX = false;
};

vm.startIonicScroll = function() {
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingY = true;
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingX = true;
};

vm.dragging = function($event, element) {
    console.log($event);
};

Once I start dragging the element I get the event call correctly:

e.g. of such and $event:

{
  "gesture": {
    "center": {
      "pageX": 609,
      "pageY": 363
    },
    "timeStamp": 1438260728495,
    "target": {

    },
    "touches": {
      "0": {
        "target": {

        },
        "identifier": 3284571703,
        "clientX": 609,
        "clientY": 363,
        "pageX": 609,
        "pageY": 363,
        "screenX": 609,
        "screenY": 363
      },
      "length": 1
    },
    "eventType": "move",
    "pointerType": "touch",
    "srcEvent": {
      "touches": {
        "0": {
          "target": {

          },
          "identifier": 3284571703,
          "clientX": 609,
          "clientY": 363,
          "pageX": 609,
          "pageY": 363,
          "screenX": 609,
          "screenY": 363
        },
        "length": 1
      },
      "targetTouches": {
        "0": {
          "target": {

          },
          "identifier": 3284571703,
          "clientX": 609,
          "clientY": 363,
          "pageX": 609,
          "pageY": 363,
          "screenX": 609,
          "screenY": 363
        },
        "length": 1
      },
      "changedTouches": {
        "0": {
          "target": {

          },
          "identifier": 3284571703,
          "clientX": 609,
          "clientY": 363,
          "pageX": 609,
          "pageY": 363,
          "screenX": 609,
          "screenY": 363
        },
        "length": 1
      },
      "scale": 1,
      "rotation": 0,
      "ctrlKey": false,
      "shiftKey": false,
      "altKey": false,
      "metaKey": false
    },
    "deltaTime": 19992,
    "deltaX": 252.05572809,
    "deltaY": 139.527864045,
    "velocityX": 0.012607829536315,
    "velocityY": 0.0069791848762005,
    "distance": 288.09740524333,
    "angle": 28.967141193712,
    "direction": "right",
    "scale": 1,
    "rotation": 0,
    "startEvent": {
      "center": {
        "pageX": 356.94427191,
        "pageY": 223.472135955
      },
      "timeStamp": 1438260708503,
      "target": {

      },
      "touches": [
        {
          "target": {

          },
          "identifier": 3284571702,
          "clientX": 348,
          "clientY": 219,
          "pageX": 348,
          "pageY": 219,
          "screenX": 348,
          "screenY": 219
        }
      ],
      "eventType": "start",
      "pointerType": "touch",
      "srcEvent": {
        "touches": {
          "0": {
            "target": {

            },
            "identifier": 3284571702,
            "clientX": 1022,
            "clientY": 710,
            "pageX": 1022,
            "pageY": 710,
            "screenX": 1022,
            "screenY": 710
          },
          "length": 1
        },
        "targetTouches": {
          "0": {
            "target": {

            },
            "identifier": 3284571702,
            "clientX": 1022,
            "clientY": 710,
            "pageX": 1022,
            "pageY": 710,
            "screenX": 1022,
            "screenY": 710
          },
          "length": 1
        },
        "changedTouches": {
          "0": {
            "target": {

            },
            "identifier": 3284571702,
            "clientX": 1022,
            "clientY": 710,
            "pageX": 1022,
            "pageY": 710,
            "screenX": 1022,
            "screenY": 710
          },
          "length": 1
        },
        "scale": 1,
        "rotation": 0,
        "ctrlKey": false,
        "shiftKey": false,
        "altKey": false,
        "metaKey": false,
        "isTapHandled": true
      }
    }
  }
}

Now every x / y I get in this event is relative to the window / document.

With ng-click you can get the offsetX / offsetY (relative to parent).

How could I manage this with on-drag ?

Upvotes: 1

Views: 2042

Answers (2)

Jonas Schmidt
Jonas Schmidt

Reputation: 1

I just want so add a cleaner way of preventing the scroll-pane to scroll:

$ionicScrollDelegate.$getByHandle('plan').freezeScroll(boolean: shouldFreeze)

I had the very same problem for two days and just did not get why dragging did not work. You helped me a lot. I forgot about the zoomfactor :) Not using Math.round increases accuracy and, in my case makes the operation more failsafe.

Upvotes: 0

RVandersteen
RVandersteen

Reputation: 2137

I found a solution after a short break:

In case someone faces this problem in the future, here is my solution:

var zoom, currentpos;
vm.stopIonicScroll = function(el) {
    currentpos = {
        x: el.x,
        y: el.y
    };
    zoom = $ionicScrollDelegate.$getByHandle('plan').getScrollView().__zoomLevel;
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingY = false;
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingX = false;
};

vm.startIonicScroll = function() {
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingY = true;
    $ionicScrollDelegate.$getByHandle('plan').getScrollView().options.scrollingX = true;
};

vm.dragging = function($event, element) {
    element.x = currentpos.x + Math.round($event.gesture.deltaX / zoom);
    element.y = currentpos.y + Math.round($event.gesture.deltaY / zoom);
};

To clarify:

On first touch (stopIonicScroll) I put the current position of the element and current zoomlevel of the ionic scroll into a variable.

When I drag the element around, I use the gesture deltaX/Y.

This deltaX / Y is calculated from the start of the drag event (that's why we need to keep the initial position).

The zoomlevel is needed to adjust the 'speed' of movement.

Upvotes: 1

Related Questions