I'm building a web app using quo.js to handle touch events.
When the user swipes (drags) with one finger, I can use the following quo.js code to recognise this and apply a css transformation:
$$('element').swipe(function() {
$('element').vendor('transform','translate(-100px,-100px)');
});
Now what I want to do is apply the translate amount based on the amount of swipe. In other words, I need to get the X/Y coordinates of the swipe. Does anyone know if this is possible using quo.js or do I need to use a different js library?
I tried this to get coordinates but it returns 'undefined':
$$('element').swipe(function(e) {
alert(e.pageX);
});
The event object quo.js passes to the callback contains a currentTouch object holding the x and y coordinates: http://jsfiddle.net/marionebl/UupmU/1/
$$('selector').swipe(function(e){
console.log('swipe');
console.log(e.currentTouch); // Gives position when gesture is cancelled
});
Note that the swipe event only fires when a swipe gesture is completed. As far as I understood your use case it would be more convenient to use the swiping event, which fires as soon as a swipe gesture is detected and during all movements until release:
var $swipeable = $$('.swipeable'),
swipeableHeight = $swipeable.height(),
swipeableWidth = $swipeable.width();
$swipeable.swiping(function(e){
var x = e.currentTouch.x - swipeableWidth / 2;
var y = e.currentTouch.y - swipeableHeight / 2;
$swipeable
.vendor('transform', 'translate(' + x +'px,'+ y +'px)');
});
Related
I would like to collect the data from my usb mouse with my OS X Sierra, with javascript / angular js.
Any idea where I can find the inputs ?
I would like to get the bits packets. Precisely, I would like then to calculate position, speed ect... of the cursor.
With some help from https://www.w3schools.com/js/js_events_examples.asp (seriously, this SHOULD have everything you need), you can create a function that calculates the current mouse position and speed.
The event you may have been looking for would be onmousemove. Try giving the window object that property. Your function should be called with an event object too which contains clientX and clientY data, use that to track the current position of the mouse.
Of course, to calculate the mouse speed, we just need to know the difference between the last position it was in, and the current position. So this should work:
var Mx = 0; // Mouse X position
var My = 0; // Mouse Y position
var lastSpeedx = 0; // Last movement by mouse on x axis
var lastSpeedy = 0; // Last movement by mouse on y axis
window.onmousemove = function (e) {
lastSpeedx = e.clientX - Mx; lastSpeedy = e.clientY - My;
Mx = e.clientX; My = e.clientY;
}
Although I hear you want to hear exactly what comes through that usb port, well I'm afraid it's not exactly that simple. Even if javascript has some kind of extension that might do that, it won't be fun to deal with the hundreds of different interfaces mice use to talk to your computer. Drivers are somewhat there to simplify this, then the OS simplifies it further, and by the time it gets to your javascript parser, it would have be quite basic.
I actually to accomplish low level usb input on C++ a couple years back (just for fun) but I just couldn't find what I needed.
I'll look into a direct solution for you, along with an angularjs solution (because I wrote this answer before I saw angularjs tagged), although I'm not sure if there's one as low level as you want it to be.
I trying to figure out, how to create a smooth cursor follow animation with cocos2d js
Here some code:
var listener = cc.EventListener.create({
event: cc.EventListener.MOUSE,
onMouseMove: function (event) {
var str = "MousePosition X: " + event.getLocationX() + " Y:" + event.getLocationY();
var actionBy = cc.MoveTo.create(2, cc.p(event.getLocationX(), $scope.bar._position.y));
$scope.bar.stopAllActions();
$scope.bar.runAction(
cc.sequence(
//cc.rotateTo(2, 0),
actionBy
)
);
// do something...
}});
The problem here, its stuck because the event is fired to often and the "$scope.bar.stopAllActions();" stops the animation.
If I remove the "$scope.bar.stopAllActions();" the animation is driving crazy, the "bar" is flying over the screen.
I just wont the bar follow the mouse cursor, just like the dog follow human
The problem here is that if you remove stopAllActions(); you'd be trying to run an action on an object that's already got an action of the same time. And in either case you are firing an animation too often on an object, I've rarely seen this work as expected.
I'd try running the action directly instead of putting it within a cc.Sequence first, but if that doesn't work, you've got two choices, both rely on manual labor:
a. Simply put the bar on the position of the mouse whenever it moves:
$scope.bar.x = event.getLocationX();
b. Assuming you want to "juice up" the game, just setting the bar on the mouse will be boring, so you could make the bar progressively catch up with the mouse:
In your constant section:
var EASING_CONSTANT = 0.9;
In the event handler:
$scope.bar.x += ($scope.bar.x - event.getLocationX()) * EASING_CONSTANT;
The lower your EASING_CONSTANT the slower the bar'll catch up to the mouse (only use values between 0 and 1).
Now, if you try to use this, you'll realize the bar never quite catches up with your mouse, so you'll have to place this code within an update function (in your main game layer's update method, for example) so it runs each frame.
BUT! Then you won't have access to an event object, so you'll have to end up with something like this:
In the event handler:
$scope.bar.targetX = event.getLocationX();
In the update method:
$scope.bar.x += ($scope.bar.x - $scope.bar.targetX) * EASING_CONSTANT;
There are lots of easing functions you can use, I just gave you the simplest example.
For instance, note that you also have the event.getDeltaX() method that'll return you the difference in position between the last call of the event and the current (how much the mouse moved since the last call of the event). With this you could do something along the lines of:
In your constant section:
var EASING_CONSTANT = 0.9;
var WOBBLING_CONSTANT = 10;
In the event handler:
$scope.bar.targetX = event.getLocationX();
$scope.bar.mouseDeltaX = event.getDeltaX();
In the update method:
$scope.bar.x += ($scope.bar.x - $scope.bar.targetX) * EASING_CONSTANT + Math.cos($scope.bar.mouseDeltaX) * WOBBLING_CONSTANT;
Just get creative and start messing around with the formula until you find a behaviour that "feels" right. But be sure to start simple first!
PS: I'm guessing you want your "bar" to only move on the x-axis, so.. are you making an arkanoid clone? :D
I'm developing in JavaScript for IE10/IE11, and am trying to get custom multi-touch events to work. I'm using the MSGesture API, and it provides a nice abstraction layer, but I would like access to the underlying positions of the touched points. Is there a way to get this?
I guess it could be calculated from the initial offset, using the scale/translation information, but was thinking there would probably be a cleaner way?
Example code:
container.addEventListener("MSGestureChange", function (e) {
// We have access to e.g.
// e.scale / e.translationX / e.translationY
// Now, this is what we need, but it's only for one finger
// (or is it an average somehow?)
// e.offsetX
// e.offsetY
// Is it possible to get offsetX/Y for each finger (pointer)?
}, false);
In my use case, we're allowing a user to define "zones" (polygons) on a map. The basic polygon editing functionality, enabled by just setting editable: true, works well. However, I need some additional functionality.
For example, when the user starts dragging a vertex, I want to highlight nearby vertices on other polygons, and if the user drags over one of them, it will "snap" the lat/lng of the vertex they were dragging to be identical to the vertex the dragged over.
Has anyone successfully inserted some "extra" code into the editing process? Are there any intermediate events being fired on those vertex handles (while dragging, mouse moving, etc.) that I can hook into, interpret, and draw some extra things on the map? What I'm hoping for is someone who can tell me "Oh, if polygon.obfuscatedVariable is set, those are drag handles, and you can listen for mousemove on polygon.obfuscatedVariable[3], retrieve the lat/long, etc."
Hacks and jury-rigged solutions are acceptable: since the built-in editing is so close to what I want, I really don't feel like recreating it from scratch.
I'd since forgotten about this question, but here's our solution to the problem. Hopefully it's helpful!
Short version:
Whenever a mousedown occurs on a shape, check if it's over a vertex, and if it is, use elementFromPoint to save a reference to the actual HTML <div> representing the vertex handle. In subsequent mousemove and mouseup events, you can poll the screen position of this <div> and compare it to the locations of other points on the map.
Long version:
I've yanked out the relevant functions from our application, so you'll need to ignore some of our specific functions and objects etc., but this does show our working "snap-to-point" implementation.
First off, we will be doing pixel-to-lat-lng conversions, so you'll need a simple Overlay defined somewhere (you always need one to do these calculations):
_this.editor.overlay = new g.maps.OverlayView();
_this.editor.overlay.draw = function () {};
_this.editor.overlay.setMap(This.map);
Now, anytime we've initialized a shape on the map, we add a mousedown event handler to it.
g.maps.event.addListener(_this.shape, 'mousedown', function (event) {
if (event.vertex >= 0) {
var pixel = _this.editor.overlay.getProjection().fromLatLngToContainerPixel(_this.shape.getPath().getAt(event.vertex));
var offset = _this.mapElement.offset();
var handle = document.elementFromPoint(pixel.x + offset.left, pixel.y + offset.top);
if (handle) {
_this.dragHandle = $(handle);
_this.snappablePoints = _this.editor.snappablePoints(_this);
} else {
_this.dragHandle = null;
_this.snappablePoints = null;
}
}
});
(You'll notice the call to snappablePoints, which is just an internal utility function that collects all the points that would be valid for this point to snap to. We do it here because it would be an expensive loop to perform on every single mousemove.)
Now, in our shape's mousemove listener, because we've saved a reference to that <div>, we can poll its screen position and compare it to the screen position of other points on the map. If a point is within a certain pixel range (I think ours is 8 pixels), we save it and hover a little icon telling the user we're going to snap.
g.maps.event.addListener(this.shape, 'mousemove', function (event) {
var projection, pixel, pixel2, offset, dist, i;
if (event.vertex >= 0 && this.dragHandle) {
// If dragHandle is set and we're moving over a vertex, we must be dragging an
// editable polygon point.
offset = this.editor.mapElement.offset();
pixel = {
x: this.dragHandle.offset().left - offset.left + this.dragHandle.width() / 2,
y: this.dragHandle.offset().top - offset.top + this.dragHandle.height() / 2
};
// Search through all previously saved snappable points, looking for one within the snap radius.
projection = this.editor.overlay.getProjection();
this.snapToPoint = null;
for(i = 0; i < this.snappablePoints.length; i++) {
pixel2 = projection.fromLatLngToContainerPixel(this.snappablePoints[i]);
dist = (pixel.x - pixel2.x) * (pixel.x - pixel2.x) + (pixel.y - pixel2.y) * (pixel.y - pixel2.y);
if (dist <= SNAP_RADIUS) {
this.snapToPoint = this.snappablePoints[i];
$('#zone-editor #snapping').css('left', pixel.x + 10 + offset.left).css('top', pixel.y - 12 + offset.top).show();
break;
}
}
if (!this.snapToPoint) {
$('#zone-editor #snapping').hide();
}
});
A little cleanup when the user stops moving the mouse:
g.maps.event.addListener(this.shape, 'mouseup', function (event) {
// Immediately clear dragHandle, so that everybody knows we aren't dragging any more.
// We'll let the path updated event deal with any actual snapping or point saving.
_this.dragHandle = null;
$('#zone-editor #snapping').hide();
});
Last, we actually handle the "snapping", which is really just a tiny bit of logic in an event listener on the shape's path.
g.maps.event.addListener(this.shape.getPath(), 'set_at', function (index, element) {
if (this.snapToPoint) {
// The updated point was dragged by the user, and we have a snap-to point.
// Overwrite the recently saved point and let another path update trigger.
var point = this.snapToPoint;
this.snapToPoint = null;
this.shape.getPath().setAt(index, point);
} else {
// Update our internal list of points and hit the server
this.refreshPoints();
this.save();
};
// Clear any junk variables whenever the path is updated
this.dragHandle = null;
this.snapToPoint = null;
this.snappablePoints = null;
});
Fin.
I have an application with many draggable objects that can also be rotated in 90 degree increments. I'm trying to figure out how to stop the user from dragging the objects outside the Raphael paper (canvas).
This is fairly simple for unrotated objects. I can simply see if the current x and y coordinates are less than 0 and set them to 0 instead. I can adjust similarly by checking if they are outside the canvas width and height.
However, a problem arises when the object is rotated because for some odd reason the coordinate plane rotates as well. Is there an easy way to keep objects inside the canvas? Or is there an example of some this somewhere?
I have spent many hours fiddling with this and I can't seem to make sense of the rotated coordinate plane in order to adjust my calculations. Even when debugging the current coordinates, they seem to shift oddly if I drag an object, release it, and then drag the object again.
Any help is greatly appreciated.
Thanks,
Ryan
I had a similar problem, I needed to move a shape within the boundaries of another shape, so what I did was:
element.drag(onstart, onmove, onend);
...
onStart: function(x,y,e){
// Initialize values so it doesn't recalculate per iteration
// this allows to resume dragging from the point it were left
App.oldX = 0;
App.oldY = 0;
App.currentCircleX = App.fingerPath.attr('cx');
App.currentCircleY = App.fingerPath.attr('cy');
},
onMove: function(dx,dy,x,y,e){
App.setDirection(dx,dy);
},
onEnd: function(e){
// nothing to do here for now
},
// this function tells the element to move only if it's within the bound area
setDirection: function(dx, dy){
var isXYinside;
this.newX = this.currentCircleX - (this.oldX - dx);
this.newY = this.currentCircleY - (this.oldY - dy);
// HERE is the key, this method receives your bounding path and evaluates the positions given and then returns true or false
isXYinside = Raphael.isPointInsidePath(this.viewportPath, this.newX, this.newY);
this.oldX = dx;
this.oldY = dy;
// so if it is within the bound area, will move, otherwise will just stay there
if (isXYinside) {
this.fingerPath.attr({
"cx": this.newX,
"cy": this.newY
});
this.currentCircleX = this.newX;
this.currentCircleY = this.newY;
}
}
I know this is an old one, but I stumbled upon this question when trying to figure out a way to do it. So here's my 2 cents in case someone has this problem.
Reference:
Raphael.isPointInsidePath
Have you tried Element.getBBox()
There Are 2 flavones which give the result before rotation and after rotation
You should toggle the Boolean argument and test it