JS multitouch for checking swipes - javascript

I was looking for the solution to find out swipe left and right on mobile browsers and created the lib (below). My questions is: is there a simple way of checking for swipe on android and iOS? Also: can I use mouse events instead?
(function (lib, img, cjs) {
lib.touches = new Array();
(lib.setTouchListeners = function(gFilename) {
document.addEventListener("touchstart", function(event) {
// index to the last touch (always the last in the list)
var index = event.touches.length - 1;
// identifier - unique id of the touch (always the least free number on android but quite large number on iOS)
var iden = event.touches[index].identifier;
// save this touch for later comparison (checking if it moved etc.)
var t = {pageX:event.touches[index].pageX, pageY:event.touches[index].pageY, identifier:event.touches[index].identifier};
lib.touches.push(t);
},false);
document.addEventListener("touchmove", function(event) {
// prevent browser from using touch (move page up and down, resize by pinch)
event.preventDefault();
},false);
document.addEventListener("touchend", function(event) {
var len = event.changedTouches.length;
var iden = 0;
// check all changes although it's always one (but just in case something changes in future)
for(var i = 0; i < len; i++) {
iden = event.changedTouches[i].identifier;
// find that identifier in the saved list
for(var j = 0; j < lib.touches.length; j++) {
if (iden == lib.touches[j].identifier) {
var horizontalMove = event.changedTouches[i].pageX - lib.touches[j].pageX;
var verticalMove = event.changedTouches[i].pageY - lib.touches[j].pageY;
if (Math.abs(horizontalMove) > 50) {
if (horizontalMove > 0) {
console.log('right');
} else {
console.log('left');
}
}
if (Math.abs(verticalMove) > 50) {
if (verticalMove > 0) {
console.log('down');
} else {
console.log('up');
}
}
lib.touches.splice(j, 1);
break;
}
}
}
// event.preventDefault();
},false);
});
})(lib = lib||{}, images = images||{}, createjs = createjs||{});
var lib, images, createjs;

You have something called a GestureOverlay or a GestureDetector which you can use to check swipes.
Here are the sites for the GestureOverlay and GestureDetector:
http://developer.android.com/reference/android/gesture/GestureOverlayView.html
http://developer.android.com/reference/android/view/GestureDetector.html
See my other answer:
https://stackoverflow.com/a/18737199/2767703

Related

Touch end event- getting the touch that actually ended if there's more than one touch

I am writing a mobile movement script for a three JS app, in which if you click the upper part of the screen you rotate the camera, and the lower part you move the character. This works perfectly if you are using only one touch, but as soon as I use the second touch a problem appears:
I can't seem to find a way to use the "end touch" event ONLY for the second touch- I tried using ev.touches[1] or ev.touches[0] but seems like nothing happens. I really need the device to discriminate the touch that actually ended, if it was the first one pressed, or the second one.
This is the code...
var originTouch;
var secondTouch;
var newTouch;
var previousTouch;
document.body.addEventListener('touchstart', (ev) => {
originTouch = ev.touches[0];
secondTouch = ev.touches[1];
console.log(originTouch);
console.log(secondTouch);
})
document.body.addEventListener('touchmove', (ev) => {
if (ev.touches[0])
{
if (ev.touches[0].clientY > window.innerHeight / 2)
{
var deltaY = originTouch.clientY - ev.touches[0].clientY;
var deltaX = originTouch.clientX - ev.touches[0].clientX;
if (deltaY > 0) { isGoingForward = true; isGoingBackward = false;}
if (deltaY < 0) { isGoingBackward = true; isGoingForward = false;}
if (deltaX < 0) { isGoingRight = true; isGoingLeft = false;}
if (deltaX > 0) { isGoingLeft = true; isGoingRight = false;}
}
else
{
if (previousTouch)
{
var movementX = ev.touches[0].pageX - previousTouch.pageX;
var movementY = ev.touches[0].pageY - previousTouch.pageY;
camerina.rotation.y += movementX / 400;
camerina.rotation.x += movementY / 400;
}
previousTouch = ev.touches[0];
}
}
if (ev.touches[1])
{
if (ev.touches[1].clientY < window.innerHeight / 2)
{
if (newTouch)
{
var movementX = ev.touches[1].pageX - newTouch.pageX;
var movementY = ev.touches[1].pageY - newTouch.pageY;
camerina.rotation.y += movementX / 400;
camerina.rotation.x += movementY / 400;
}
newTouch = ev.touches[1];
}
}
})
document.body.addEventListener('touchend', (ev) => {
//this is, of course, ending every touch when the second touch is released.
//but if I use --if (ev.touches[0] or [1])-- nothing happens.
//It feels like I'm not getting a way to find which is the touch that actually ended.
//this has to end only if the first touch ended,
isGoingForward = false;
isGoingBackward = false;
isGoingLeft = false;
isGoingRight = false;
previousTouch = null;
originTouch = null;
//this has to end only if the second touch ended.
newTouch = null;
})

How do I iterate through a loop 1 by 1 removing a classList value each time an event is fired?

I have a function attached to a scroll-down event which adds a class one by one to an array of items. I want to now make a function that does the opposite and attach it to a scroll up event. Any help will be met with great praise!
I made a function that when the scroll up event is fired it removes all the classes from the array, but I want to remove them one by one.
var slide = document.querySelectorAll('div.about-slide');
This is the function im using to add the classes to the elements one by one
function addOnScroll() {
for ( var i = 0; i < slide.length; i++){
if(slide[i].classList.contains('scroll')){
continue;
}else{
slide[i].classList.add('scroll');
break;
}
}
};
This is fired on a scroll up event, it removes all the added class from the code above. But I want it to remove the classes one by one.
function removeOnScroll() {
for ( var i = 0; i < slide.length; i++){
slide[i].classList.remove('scroll')
}
};
The mouse scroll event I'm using.
function onDocumentMouseScroll( event ) {
console.log(event);
if( Date.now() - lastMouseWheelStep > 600 ) {
lastMouseWheelStep = Date.now();
var delta = event.detail || -event.wheelDelta;
if( delta > 0 ) {
navigateNext();
addOnScroll();
moveBackground();
}
else if( delta < 0 ) {
navigatePrev();
removeOnScroll();
}
}
}
So, why not do the opposite of what you do on the scroll down ?
function addOnScroll() {
for (var i = 0; i < slide.length; i++) {
if (slide[i].classList.contains('scroll')) {
continue;
} else {
slide[i].classList.add('scroll');
break;
}
}
};
function removeOnScroll() {
for (var i = slide.length - 1; i >= 0; i--) {
if (!slide[i].classList.contains('scroll')) {
continue;
} else {
slide[i].classList.remove('scroll');
break;
}
}
};
However, to simplify your code you could just do a new selection each time
function addOnScroll() {
var next = document.querySelector('div.about-slide:not(.scroll)');
if (next)
next.classList.add('scroll');
};
function removeOnScroll() {
var all = document.querySelectorAll('div.about-slide.scroll'),
last = all[all.length - 1]
if (last)
last.classList.remove('scroll');
};
You can improve below code and it will help updating class one by one Fiddle.
// For Chrome
window.addEventListener('mousewheel', mouseWheelEvent);
// For Firefox
window.addEventListener('DOMMouseScroll', mouseWheelEvent);
function mouseWheelEvent(e) {
var slide = document.getElementsByClassName("about-slide");
var bScroll = document.documentElement.scrollTop;
for (var i = 0; i < slide.length; i++) {
var sHeight = slide[i].offsetHeight;
var offsets = slide[i].offsetTop;
if (bScroll > offsets && bScroll < offsets + sHeight) {
slide[i].classList.add('scroll');
} else {
slide[i].classList.remove('scroll');
}
}
}

How do I fix these touch events? Events respond if there are 2 fingers but not 1

I am making a simple game of mine mobile-friendly.
The goal is to:
Make character walk if a touchstart event is sensed on right half of screen.
Stop character if a touchend event is sensed on the right half.
Jump the character if a touchend event happens on the left half of the screen.
I have the logic working perfectly for mouse up and down events so I'm pretty sure it's something to do inside the touchstart and end functions.
If two fingers are used as one press it seems to work fine.
If only one finger is used it doesn't work properly: touching anywhere starts the movement but nothing will stop it.
Here is the code for the touch inputs and associated function:
CheckWhichScreenHalf = function(e) {
loc = WindowToCanvas(e.pageX, e.pageY);
onScreenY = loc.y >= 0 && loc.y <= gameCanvas.height;
leftSideX = loc.x >= 0 && loc.x < gameCanvas.width/2;
rightSideX = loc.x > gameCanvas.width/2 && loc.x <= gameCanvas.width;
if (onScreenY && leftSideX){
return 'left';
}
else if (onScreenY && rightSideX){
return 'right';
}
else return 'neither';
};
TouchMove = false;
TouchJump = false;
gameCanvas.ontouchstart = function(e){
if (imagesHaveBeenLoaded) {
e.preventDefault();
for (var i = 0; i < e.touches.length; i++){
var side = CheckWhichScreenHalf(e.touches.item(i));
if (side === 'right'){
TouchMove = true;
}
}
}
}
gameCanvas.ontouchend = function(e){
if (imagesHaveBeenLoaded) {
e.preventDefault();
for (var i = 0; i < e.touches.length; i++){
var side = CheckWhichScreenHalf(e.touches.item(i));
if (side === 'right'){
TouchMove = false;
}
else if (side === 'left'){
playerJumping = true;
}
}
}
}
The game can be played here: http://webstudentwork.com/jgossling/MMWD/mp2/mp2.html

Touch Events not registering for HTML5 Canvas Authoring using Flash CC

I have been having some issues when it comes to authoring HTML 5 Canvas in Flash CC, mostly as a result of the lack of information on writing JavaScript inside Flash.
I have been converting an existing drag and drop .fla into HTML 5 with the hope of making it iOS and Android compatible. It is already functioning with mouse, but I have hit a brick wall on trying to add touch support.
The only way I have been able to even register the touch events is by listening to the entire window, which isn't very useful when I have multiple pieces that I want to move around.
This is what I have so far, all this code is located on the first frame of the main Scene Timeline, and the scene is composed of 5 pieces and 5 targets for those pieces, as well as a pop up task completed box and a reset button.
this.stop();
MainStage = this;//Declare
//*********************
//Actual Drag and Dropping
// Initialize:
var numPieces = 5;//<---------------Place number of pieces HERE---------------
var homePosX = [];
var homePosY = [];
var correctAns = 0;
var isClickableAry = [];
var whoAmI = [];//Declared "Globally" so that I can identify which piece is being grabbed later
for (var i = 0; i < numPieces; i++)
{
var pieceName = "p" + (i + 1);
var piece = this[pieceName];
//This sets the starting position for each piece
homePosX[i+1] = piece.x;//(i+1) is so that Piece names line up with Target names and MC names
homePosY[i+1] = piece.y;
whoAmI[i] = piece;
isClickableAry[i] = 1;//Makes it so each pieces is set as clickable
if( piece ){
piece.name = pieceName;
piece.on("mousedown" || "touchstart", function(evt)
{
evt.preventDefault();
//Debug
console.log(checkPiece(this));
//Rather than adding and removing event listeners, just check to see if piece is clickable
if(isClickableAry[checkPiece(this)] == 1){
this.parent.addChild(this);// Bump to top
this.offset = {x:this.x - evt.stageX, y:this.y - evt.stageY};
//Debug
console.log(piece + "PICKED UP, X " + piece.x + ", Y " + piece.y + " is Clickable? ");
//Set Home Coordinates (Where it was picked up)
homeX = this.x;
homeY = this.y;
}
});
piece.on("touchmove",function(evt)
{
console.log("touch moved! " + touchobj);
evt.preventDefault();
});
piece.on("pressmove", function(evt)
{
if(isClickableAry[checkPiece(this)] == 1){
this.x = evt.stageX + this.offset.x;
this.y = evt.stageY + this.offset.y;
//Mouse Cursor change
document.body.style.cursor='move';
}
});
piece.on("pressup" || "touchend" || "touchcancel", function(evt)
{
var target = this.parent["t"+this.name.substr(1)];
//Reset Cursor
document.body.style.cursor='auto';
if( target && hitTestInRange( target, 60) && isClickableAry[checkPiece(this)] == 1 ){
this.x = target.x;
this.y = target.y;
//If it is correct add one
correctAns++;
//Make that button Unclickable
isClickableAry[checkPiece(this)] = 0;
if(correctAns >= numPieces){
//If they have answered correctly equal to the the number of pieces
MainStage.complete_mc.parent.addChild(MainStage.complete_mc);//Bump to top
MainStage.complete_mc.gotoAndStop(1);
//reset answer counter and make drag pieces and buttons unclickable
correctAns = 0;
//Debug
console.log(correctAns + "CORRECT!";)
}
}else{
//Return to home Coordinates (Where it was on intialization)
if(isClickableAry[checkPiece(this)] == 1){
this.x = homePosX[checkPiece(this)+1];
this.y = homePosY[checkPiece(this)+1];
}
}
});
piece.on("mouseover", function(evt)
{
if(isClickableAry[checkPiece(this)] == 1){
//Makes cursor a pointer finger
document.body.style.cursor='pointer';
}
});
piece.on('mouseout',function(evt)
{
//sets cursor back to normal
document.body.style.cursor='auto';
});
}
}
function hitTestInRange( target, range )
{
if( target.x > stage.mouseX - range &&
target.x < stage.mouseX + range &&
target.y > stage.mouseY - range &&
target.y < stage.mouseY + range )
{
return true;
}
return false;
}
//Check which piece it is
function checkPiece(checkName)
{
for (var i = 0; i < numPieces; i++)
{
if (checkName == whoAmI[i]){
return i;
}
}
}
//Reset Functionality
this.complete_mc.reset_btn.addEventListener("click", resetPos.bind(this));
function resetPos(){
for (var i = 0; i < numPieces; i++)
{
var pieceName = "p" + (i + 1);
var piece = this[pieceName];
correctAns = 0;
//Makes Pieces Grabable again
isClickableAry[i] = 1;
//This returns each piece to their Original Starting Positions
piece.x = homePosX[i+1];
piece.y = homePosY[i+1];
}
}
//Controlling the Pop Up Window, window pops up when user answers everything correctly
this.complete_mc.exitComplete_btn.addEventListener("click", closePopUp.bind(this));
this.complete_mc.exitComplete_btn_alt. addEventListener("click", closePopUp.bind(this));
function closePopUp(){
MainStage.complete_mc.gotoAndStop(0);
}
In my own troubleshooting with other problems that have come up generally the issue has to do with scope of either functions or variables, since when flash exports the files it generates its own .js file and turns all of your movie clips into code and separates the code that you have written by whichever frame you wrote it on.
Any help at all would be appreciated.
EDIT: After a bit more research I think the problem might have something to do with touch events only being able to target separate elements? So it isn't able to grab objects inside the canvas element just the canvas element itself?
Turns out that adding touch support is incredibly easy. All I was missing was one line of code
createjs.Touch.enable(stage);
this makes all the touch events respond as mouse events. and fixed all my issues.

Can i create a javascript carousel which contains a flash file as well as static images?

I was wondering if it's possible to include an swf within a javascript carousel that currently just contains stagic images. What I'm looking to do is include a flash animation within the carousel.
I guess I've got two main questions:
Is it possible to cycle through flash files in the same way as an image?
How would I get the javascript and flash to interact so the flash file would know when it had been selected?
If it helps, here's the js we're using:
$(document).ready(function(){
var $looper = true;
var timer;
var currentSlide = 0;
var cell = 0;
var row = 1;
var hCycles = 0;
var aCycles = 0;
//no. of full cycles
var homecycles = 2;
var aboutcycles = 2;
//aboutSlide speed
var fast = 1200;
var slow = 4000;
//hide homepage slides
$('#slide2').fadeOut(0);
$('#slide3').fadeOut(0);
$('#slide4').fadeOut(0);
$('#slide5').fadeOut(0);
$('#slide6').fadeOut(0);
//hide about slides
$('.a-slide1').fadeOut(0);
$('.a-slide2').fadeOut(0);
$('.a-slide3').fadeOut(0);
$('.a-slide4').fadeOut(0);
$('#slide-c1 .a-slide1').fadeIn(1200);
runSlide(fast);
function runSlide(x) {
if ($('body').is('.about')) {
setTimeout(function() {
aboutSlides();
}, x);
} else {
if ($looper) {
setTimeout(function() {
slideShow();
}, 4000);
}
}
}
function slideShow() {
if ($looper) {
if (currentSlide++ < 6 && hCycles < homecycles) {
$('#slide'+ currentSlide).fadeOut(1200);
if (currentSlide == 6) {
$('#slide1').fadeIn(1200);
$('#slide-wrapper li').removeClass('active');
$('#btn1').addClass('active');
currentSlide = 0;
hCycles = hCycles+1;
} else {
$('#slide'+ (currentSlide+1)).fadeIn(1200);
$('#slide-wrapper li').removeClass('active');
$('#btn'+ (currentSlide+1)).addClass('active');
}
runSlide();
} else {
$looper = false;
}
}
};
$('#slide-wrapper li').each(function(index) {
$('#btn'+(index+1)).click(function(){
$looper = false;
$('.slide').fadeOut(1200);
$('#slide'+ (index+1)).fadeIn(1200);
$('#slide-wrapper li').removeClass('active');
$(this).addClass('active');
});
});
function aboutSlides() {
if (cell++ < 3 && aCycles < aboutcycles) {
if (cell == 3) {
if (row < 3) {
row = row+1;
} else {
row = 1;
aCycles = aCycles+1;
}
var hide = (row-1);
if ((row-1) == 0) {hide = 3}
$('#slide-c1 .a-slide'+ hide).fadeOut(1200);
$('#slide-c1 .a-slide'+row).fadeIn(1200);
cell = 0;
runSlide(fast);
} else {
$('#slide-c'+(cell+1)+' .a-slide'+ (row-1)).fadeOut(1200);
$('#slide-c'+(cell+1)+' .a-slide'+(row)).fadeIn(1200);
if (cell == 2) {
runSlide(slow);
} else {
runSlide(fast);
}
}
} else {
// create the final strip
$('#slide-c3 .a-slide3').fadeOut(1200);
$('#slide-c3 .a-slide4').fadeIn(1200);
}
}
});
Thanks!
There isn't any problem as to whatever content you want to put in your slides. As long as it is valid html, it's valid in a slide. Countless jquery/motools/etc plugins let you specify whatever you want for content.
flash is valid.
But you might want to revert to another revealing method. setting the opacity on a swf from javascript is complex and yields to different results, according to browser and flash version. If your flash file is custom made, then you can create a function that fades it to white for example, and call it from javascript. But from experience, changing the opacity of a swf is calling for trouble.
I don't know if this is relevant enough to be an answer, I wanted to post it as a comment, but there isn't any comment button. Oh well.

Categories

Resources