Double Tap detect distance increase in HammerJS - distance

Im using Hammer JS to detect mobile gestures.
Im having little issue with double tap.
Currently in hammer js double tap is detected if a person taps 2 times where the 1st tap point and 2nd tap point should be the same or near to each other.
Example 1 :
1st tap point = position 0px, 2nd tap point = position 3px
Hammer JS can detect the doubletap event since the 2 points are near to each other. Ive also tested this in my android phone using chrome browser.
Example 2 :
1st tap point = position 0px, 2nd tap point = position 10x
Hammer JS CANNOT detect the double tap event since the 2 points are far to each other.
How do i do it in Hammer JS so it could detect double tap even if the 2 tap points are far to each other.
I want something like this :
mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2, maxDistance : 10 }));
Does anyone know if this is possible in HammerJS?
Thanks in Advance

Increasing posThreshold in the recognizer options should do the trick.
mc.add(new Hammer.Tap({ event: 'doubletap', taps: 2, threshold: 10, posThreshold: 10 }));
See Hammer's tap docs here: http://hammerjs.github.io/recognizer-tap/

Related

How do you apply one action to multiple Sprites in SpriteKit?

If I've got a dude at the top of my screen, and a dude who comes in later at the bottom, and I want them both to move to the left of the screen using my moveToLeftOfScreen action I've created, how do I do that?
If I've got var moveToLeftOfScreen = SKAction.moveTo(CGPoint(x:blhabhla, y:bhlahbla, duration: 3)) that won't allow something to move to the left in a straight line from where it spawns.
Long story short: Can you make a single action that says "Move to the left until you hit the screen, then move back to the right until you hit the screeN" and apply that to things spawning in at different locations at different times and then just apply that action when needed throughout your code instead of writing a different action for every single height.
Contrary to sangony, I would have thought this is very possible, though I may be missing something.
Could you not create a reference to an SKAction that is a sequence of move to X=0 and move to X=size.width? and repeat if forever.
I'm not near my mac so I cant get the syntax perfect in XCode so apologies for any errors. Also this assumes that the scene will create this reference, hence the self.size.width:
let moveLeft = SKAction.moveToX(0, duration: 3)
let moveRight = SKAction.moveToX(self.size.width, duration: 3)
let moveLeftThenRight = SKAction.sequence([moveLeft, moveRight])
let continousMovement = SKAction.repeatActionForever(moveLeftThenRight)
Apply that final action to any node that spawns and you should be ok if I understand you correctly.
There will be an issue with the first movement being slow as it will always take 3 seconds to move to the left regardless of where the node spawns. This can be fixed by getting the fraction of the distance it needs to move and multiplying it by 3:
let firstMovementDuration = (node.position.x / self.size.width) * 3
let firstMoveLeft = SKAction.moveToX(0, duration: firstMovementDuration)
And from there continue with normal movement. There's also the timingMode to consider for more natural movement such as .EaseInEaseOut.

rotary dial - rotation limitation

I am making a vintage phone and got a working starting code where user moves his fingers over a UIImageView numbers and it rotates dial. It then moves it back to original position. See screenshot.
The three problems that I can't seem to figure out are;
How can I restrict user to rotate only in clockwise direction? Currently user can move it in any direction (clockwise and counter clockwise)
How can I detect which number that user selected? Meaning user touched 1 or 3 or 5? I need this info so that I can stop the rotation when that number reaches the bar on the right.
In my current code when I stop the rotation and let go of the circle, it moves back to it's place by moving back counter clockwise. It works well if I select 1,2,3,4 but for any number 5 and up the dial moves clockwise back to its original position. How can I force counter clockwise motion on touchesEnded?
Let’s assume that you’re talking about this gesture:
Source.
Build a single-touch rotation gesture recognizer. After building the gesture recognizer correctly, you can just look at the rotation and see what to do with the rotary pad.
There are several things you’ll consider when building a single-touch rotation gesture recognizer. If you look at UIRotationGestureRecognizer, it uses connection between two touches, backed by two fingers, to derive the current angle, then compares the angle to the previous angle, derived from an earlier touch change event, to see the delta.
Measuring the current angle
It takes two points to form a line and you need a line to know the angle. If you’re working with only one touch, you need an anchor point. There are many ways to send an anchor point to your gesture recognizer, and since you’re likely going to build a custom class, use delegation.
Accumulating rotation counts
If you simply note the angle and send off messages during touch changes, it’ll sometimes work. However, if you’d like to implement hysteresis (e.g. this rotary dial will only rotate once clockwise, then it tightens up), you’ll need to accumulate rotation counts for both clockwise and counter-clockwise directions.
Fortunately, you can assume that a) the touch events will not get dropped too often, and b) simply comparing the current angle against the past angle, seeing if they cross quadrant boundaries, will suffice.
For example:
If the touch moved from the top-left quadrant into the top-right quadrant, add one to the rotation count.
If the touch moved from the top-right quadrant into the top-left quadrant, subtract one from the rotation count.
(Yup, this actually works.)
Emitting the correct, accumulated rotation
If you want to emit rotation information exactly like how UIRotationGestureRecognizer did, there will be four things you’re tracking.
Starting Angle: The angle between a connection from the anchor point to the starting touch, and a connection from the anchor point to a fixed reference point.
Current Angle: The angle between a connection from the anchor point to the current touch, and a connection from the anchor point to a fixed reference point.
Rotation Count: The number of clockwise revolutions derived from continuously comparing the current value of Current Angle against its last value (as talked about in the last section). If the touch is moving counter-clockwise, then this count will go into negative.
You’ll provide Rotation Count * 2_PI + (Current Angle - Starting Angle) as the rotation.
OK, I would take a different approach. First, you want to create a RotaryDial class to encapsulate all of the behavior. Then you can just plug it into any view as you see fit.
To keep things simple I would consider making each number button a movable UIImageView, call it RotaryDialDigit or something like that. You would instantiate and place ten of those.
The dial "frame" would just tag along for the ride as the user moves one of the RotaryDialDigit buttons. It's just an image (unless you want the user to be able to touch it and do something with it.
From there, knowing which button is being held down and limiting its rotation to a given direction as well as stopping at at the bar is fairly easy stuff.
By using a protocol you can then have the RotaryDial instance tell the container when a number has been dialed. To the container RotaryDial would feel like a keypad sending a message every time a button is pressed. You really don't want the container bothering with anything other than completed number selections.
To detect which number is touched, when you create each number you should set the tag value of its UIView. Then when the user touches the number you can detect which UIView object it was by checking that tag value.
For the rotation problem, I'd suggest looking at how you are calculating the angle. At a guess I'd say for numbers greater than 4 (which you discern from the tag) you need to do something like subtract the angle you are currently calculating from 360 degrees (well 2Pi). (But I have a head cold right now so the actual math is escaping me :-) )
Without seeing your code, I assume the numbers are a static image and you are animating the finger holes as they rotate past each number. If so:
Detecting which number: defina a CGRect around each button. When the user taps the screen, check which rectangle contains the tap location.
Controlling rotation direction: as the user drags their finger, comtinuously calculate the angle from the dial stop to the current tap location. If the angle moves in the wrong direction, dont update the position of the finger hole. Note that trig functions return vales from +Pi to -Pi radians. For the digits greater than 5, rather than handle negative angles you will probably want to add 2Pi radians ( or 360 degrees) to the angle.
Rotating wrong way: the digits below 5 are generatting angles in the range of 0 to -Pi. Without seeing code, I suspect adding 2Pi to the angle will correct your rotation direction.
Here is a better dial:
Have fun!

Multitouch swipe gesture

How can I simulate a two-finger left-to-right swipe within a UITextView in UIAutomation?
I've tried this:
var textView = target.frontMostApp().mainWindow().textViews()[0];
textView.dragInsideWithOptions({
touchCount:2,
startOffset:{x:0.2, y:5.80},
endOffset:{x:0.8, y:5.80},
duration:1.5
});
But apparently it is not having any effect. Sometimes it looks like it is doing only one finger gesture even I am passing 2 as the touch count.
One concern is: How UIAutomation knows where place the second touch? I am only specifying the start and end of one touch, not two. Is this correct? Maybe this is the origin of my problem?
Also, I have not very clear the coordinates system of objects. Unless I pass very small values for x, y I usually get warnings: out of bounds. Passing coordinates I would usually pass using Objective-C seem to be way large :(
A very late answer...
I met your problem today, in 2015, and I have the chance to have Apple doc for this function. Wasn't the case in 2012 perhaps...
Apple docs says :
You can use offsets to achieve finer precision in specifying the hitpoint within the rect for the specified element. The offset comprises a pair of x and y values, each ranging from 0.0 to 1.0. These values represent, respectively, relative horizontal and vertical positions within the rect, with {x:0.0, y:0.0} as the top left and {x:1.0, y:1.0} as the bottom right. Thus, {x:0.3, y:0.6} specifies a position just below and to the left of center, and {x:1.0, y:0.5} specifies a position centered vertically at the far right.
This example performs a slow drag within the target element from left edge to right edge, just below the top:
target.dragInsideWithOptions({startOffset:{x:0.0, y:0.1}, endOffset:{x:1.0, y:0.1}, duration:1.5});
So x and y values are relative within the rect you choose.
In your example :
startOffset:{x:0.2, y:5.80}
You begin the swipe from left in the textview at 20% of its length, and y is 5.80 times beyond the border...
It would better work with values as :
startOffset:{x:0.0, y:0.1}, endOffset:{x:0.5, y:0.1}
For my part, I made the two-finger left-to-right swipe work with this code :
target.frontMostApp().mainWindow().dragInsideWithOptions({touchCount:2, startOffset:{x:0.0, y:0.1}, endOffset:{x:0.5, y:0.1}, duration:1});

iPhone/iPad circular intensity gauge control (image included)

I found this interesting interface(starts at 33 seconds http://vimeo.com/22946428 ), and would like to design something similar for my own apps. I'm particularly interested in the circular intensity gauge/knob control as on the attached image.
It has a very futuristic feel to it and should be fairly simple to implement using touchesMoved: gesture recognizer callback.
But in order to not-reinvent the wheel, are there any open source libraries that offer advanced UI capabilities, like the ones in the picture/video?
Update: Answer by Hubert demonstrates how to use single finger motion to rotate the dial. The second part of the puzzle is: how to fill the control with color?
I'm thinking of rotating a background color image, but a part of it has to be cut off or covered with something else to vary from an empty background to full. Maybe the cut out element (about 1 radian) may hide a set of fan-like segments that follow the finger and create an illusion of a continuously increasing or decreasing fill of the gauge. The 6 segments x,y would be continuously animating, positioning them in such a way as to cover only the required fraction of the control.
I dont think you will find that control exactly, but Here are a couple of links to working with and tutorials on rotary controls for iOS:
http://www.raywenderlich.com/9864/how-to-create-a-rotating-wheel-control-with-uikit
http://maniacdev.com/2012/02/tutorial-creating-a-one-figure-rotation-gesture-recognizer-for-a-rotary-knob-control-on-ios/
http://maniacdev.com/2011/12/open-source-libraries-for-easily-adding-rotary-knob-controls-in-your-ios-apps/
Here's an example of a circular progress view. Combined with a one finger rotary control, it creates a similar gauge to the one requested (simply overlay 2 controls on top of each other)
Then link the two controls with the rotation callback:
- (void) rotation: (CGFloat) angle
{
// calculate rotation angle
imageAngle += angle;
if (imageAngle > 360)
imageAngle -= 360;
else if (imageAngle < -360)
imageAngle += 360;
progress = imageAngle/360.0;
}
DACircularProgress view
+
OneFingerRotationGestrureRecognizer

Mouse position not consistent with HTML canvas ondrag

I am trying to drag some shapes in HTML canvas but I am encountering a problem with respect to determining the change in mouse coordinates [dx,dy]
First of all, there is no problem in the coordinates themselves, stored in mousePos as the rollover effects work flawlessly. What I am doing is, upon first entering the shape, saving the mouse coordinates.
pos = {x : mousePos[0] , y : mousePos[1]};
Then, onMotion updates the coordinates everytime the mouse moves as well as recording the current position
dx=mousePos[0]-pos.x;
dy=mousePos[1]-pos.y;
pos = {x : mousePos[0] , y : mousePos[1]};
Then I add the dx and dy values to the shapes coordinates (lets take a simple rectangle as an example)
ctx.fillRect(0+this.dx,0+this.dy,100+this.dx,100+this.dy);
as long as the mouse doesn't move too fast, it works relatively well (not perfect though). If I move the mouse very quickly, without going out of the window, the rectangle does not catch up with the mouse. I can understand if there is a delay catching up to the mouse, but how can the delta values be off? Clearly we know where we started, and even if dozens/hundreds of pixels are skipped in the process, eventually the mouse should stop and the correct delta values should be calculated.
Any help would be greatly appreciated as I have hit a conceptual wall here.
You might try to get e.layerX-Y when the onMotion is fired to get the real position instead of the delta. This way it can't be "off".
To use this, place your shape into a div with style="padding:0px;margin=0px;" , because the position is relative to the parent block.