Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add callbacks for start, move and end. #61

Open
whoacowboy opened this issue Jan 9, 2019 · 4 comments
Open

Add callbacks for start, move and end. #61

whoacowboy opened this issue Jan 9, 2019 · 4 comments

Comments

@whoacowboy
Copy link
Collaborator

whoacowboy commented Jan 9, 2019

Great library, thank you.

I don't know if I am doing this the right way, but I have been tying into the start and end function of the gestures and it is a bit of a PIA.

it looks like this.

  let pan = new ZingTouch.Pan({numInputs: 1})
  let that = this
  pan.start  = function (inputs) {
	inputs.forEach((input) => {
	  const progress = input.getGestureProgress(this.getId())
	  progress.active = true
	  progress.lastEmitted = {
		x: input.current.x,
		y: input.current.y,
	  }
	})
	that.doThatThing(inputs)
  }
  pan.end = function (inputs) {
	inputs.forEach((input) => {
	  const progress = input.getGestureProgress(this.getId())
	  progress.active = false
	})
	that.doThatOtherThing(inputs)
	return null
  }

I was thinking it would be great to just pass some callbacks. You could do it something like this.
I can make a PR if your interested.

/**
 * @file Pan.js
 * Contains the Pan class
 */

import Gesture from './Gesture.js';
import util from './../core/util.js';

const DEFAULT_INPUTS = 1;
const DEFAULT_MIN_THRESHOLD = 1;

/**
 * A Pan is defined as a normal movement in any direction on a screen.
 * Pan gestures do not track start events and can interact with distance gestures
 * @class Pan
 */
class Pan extends Gesture {
  /**
   * Constructor function for the Pan class.
   * @param {Object} [options] - The options object.
   * @param {Number} [options.numInputs=1] - Number of inputs for the
   *  Pan gesture.
   * @param {Number} [options.threshold=1] - The minimum number of
   * @param {Function} [options.onStart] - The on start callback
   * @param {Function} [options.onMove] - The on move callback
   * @param {Function} [options.onEnd] - The on end callback
   */
  constructor(options) {
    super();

    /**
     * The type of the Gesture.
     * @type {String}
     */
    this.type = 'pan';

    /**
     * The number of inputs to trigger a Pan can be variable,
     * and the maximum number being a factor of the browser.
     * @type {Number}
     */
    this.numInputs = (options && options.numInputs) ?
      options.numInputs : DEFAULT_INPUTS;

    /**
     * The minimum amount in pixels the pan must move until it is fired.
     * @type {Number}
     */
    this.threshold = (options && options.threshold) ?
      options.threshold : DEFAULT_MIN_THRESHOLD;
      
	/**
	 * The on start callback
	 */
    if (options && options.onStart && typeof options.onStart === "function") {
    	this.onStart = options.onStart
    }      
	/**
	 * The on move callback
	 */
    if (options && options.onMove && typeof options.onMove === "function") {
    	this.onMove = options.onMove
    }      
	/**
	 * The on end callback
	 */
    if (options && options.onEnd && typeof options.onEnd === "function") {
    	this.onEnd = options.onEnd
    }
  }

  /**
   * Event hook for the start of a gesture. Marks each input as active,
   * so it can invalidate any end events.
   * @param {Array} inputs
   */
  start(inputs) {
    inputs.forEach((input) => {
      const progress = input.getGestureProgress(this.getId());
      progress.active = true;
      progress.lastEmitted = {
        x: input.current.x,
        y: input.current.y,
      };
    });
    if(this.onStart) {
    	this.onStart(inputs);
    }
  }

  /**
   * move() - Event hook for the move of a gesture.
   * Fired whenever the input length is met, and keeps a boolean flag that
   * the gesture has fired at least once.
   * @param {Array} inputs - The array of Inputs on the screen
   * @param {Object} state - The state object of the current region.
   * @param {Element} element - The element associated to the binding.
   * @return {Object} - Returns the distance in pixels between the two inputs.
   */
  move(inputs, state, element) {
    if (this.numInputs !== inputs.length) return null;

    const output = {
      data: [],
    };

    inputs.forEach( (input, index) => {
      const progress = input.getGestureProgress(this.getId());
      const distanceFromLastEmit = util.distanceBetweenTwoPoints(
        progress.lastEmitted.x,
        progress.lastEmitted.y,
        input.current.x,
        input.current.y
      );
      const reachedThreshold = distanceFromLastEmit >= this.threshold;

      if (progress.active && reachedThreshold) {
        output.data[index] = packData( input, progress );
        progress.lastEmitted.x = input.current.x;
        progress.lastEmitted.y = input.current.y;
      }
    });

    if(this.onMove) {
    	this.onMove(inputs, state, element);
    }
    return output;

    function packData( input, progress ) {
      const distanceFromOrigin = util.distanceBetweenTwoPoints(
        input.initial.x,
        input.current.x,
        input.initial.y,
        input.current.y
      );
      const directionFromOrigin = util.getAngle(
        input.initial.x,
        input.initial.y,
        input.current.x,
        input.current.y
      );
      const currentDirection = util.getAngle(
        progress.lastEmitted.x,
        progress.lastEmitted.y,
        input.current.x,
        input.current.y
      );
      const change = {
        x: input.current.x - progress.lastEmitted.x,
        y: input.current.y - progress.lastEmitted.y,
      };

      return {
        distanceFromOrigin,
        directionFromOrigin,
        currentDirection,
        change,
      };
    }
  }

  /* move*/

  /**
   * end() - Event hook for the end of a gesture. If the gesture has at least
   * fired once, then it ends on the first end event such that any remaining
   * inputs will not trigger the event until all inputs have reached the
   * touchend event. Any touchend->touchstart events that occur before all
   * inputs are fully off the screen should not fire.
   * @param {Array} inputs - The array of Inputs on the screen
   * @return {null} - null if the gesture is not to be emitted,
   *  Object with information otherwise.
   */
  end(inputs) {
    inputs.forEach((input) => {
      const progress = input.getGestureProgress(this.getId());
      progress.active = false;
    });
    return null;
  }

    if(this.onEnd) {
      this.onEnd(onEnd);
    }
  /* end*/
}

export default Pan;

@tryhardest
Copy link

Did you ever do a PR @whoacowboy ? How was your experience with Zing? Did you previously use Interact.js, hammer, quo or anything?

@whoacowboy
Copy link
Collaborator Author

whoacowboy commented Mar 25, 2020

@tryhardest I forked the rep, added the events to the Pan (and some degree stuff that is suspect) which is what I needed, and now I use my forked repo. The library is great, I really like that it tracks multiple touch events. I think the Zing folks have moved on. They said that they opted for another solution and they don't use ZingTouch anymore. When I asked what they opted for they went dark. Pretty much most of my requests have met the same response. I used hammer.js too, but opted to switch to this one because hammer didn't seem like it was being maintained, ha.

here is the forked repo if you are interested.

figurosity/zingtouch

@tryhardest
Copy link

Thanks @whoacowboy yes it does looked unmaintained. We used to use Hammer and Quo back in the day and hammer might not be maintained but still has wide use from the looks of it. But so much has changed past CPL yrs. Ever seen or tinkered with Interact.js our touchy.js? Check them too. I'll check out your fork thanks.

@whoacowboy
Copy link
Collaborator Author

@tryhardest I haven't tried either of those interact.js looks like it actively maintained, bugs are being closed 4 days ago. Touchy looks like it isn't maintained at all. Thanks for the tip, I'll check out interact when i get the chance.

mike-schultz pushed a commit that referenced this issue Apr 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants