zenXian / core-plot

Automatically exported from code.google.com/p/core-plot
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

Fully support mouse + trackpad input for user action enabled plot spaces #590

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Currently, when you enable user interaction on a plotspace, core-plot 
automatically supports scrolling a scatterplot within its global ranges. This 
is done by dragging with the mouse.

To make use of other mouse and trackpad input (like swipe gestures, mouse 
wheel) this handling should be extended. Properly handling that is not as 
trivial as it seems, but I have done this for a class already and would like to 
share that code here, so it becomes easier to implement it in core-plot. Note 
that only vertical scrolling is handled in my example code.

For another control in my application (OSX) I implemented scrolling myself for 
all possible devices (trackpad + mouse, including high precision mouse pos, 
swipe, scroll wheel etc.). You might be interested in how I did it to derive a 
solution for core-plot. Implemention handles vertical scrolling only at the 
moment, but it should be easy to add the horizontal case:

- (void)scrollWheel: (NSEvent *)event
{
    switch (event.phase) {
        case NSEventPhaseBegan: // Trackpad with no momentum scrolling. Fingers moved on trackpad.
            offsetAccumulator = scrollOffset;
            // Fall through.
        case NSEventPhaseChanged:
            if (offsetAccumulator >= 0) {
                offsetAccumulator += event.scrollingDeltaY / 5;
            } else {
                offsetAccumulator += event.scrollingDeltaY / 2.0 * exp(offsetAccumulator / 75.0);
            }
            [self setScrollOffset: offsetAccumulator];
            break;

        case NSEventPhaseEnded:
            if (scrollOffset < 0) {
                [self.animator setScrollOffset: 0];
            }
            offsetAccumulator = scrollOffset;
            break;

        case NSEventPhaseNone:
            if (event.momentumPhase == NSEventPhaseNone)
            {
                // Mouse wheel.
                if ([event hasPreciseScrollingDeltas]) {
                    offsetAccumulator += event.scrollingDeltaY;
                    if (offsetAccumulator < 0) {
                        offsetAccumulator = 0;
                    }
                    [self setScrollOffset: offsetAccumulator];

                } else {
                    offsetAccumulator += 10 * event.scrollingDeltaY;
                    if (offsetAccumulator < 0) {
                        offsetAccumulator = 0;
                    }
                    [self.animator setScrollOffset: offsetAccumulator];
                }
            }

            break;
    }

    switch (event.momentumPhase) {
        case NSEventPhaseBegan: // Trackpad with momentum scrolling. User just lifted fingers.
            ignoreMomentumChange = NO;
            offsetAccumulator = scrollOffset;
            break;

        case NSEventPhaseChanged:
            if (!ignoreMomentumChange) {
                if (offsetAccumulator >= -50) {
                    offsetAccumulator += event.scrollingDeltaY / 5;
                    [self setScrollOffset: offsetAccumulator];
                } else {
                    // If we scrolled beyond the acceptable bound ignore any further
                    // (automatically generated) change events and animate back to 0 position.
                    ignoreMomentumChange = YES;
                    offsetAccumulator = 0;
                    [self.animator setScrollOffset: offsetAccumulator];
                }
            }
            break;

        case NSEventPhaseEnded:
            break;
    }
}

scrollOffset is the current offset (0..+infinite) while the offsetAccumulator 
is a temporary offset used during an ongoing scroll operation to get the 
animations smooth. Additionally I create an animation for scrollOffset:

- (id)animationForKey: (NSString *)key
{
    if ([key isEqualToString: @"scrollOffset"]) {
        CABasicAnimation *animation = [CABasicAnimation animation];
        animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut];
        animation.speed = 1;
        return animation;
    } else {
        return [super animationForKey:key];
    }
}

Original issue reported on code.google.com by mike.lischke on 6 Oct 2013 at 9:24

GoogleCodeExporter commented 9 years ago
Especially with momentum scrolling this enhancements becomes essential. It's 
really hard to do momentum scrolling by mouse dragging.

Original comment by mike.lischke on 6 Oct 2013 at 2:02

GoogleCodeExporter commented 9 years ago

Original comment by eskr...@mac.com on 11 Oct 2013 at 12:30

GoogleCodeExporter commented 9 years ago

Original comment by eskr...@mac.com on 16 Nov 2013 at 1:29

GoogleCodeExporter commented 9 years ago
Related to issue #614.

Original comment by eskr...@mac.com on 21 Dec 2013 at 1:03

GoogleCodeExporter commented 9 years ago
Moved to GitHub issue #24.

https://github.com/core-plot/core-plot/issues/24

Original comment by eskr...@mac.com on 30 Dec 2013 at 1:13