RVandersteen RVandersteen - 1 year ago 164
AngularJS Question

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
?

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download