RVandersteen RVandersteen - 3 months ago 48
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

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.

Comments